Generate trace functions parameters
[barectf.git] / barectf / cli.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2014 Philippe Proulx <philippe.proulx@efficios.com>
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22 from termcolor import cprint, colored
23 import barectf.templates
24 import pytsdl.parser
25 import pytsdl.tsdl
26 import collections
27 import argparse
28 import sys
29 import os
30 import re
31
32
33 def _perror(msg, exit_code=1):
34 cprint('Error: {}'.format(msg), 'red', attrs=['bold'], file=sys.stderr)
35 sys.exit(exit_code)
36
37
38 def _pinfo(msg):
39 cprint(':: {}'.format(msg), 'blue', attrs=['bold'], file=sys.stderr)
40
41
42 def _parse_args():
43 ap = argparse.ArgumentParser()
44
45 ap.add_argument('-O', '--output', metavar='OUTPUT', action='store',
46 default=os.getcwd(),
47 help='output directory of C files')
48 ap.add_argument('-p', '--prefix', metavar='PREFIX', action='store',
49 default='barectf',
50 help='custom prefix for C function and structure names')
51 ap.add_argument('-s', '--static-inline', action='store_true',
52 help='generate static inline C functions')
53 ap.add_argument('-c', '--manual-clock', action='store_true',
54 help='do not use a clock callback: pass clock value to tracing functions')
55 ap.add_argument('metadata', metavar='METADATA', action='store',
56 help='CTF metadata input file')
57
58 # parse args
59 args = ap.parse_args()
60
61 # validate output directory
62 if not os.path.isdir(args.output):
63 _perror('"{}" is not an existing directory'.format(args.output))
64
65 # validate prefix
66 if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', args.prefix):
67 _perror('"{}" is not a valid C identifier'.format(args.prefix))
68
69 # validate that metadata file exists
70 if not os.path.isfile(args.metadata):
71 _perror('"{}" is not an existing file'.format(args.metadata))
72
73 return args
74
75
76 class _CBlock(list):
77 pass
78
79
80 class _CLine(str):
81 pass
82
83
84 class BarectfCodeGenerator:
85 _CTX_AT = 'ctx->at'
86 _CTX_BUF = 'ctx->buf'
87 _CTX_BUF_SIZE = 'ctx->buf_size'
88 _CTX_BUF_AT = '{}[{} >> 3]'.format(_CTX_BUF, _CTX_AT)
89 _CTX_BUF_AT_ADDR = '&{}'.format(_CTX_BUF_AT)
90 _CTX_CALL_CLOCK_CB = 'ctx->clock_cb(ctx->clock_cb_data)'
91
92 _bo_suffixes_map = {
93 pytsdl.tsdl.ByteOrder.BE: 'be',
94 pytsdl.tsdl.ByteOrder.LE: 'le',
95 }
96
97 _tsdl_type_names_map = {
98 pytsdl.tsdl.Integer: 'integer',
99 pytsdl.tsdl.FloatingPoint: 'floating point',
100 pytsdl.tsdl.Enum: 'enumeration',
101 pytsdl.tsdl.String: 'string',
102 pytsdl.tsdl.Array: 'static array',
103 pytsdl.tsdl.Sequence: 'dynamic array',
104 pytsdl.tsdl.Struct: 'structure',
105 }
106
107 def __init__(self):
108 self._parser = pytsdl.parser.Parser()
109 self._obj_size_cb = {
110 pytsdl.tsdl.Struct: self._get_struct_size,
111 pytsdl.tsdl.Integer: self._get_integer_size,
112 pytsdl.tsdl.Enum: self._get_enum_size,
113 pytsdl.tsdl.FloatingPoint: self._get_floating_point_size,
114 pytsdl.tsdl.Array: self._get_array_size,
115 }
116 self._obj_alignment_cb = {
117 pytsdl.tsdl.Struct: self._get_struct_alignment,
118 pytsdl.tsdl.Integer: self._get_integer_alignment,
119 pytsdl.tsdl.Enum: self._get_enum_alignment,
120 pytsdl.tsdl.FloatingPoint: self._get_floating_point_alignment,
121 pytsdl.tsdl.Array: self._get_array_alignment,
122 pytsdl.tsdl.Sequence: self._get_sequence_alignment,
123 pytsdl.tsdl.String: self._get_string_alignment,
124 }
125 self._obj_param_ctype_cb = {
126 pytsdl.tsdl.Struct: lambda obj: 'const void*',
127 pytsdl.tsdl.Integer: self._get_integer_param_ctype,
128 pytsdl.tsdl.Enum: self._get_enum_param_ctype,
129 pytsdl.tsdl.FloatingPoint: self._get_floating_point_param_ctype,
130 pytsdl.tsdl.Array: lambda obj: 'const void*',
131 pytsdl.tsdl.Sequence: lambda obj: 'const void*',
132 pytsdl.tsdl.String: lambda obj: 'const char*',
133 }
134 self._write_field_obj_cb = {
135 pytsdl.tsdl.Struct: self._write_field_struct,
136 pytsdl.tsdl.Integer: self._write_field_integer,
137 pytsdl.tsdl.Enum: self._write_field_enum,
138 pytsdl.tsdl.FloatingPoint: self._write_field_floating_point,
139 pytsdl.tsdl.Array: self._write_field_array,
140 pytsdl.tsdl.Sequence: self._write_field_sequence,
141 pytsdl.tsdl.String: self._write_field_string,
142 }
143
144 # TODO: prettify this function
145 def _validate_struct(self, struct):
146 # just in case we call this with the wrong type
147 if type(struct) is not pytsdl.tsdl.Struct:
148 raise RuntimeError('expecting a struct')
149
150 # make sure inner structures are at least byte-aligned
151 if self._get_obj_alignment(struct) < 8:
152 raise RuntimeError('inner struct must be at least byte-aligned')
153
154 # check each field
155 for fname, ftype in struct.fields.items():
156 if type(ftype) is pytsdl.tsdl.Sequence:
157 raise RuntimeError('field "{}" is a dynamic array (not allowed here)'.format(fname))
158 elif type(ftype) is pytsdl.tsdl.Array:
159 # we need to check every element until we find a terminal one
160 element = ftype.element
161
162 while True:
163 if type(element) is pytsdl.tsdl.Sequence:
164 raise RuntimeError('field "{}" contains a dynamic array (not allowed here)'.format(fname))
165 elif type(element) is pytsdl.tsdl.Variant:
166 raise RuntimeError('field "{}" contains a variant (unsupported)'.format(fname))
167 elif type(element) is pytsdl.tsdl.String:
168 raise RuntimeError('field "{}" contains a string (not allowed here)'.format(fname))
169 elif type(element) is pytsdl.tsdl.Struct:
170 _validate_struct(element)
171 elif type(element) is pytsdl.tsdl.Integer:
172 if self._get_obj_size(element) > 64:
173 raise RuntimeError('integer field "{}" larger than 64-bit'.format(fname))
174 elif type(element) is pytsdl.tsdl.FloatingPoint:
175 if self._get_obj_size(element) > 64:
176 raise RuntimeError('floating point field "{}" larger than 64-bit'.format(fname))
177 elif type(element) is pytsdl.tsdl.Enum:
178 if self._get_obj_size(element) > 64:
179 raise RuntimeError('enum field "{}" larger than 64-bit'.format(fname))
180
181 if type(element) is pytsdl.tsdl.Array:
182 # still an array, continue
183 element = element.element
184 else:
185 # found the terminal element
186 break
187 elif type(ftype) is pytsdl.tsdl.Variant:
188 raise RuntimeError('field "{}" is a variant (unsupported)'.format(fname))
189 elif type(ftype) is pytsdl.tsdl.String:
190 raise RuntimeError('field "{}" is a string (not allowed here)'.format(fname))
191 elif type(ftype) is pytsdl.tsdl.Struct:
192 self._validate_struct(ftype)
193 elif type(ftype) is pytsdl.tsdl.Integer:
194 if self._get_obj_size(ftype) > 64:
195 raise RuntimeError('integer field "{}" larger than 64-bit'.format(fname))
196 elif type(ftype) is pytsdl.tsdl.FloatingPoint:
197 if self._get_obj_size(ftype) > 64:
198 raise RuntimeError('floating point field "{}" larger than 64-bit'.format(fname))
199 elif type(ftype) is pytsdl.tsdl.Enum:
200 if self._get_obj_size(ftype) > 64:
201 raise RuntimeError('enum field "{}" larger than 64-bit'.format(fname))
202
203 def _validate_context_fields(self, struct):
204 if type(struct) is not pytsdl.tsdl.Struct:
205 raise RuntimeError('expecting a struct')
206
207 for fname, ftype in struct.fields.items():
208 if type(ftype) is pytsdl.tsdl.Variant:
209 raise RuntimeError('field "{}" is a variant (unsupported)'.format(fname))
210 elif type(ftype) is pytsdl.tsdl.Struct:
211 # validate inner structure against barectf constraints
212 self._validate_struct(ftype)
213
214 def _validate_integer(self, integer, size=None, align=None,
215 signed=None):
216 if type(integer) is not pytsdl.tsdl.Integer:
217 raise RuntimeError('expected integer')
218
219 if size is not None:
220 if integer.size != size:
221 raise RuntimeError('expected {}-bit integer'.format(size))
222
223 if align is not None:
224 if integer.align != align:
225 raise RuntimeError('expected integer with {}-bit alignment'.format(align))
226
227 if signed is not None:
228 if integer.signed != signed:
229 raise RuntimeError('expected {} integer'.format('signed' if signed else 'unsigned'))
230
231 def _validate_packet_header(self, packet_header):
232 try:
233 self._validate_struct(packet_header)
234 except RuntimeError as e:
235 _perror('packet header: {}'.format(e))
236
237 # magic must be the first field
238 if 'magic' in packet_header.fields:
239 if list(packet_header.fields.keys())[0] != 'magic':
240 _perror('packet header: "magic" must be the first field')
241 else:
242 _perror('packet header: missing "magic" field')
243
244 # magic must be a 32-bit unsigned integer, 32-bit aligned
245 try:
246 self._validate_integer(packet_header['magic'], 32, 32, False)
247 except RuntimeError as e:
248 _perror('packet header: "magic": {}'.format(e))
249
250 # mandatory stream_id
251 if 'stream_id' not in packet_header.fields:
252 _perror('packet header: missing "stream_id" field')
253
254 # stream_id must be an unsigned integer
255 try:
256 self._validate_integer(packet_header['stream_id'], signed=False)
257 except RuntimeError as e:
258 _perror('packet header: "stream_id": {}'.format(e))
259
260 # only magic and stream_id allowed
261 if len(packet_header.fields) != 2:
262 _perror('packet header: only "magic" and "stream_id" fields are allowed')
263
264 def _dot_name_to_str(self, name):
265 return '.'.join(name)
266
267 def _compare_integers(self, int1, int2):
268 if type(int1) is not pytsdl.tsdl.Integer:
269 return False
270
271 if type(int2) is not pytsdl.tsdl.Integer:
272 return False
273
274 size = int1.size == int2.size
275 align = int1.align == int2.align
276 cmap = int1.map == int2.map
277 base = int1.base == int2.base
278 encoding = int1.encoding == int2.encoding
279 signed = int1.signed == int2.signed
280 comps = (size, align, cmap, base, encoding, signed)
281
282 # True means 1 for sum()
283 return sum(comps) == len(comps)
284
285 def _validate_packet_context(self, stream):
286 packet_context = stream.packet_context
287 sid = stream.id
288
289 try:
290 self._validate_struct(packet_context)
291 except RuntimeError as e:
292 _perror('stream {}: packet context: {}'.format(sid, e))
293
294 fields = packet_context.fields
295
296 # if timestamp_begin exists, timestamp_end must exist
297 if 'timestamp_begin' in fields or 'timestamp_end' in fields:
298 if 'timestamp_begin' not in fields or 'timestamp_end' not in fields:
299 _perror('stream {}: packet context: "timestamp_begin" must exist if "timestamp_end" exists'.format(sid))
300 else:
301 # timestamp_begin and timestamp_end must have the same integer
302 # as the event header's timestamp field (should exist by now)
303 timestamp = stream.event_header['timestamp']
304
305 if not self._compare_integers(fields['timestamp_begin'], timestamp):
306 _perror('stream {}: packet context: "timestamp_begin": integer type different from event header\'s "timestamp" field'.format(sid))
307
308 if not self._compare_integers(fields['timestamp_end'], timestamp):
309 _perror('stream {}: packet context: "timestamp_end": integer type different from event header\'s "timestamp" field'.format(sid))
310
311 # content_size must exist and be an unsigned integer
312 if 'content_size' not in fields:
313 _perror('stream {}: packet context: missing "content_size" field'.format(sid))
314
315 try:
316 self._validate_integer(fields['content_size'], 32, 32, False)
317 except:
318 try:
319 self._validate_integer(fields['content_size'], 64, 64, False)
320 except:
321 _perror('stream {}: packet context: "content_size": expecting unsigned 32-bit/64-bit integer'.format(sid))
322
323 # packet_size must exist and be an unsigned integer
324 if 'packet_size' not in fields:
325 _perror('stream {}: packet context: missing "packet_size" field'.format(sid))
326
327 try:
328 self._validate_integer(fields['packet_size'], 32, 32, False)
329 except:
330 try:
331 self._validate_integer(fields['packet_size'], 64, 64, False)
332 except:
333 _perror('stream {}: packet context: "packet_size": expecting unsigned 32-bit/64-bit integer'.format(sid))
334
335 # if cpu_id exists, must be an unsigned integer
336 if 'cpu_id' in fields:
337 try:
338 self._validate_integer(fields['cpu_id'], signed=False)
339 except RuntimeError as e:
340 _perror('stream {}: packet context: "cpu_id": {}'.format(sid, e))
341
342 def _validate_event_header(self, stream):
343 event_header = stream.event_header
344 sid = stream.id
345
346 try:
347 self._validate_struct(event_header)
348 except RuntimeError as e:
349 _perror('stream {}: event header: {}'.format(sid, e))
350
351 fields = event_header.fields
352
353 # id must exist and be an unsigned integer
354 if 'id' not in fields:
355 _perror('stream {}: event header: missing "id" field'.format(sid))
356
357 try:
358 self._validate_integer(fields['id'], signed=False)
359 except RuntimeError as e:
360 _perror('stream {}: "id": {}'.format(sid, format(e)))
361
362
363 # timestamp must exist, be an unsigned integer and be mapped to a valid clock
364 if 'timestamp' not in fields:
365 _perror('stream {}: event header: missing "timestamp" field'.format(sid))
366
367 try:
368 self._validate_integer(fields['timestamp'], signed=False)
369 except RuntimeError as e:
370 _perror('stream {}: event header: "timestamp": {}'.format(sid, format(e)))
371
372 if fields['timestamp'].map is None:
373 _perror('stream {}: event header: "timestamp" must be mapped to a valid clock'.format(sid))
374
375 # id must be the first field, followed by timestamp
376 if list(fields.keys())[0] != 'id':
377 _perror('stream {}: event header: "id" must be the first field'.format(sid))
378
379 if list(fields.keys())[1] != 'timestamp':
380 _perror('stream {}: event header: "timestamp" must be the second field'.format(sid))
381
382 # only id and timestamp and allowed in event header
383 if len(fields) != 2:
384 _perror('stream {}: event header: only "id" and "timestamp" fields are allowed'.format(sid))
385
386 def _validate_stream_event_context(self, stream):
387 stream_event_context = stream.event_context
388 sid = stream.id
389
390 if stream_event_context is None:
391 return
392
393 try:
394 self._validate_context_fields(stream_event_context)
395 except RuntimeError as e:
396 _perror('stream {}: event context: {}'.format(sid, e))
397
398 def _validate_event_context(self, stream, event):
399 event_context = event.context
400 sid = stream.id
401 eid = event.id
402
403 if event_context is None:
404 return
405
406 try:
407 self._validate_context_fields(event_context)
408 except RuntimeError as e:
409 _perror('stream {}: event {}: context: {}'.format(sid, eid, e))
410
411 def _validate_event_fields(self, stream, event):
412 event_fields = event.fields
413 sid = stream.id
414 eid = event.id
415
416 try:
417 self._validate_context_fields(event_fields)
418 except RuntimeError as e:
419 _perror('stream {}: event {}: fields: {}'.format(sid, eid, e))
420
421 def _validate_all_scopes(self):
422 # packet header
423 self._validate_packet_header(self._doc.trace.packet_header)
424
425 # stream stuff
426 for stream in self._doc.streams.values():
427 self._validate_event_header(stream)
428 self._validate_packet_context(stream)
429 self._validate_stream_event_context(stream)
430
431 # event stuff
432 for event in stream.events:
433 self._validate_event_context(stream, event)
434 self._validate_event_fields(stream, event)
435
436 def _validate_metadata(self):
437 self._validate_all_scopes()
438
439 # 3, 4 -> 4
440 # 4, 4 -> 4
441 # 5, 4 -> 8
442 # 6, 4 -> 8
443 # 7, 4 -> 8
444 # 8, 4 -> 8
445 # 9, 4 -> 12
446 def _get_alignment(self, at, align):
447 return (at + align - 1) & -align
448
449 # this converts a tree of offset variables:
450 #
451 # field
452 # a -> 0
453 # b -> 8
454 # other_struct
455 # field -> 16
456 # yeah -> 20
457 # c -> 32
458 # len -> 36
459 #
460 # to a flat dict:
461 #
462 # field_a -> 0
463 # field_b -> 8
464 # field_other_struct_field -> 16
465 # field_other_struct_yeah -> 20
466 # field_c -> 32
467 # len -> 36
468 def _flatten_offvars_tree(self, offvars_tree, prefix=None,
469 offvars=None):
470 if offvars is None:
471 offvars = collections.OrderedDict()
472
473 for name, offset in offvars_tree.items():
474 if prefix is not None:
475 varname = '{}_{}'.format(prefix, name)
476 else:
477 varname = name
478
479 if isinstance(offset, dict):
480 self._flatten_offvars_tree(offset, varname, offvars)
481 else:
482 offvars[varname] = offset
483
484 return offvars
485
486 # returns the size of a struct with _static size_
487 def _get_struct_size(self, struct,
488 offvars_tree=None,
489 base_offset=0):
490 if offvars_tree is None:
491 offvars_tree = collections.OrderedDict()
492
493 offset = 0
494
495 for fname, ftype in struct.fields.items():
496 field_alignment = self._get_obj_alignment(ftype)
497 offset = self._get_alignment(offset, field_alignment)
498
499 if type(ftype) is pytsdl.tsdl.Struct:
500 offvars_tree[fname] = collections.OrderedDict()
501 sz = self._get_struct_size(ftype, offvars_tree[fname],
502 base_offset + offset)
503 else:
504 # only integers may act as sequence lengths
505 if type(ftype) is pytsdl.tsdl.Integer:
506 offvars_tree[fname] = base_offset + offset
507
508 sz = self._get_obj_size(ftype)
509
510 offset += sz
511
512 return offset
513
514 def _get_array_size(self, array):
515 element = array.element
516
517 # effective size of one element includes its alignment after its size
518 size = self._get_obj_size(element)
519 align = self._get_obj_alignment(element)
520
521 return self._get_alignment(size, align) * array.length
522
523 def _get_enum_size(self, enum):
524 return self._get_obj_size(enum.integer)
525
526 def _get_floating_point_size(self, floating_point):
527 return floating_point.exp_dig + floating_point.mant_dig
528
529 def _get_integer_size(self, integer):
530 return integer.size
531
532 def _get_obj_size(self, obj):
533 return self._obj_size_cb[type(obj)](obj)
534
535 def _get_struct_alignment(self, struct):
536 if struct.align is not None:
537 return struct.align
538
539 cur_align = 1
540
541 for fname, ftype in struct.fields.items():
542 cur_align = max(self._get_obj_alignment(ftype), cur_align)
543
544 return cur_align
545
546 def _get_integer_alignment(self, integer):
547 return integer.align
548
549 def _get_floating_point_alignment(self, floating_point):
550 return floating_point.align
551
552 def _get_enum_alignment(self, enum):
553 return self._get_obj_alignment(enum.integer)
554
555 def _get_string_alignment(self, string):
556 return 8
557
558 def _get_array_alignment(self, array):
559 return self._get_obj_alignment(array.element)
560
561 def _get_sequence_alignment(self, sequence):
562 return self._get_obj_alignment(sequence.element)
563
564 def _get_obj_alignment(self, obj):
565 return self._obj_alignment_cb[type(obj)](obj)
566
567 def _name_to_param_name(self, prefix, name):
568 return 'param_{}_{}'.format(prefix, name)
569
570 def _ev_f_name_to_param_name(self, name):
571 return self._name_to_param_name('evf', name)
572
573 def _ev_c_name_to_param_name(self, name):
574 return self._name_to_param_name('evc', name)
575
576 def _ev_sec_name_to_param_name(self, name):
577 return self._name_to_param_name('evsec', name)
578
579 def _ev_h_name_to_param_name(self, name):
580 return self._name_to_param_name('evh', name)
581
582 def _s_pc_name_to_param_name(self, name):
583 return self._name_to_param_name('spc', name)
584
585 def _s_ph_name_to_param_name(self, name):
586 return self._name_to_param_name('sph', name)
587
588 def _get_integer_param_ctype(self, integer):
589 signed = 'u' if not integer.signed else ''
590
591 if integer.size == 8:
592 sz = '8'
593 elif integer.size == 16:
594 sz = '16'
595 elif integer.size == 32:
596 sz = '32'
597 elif integer.size == 64:
598 sz = '64'
599 else:
600 # if the integer is signed and of uncommon size, the sign bit is
601 # at a custom position anyway so we use a 64-bit unsigned
602 signed = 'u'
603
604 if integer.signed:
605 sz = '64'
606 else:
607 if integer.size < 16:
608 sz = '8'
609 elif integer.size < 32:
610 sz = '16'
611 elif integer.size < 64:
612 sz = '32'
613 else:
614 sz = '64'
615
616 return '{}int{}_t'.format(signed, sz)
617
618 def _get_enum_param_ctype(self, enum):
619 return self._get_obj_param_ctype(enum.integer)
620
621 def _get_floating_point_param_ctype(self, fp):
622 if fp.exp_dig == 8 and fp.mant_dig == 24 and fp.align == 32:
623 return 'float'
624 elif fp.exp_dig == 11 and fp.mant_dig == 53 and fp.align == 64:
625 return 'double'
626 else:
627 return 'uint64_t'
628
629 def _get_obj_param_ctype(self, obj):
630 return self._obj_param_ctype_cb[type(obj)](obj)
631
632 def _get_chk_offset_v(self, size):
633 fmt = '{}_CHK_OFFSET_V({}, {}, {});'
634 ret = fmt.format(self._prefix.upper(), self._CTX_AT,
635 self._CTX_BUF_SIZE, size)
636
637 return ret
638
639 def _get_chk_offset_v_cline(self, size):
640 return _CLine(self._get_chk_offset_v(size))
641
642 def _get_align_offset(self, align):
643 fmt = '{}_ALIGN_OFFSET({}, {});'
644 ret = fmt.format(self._prefix.upper(), self._CTX_AT, align)
645
646 return ret
647
648 def _get_align_offset_cline(self, size):
649 return _CLine(self._get_align_offset(size))
650
651 def _write_field_struct(self, fname, src_name, struct):
652 size = self._get_struct_size(struct)
653 size_bytes = self._get_alignment(size, 8) // 8
654 dst = self._CTX_BUF_AT_ADDR
655
656 return [
657 # memcpy() is safe since barectf requires inner structures
658 # to be byte-aligned
659 self._get_chk_offset_v_cline(size),
660 _CLine('memcpy({}, {}, {});'.format(dst, src_name, size_bytes)),
661 _CLine('{} += {};'.format(self._CTX_AT, size)),
662 ]
663
664 def _write_field_integer(self, fname, src_name, integer):
665 bo = self._bo_suffixes_map[integer.byte_order]
666 ptr = self._CTX_BUF
667 t = self._get_obj_param_ctype(integer)
668 start = self._CTX_AT
669 length = self._get_obj_size(integer)
670 fmt = 'barectf_bitfield_write_{}({}, {}, {}, {}, {});'
671
672 return [
673 self._get_chk_offset_v_cline(length),
674 _CLine(fmt.format(bo, ptr, t, start, length, src_name)),
675 _CLine('{} += {};'.format(self._CTX_AT, length))
676 ]
677
678 def _write_field_enum(self, fname, src_name, enum):
679 return self._write_field_obj(fname, src_name, enum.integer)
680
681 def _write_field_floating_point(self, fname, src_name, floating_point):
682 bo = self._bo_suffixes_map[floating_point.byte_order]
683 ptr = self._CTX_BUF
684 t = self._get_obj_param_ctype(floating_point)
685 start = self._CTX_AT
686 length = self._get_obj_size(floating_point)
687 fmt = 'barectf_bitfield_write_{}({}, {}, {}, {}, {});'
688
689 return [
690 self._get_chk_offset_v_cline(length),
691 _CLine(fmt.format(bo, ptr, t, start, length, src_name)),
692 _CLine('{} += {};'.format(self._CTX_AT, length))
693 ]
694
695 def _write_field_array(self, fname, src_name, array):
696 clines = []
697
698 # array index variable declaration
699 iv = 'ia_{}'.format(fname)
700 clines.append(_CLine('uint32_t {};'.format(iv)))
701
702 # for loop using array's static length
703 line = 'for ({iv} = 0; {iv} < {l}; ++{iv}) {{'.format(iv=iv, l=array.length)
704 clines.append(_CLine(line))
705
706 # for loop statements
707 for_block = _CBlock()
708
709 # align bit index before writing to the buffer
710 element_align = self._get_obj_alignment(array.element)
711 cline = self._get_align_offset_cline(element_align)
712 for_block.append(cline)
713
714 # write element to the buffer
715 for_block += self._write_field_obj(fname, src_name, array.element)
716 clines.append(for_block)
717
718 # for loop end
719 clines.append(_CLine('}'))
720
721 return clines
722
723 def _write_field_sequence(self, fname, src_name, sequence):
724 return [
725 _CLine('would write sequence here;'),
726 ]
727
728 def _write_field_string(self, fname, src_name, string):
729 clines = []
730
731 # string index variable declaration
732 iv = 'is_{}'.format(fname)
733 clines.append(_CLine('uint32_t {};'.format(iv)))
734
735 # for loop; loop until the end of the source string is reached
736 fmt = "for ({iv} = 0; {src}[{iv}] != '\\0'; ++{iv}, {ctxat} += 8) {{"
737 line = fmt.format(iv=iv, src=src_name, ctxat=self._CTX_AT)
738 clines.append(_CLine(line))
739
740 # for loop statements
741 for_block = _CBlock()
742
743 # check offset overflow
744 for_block.append(self._get_chk_offset_v_cline(8))
745
746 # write byte to the buffer
747 fmt = '{dst} = {src}[{iv}];'
748 line = fmt.format(dst=self._CTX_BUF_AT, iv=iv, src=src_name)
749 for_block.append(_CLine(line))
750
751 # append for loop
752 clines.append(for_block)
753 clines.append(_CLine('}'))
754
755 # write NULL character to the buffer
756 clines.append(_CLine("{} = '\\0';".format(self._CTX_BUF_AT)))
757 clines.append(_CLine('{} += 8;'.format(self._CTX_AT)))
758
759 return clines
760
761 def _write_field_obj(self, fname, src_name, ftype):
762 return self._write_field_obj_cb[type(ftype)](fname, src_name, ftype)
763
764 def _get_offvar_name(self, name, prefix=None):
765 parts = ['off']
766
767 if prefix is not None:
768 parts.append(prefix)
769
770 parts.append(name)
771
772 return '_'.join(parts)
773
774 def _get_offvar_name_from_expr(self, expr):
775 return self._get_offvar_name('_'.join(expr))
776
777 def _field_to_clines(self, fname, ftype, scope_name, param_name_cb):
778 clines = []
779 pname = param_name_cb(fname)
780 align = self._get_obj_alignment(ftype)
781
782 # group comment
783 fmt = '/* write {}.{} ({}) */'
784 line = fmt.format(scope_name, fname,
785 self._tsdl_type_names_map[type(ftype)])
786 clines.append(_CLine(line))
787
788 # align bit index before writing to the buffer
789 cline = self._get_align_offset_cline(align)
790 clines.append(cline)
791
792 # write offset variables
793 if type(ftype) is pytsdl.tsdl.Struct:
794 offvars_tree = collections.OrderedDict()
795 self._get_struct_size(ftype, offvars_tree)
796 off_vars = self._flatten_offvars_tree(offvars_tree)
797
798 # as many offset as there are child fields because a future
799 # sequence could refer to any of those fields
800 for lname, offset in off_vars.items():
801 offvar = self._get_offvar_name('_'.join([fname, lname]))
802 fmt = 'uint32_t {} = {} + {};'
803 line = fmt.format(offvar, self._CTX_AT, offset);
804 clines.append(_CLine(line))
805 elif type(ftype) is pytsdl.tsdl.Integer:
806 # offset of this simple field is the current bit index
807 offvar = self._get_offvar_name(fname)
808 line = 'uint32_t {} = {};'.format(offvar, self._CTX_AT)
809 clines.append(_CLine(line))
810
811 clines += self._write_field_obj(fname, pname, ftype)
812
813 return clines
814
815 def _join_cline_groups(self, cline_groups):
816 if not cline_groups:
817 return cline_groups
818
819 output_clines = cline_groups[0]
820
821 for clines in cline_groups[1:]:
822 output_clines.append('')
823 output_clines += clines
824
825 return output_clines
826
827 def _struct_to_clines(self, struct, scope_name, param_name_cb):
828 cline_groups = []
829
830 for fname, ftype in struct.fields.items():
831 clines = self._field_to_clines(fname, ftype, scope_name,
832 param_name_cb)
833 cline_groups.append(clines)
834
835 return self._join_cline_groups(cline_groups)
836
837 def _get_struct_size_offvars(self, struct):
838 offvars_tree = collections.OrderedDict()
839 size = self._get_struct_size(struct, offvars_tree)
840 offvars = self._flatten_offvars_tree(offvars_tree)
841
842 return size, offvars
843
844 def _get_ph_size_offvars(self):
845 return self._get_struct_size_offvars(self._doc.trace.packet_header)
846
847 def _get_pc_size_offvars(self, stream):
848 return self._get_struct_size_offvars(stream.packet_context)
849
850 def _offvars_to_ctx_clines(self, prefix, offvars):
851 clines = []
852
853 for name in offvars.keys():
854 offvar = self._get_offvar_name(name, prefix)
855 clines.append(_CLine('uint32_t {};'.format(offvar)))
856
857 return clines
858
859 def _gen_barectf_ctx_struct(self, stream, hide_sid=False):
860 # get offset variables for both the packet header and packet context
861 ph_size, ph_offvars = self._get_ph_size_offvars()
862 pc_size, pc_offvars = self._get_pc_size_offvars(stream)
863 clines = self._offvars_to_ctx_clines('ph', ph_offvars)
864 clines += self._offvars_to_ctx_clines('pc', pc_offvars)
865
866 # indent C
867 clines_indented = []
868 for cline in clines:
869 clines_indented.append(_CLine('\t' + cline))
870
871 # clock callback
872 clock_cb = '\t/* (no clock callback) */'
873
874 if not self._manual_clock:
875 ctype = self._get_clock_type(stream)
876 fmt = '\t{} (*clock_cb)(void*),\n\tvoid* clock_cb_data;'
877 clock_cb = fmt.format(ctype)
878
879 # fill template
880 sid = ''
881
882 if not hide_sid:
883 sid = stream.id
884
885 t = barectf.templates.BARECTF_CTX
886 struct = t.format(prefix=self._prefix, sid=sid,
887 ctx_fields='\n'.join(clines_indented),
888 clock_cb=clock_cb)
889
890 return struct
891
892 def _gen_barectf_contexts_struct(self):
893 hide_sid = False
894
895 if len(self._doc.streams) == 1:
896 hide_sid = True
897
898 structs = []
899
900 for stream in self._doc.streams.values():
901 struct = self._gen_barectf_ctx_struct(stream, hide_sid)
902 structs.append(struct)
903
904 return '\n\n'.join(structs)
905
906 _packet_context_known_fields = [
907 'content_size',
908 'packet_size',
909 'timestamp_begin',
910 'timestamp_end',
911 ]
912
913 def _get_clock_type(self, stream):
914 return self._get_obj_param_ctype(stream.event_header['timestamp'])
915
916 def _gen_manual_clock_param(self, stream):
917 return '{} param_clock'.format(self._get_clock_type(stream))
918
919 def _gen_barectf_func_open_body(self, stream):
920 clines = []
921
922 # update timestamp end if present
923 if self._stream_has_timestamp_begin_end(stream):
924 # get clock value ASAP
925 clk_type = self._get_clock_type(stream)
926 clk = self._gen_get_clock_value()
927 line = '{} clk_value = {};'.format(clk_type, clk)
928 clines.append(_CLine(line))
929 clines.append(_CLine(''))
930
931 # packet context fields
932 fcline_groups = []
933 scope_name = 'stream.packet.context'
934
935 for fname, ftype in stream.packet_context.fields.items():
936 # packet size
937 if fname == 'packet_size':
938 fclines = self._field_to_clines(fname, ftype, scope_name,
939 lambda x: 'ctx->buffer_size')
940 fcline_groups.append(fclines)
941
942 # content size (skip)
943 elif fname == 'content_size':
944 fclines = self._field_to_clines(fname, ftype, scope_name,
945 lambda x: '0')
946 fcline_groups.append(fclines)
947
948 # timestamp_begin
949 elif fname == 'timestamp_begin':
950 fclines = self._field_to_clines(fname, ftype, scope_name,
951 lambda x: 'clk_value')
952 fcline_groups.append(fclines)
953
954 # timestamp_end (skip)
955 elif fname == 'timestamp_end':
956 fclines = self._field_to_clines(fname, ftype, scope_name,
957 lambda x: '0')
958 fcline_groups.append(fclines)
959
960 # anything else
961 else:
962 fclines = self._field_to_clines(fname, ftype, scope_name,
963 self._s_pc_name_to_param_name)
964 fcline_groups.append(fclines)
965
966 clines += self._join_cline_groups(fcline_groups)
967
968 # get source
969 cblock = _CBlock(clines)
970 src = self._cblock_to_source(cblock)
971
972 return src
973
974 def _gen_barectf_func_open(self, stream, gen_body, hide_sid=False):
975 params = []
976
977 # manual clock
978 if self._manual_clock:
979 clock_param = self._gen_manual_clock_param(stream)
980 params.append(clock_param)
981
982 # packet context
983 for fname, ftype in stream.packet_context.fields.items():
984 if fname in self._packet_context_known_fields:
985 continue
986
987 ptype = self._get_obj_param_ctype(ftype)
988 pname = self._s_pc_name_to_param_name(fname)
989 param = '{} {}'.format(ptype, pname)
990 params.append(param)
991
992 params_str = ''
993
994 if params:
995 params_str = ',\n\t'.join([''] + params)
996
997 # fill template
998 sid = ''
999
1000 if not hide_sid:
1001 sid = stream.id
1002
1003 t = barectf.templates.FUNC_OPEN
1004 func = t.format(si=self._si_str, prefix=self._prefix, sid=sid,
1005 params=params_str)
1006
1007 if gen_body:
1008 func += '\n{\n'
1009 func += self._gen_barectf_func_open_body(stream)
1010 func += '\n}'
1011 else:
1012 func += ';'
1013
1014 return func
1015
1016 def _gen_barectf_func_init_body(self, stream):
1017 clines = []
1018
1019 line = 'uint32_t ctx_at_bkup;'
1020 clines.append(_CLine(line))
1021
1022 # set context parameters
1023 clines.append(_CLine(''))
1024 clines.append(_CLine("/* barectf context parameters */"))
1025 clines.append(_CLine('ctx->buf = buf;'))
1026 clines.append(_CLine('ctx->buf_size = buf_size * 8;'))
1027 clines.append(_CLine('{} = 0;'.format(self._CTX_AT)))
1028
1029 if not self._manual_clock:
1030 clines.append(_CLine('ctx->clock_cb = clock_cb;'))
1031 clines.append(_CLine('ctx->clock_cb_data = clock_cb_data;'))
1032
1033 # set context offsets
1034 clines.append(_CLine(''))
1035 clines.append(_CLine("/* barectf context offsets */"))
1036 ph_size, ph_offvars = self._get_ph_size_offvars()
1037 pc_size, pc_offvars = self._get_pc_size_offvars(stream)
1038 pc_alignment = self._get_obj_alignment(stream.packet_context)
1039 pc_offset = self._get_alignment(ph_size, pc_alignment)
1040
1041 for offvar, offset in ph_offvars.items():
1042 offvar_field = self._get_offvar_name(offvar, 'ph')
1043 line = 'ctx->{} = {};'.format(offvar_field, offset)
1044 clines.append(_CLine(line))
1045
1046 for offvar, offset in pc_offvars.items():
1047 offvar_field = self._get_offvar_name(offvar, 'pc')
1048 line = 'ctx->{} = {};'.format(offvar_field, pc_offset + offset)
1049 clines.append(_CLine(line))
1050
1051 clines.append(_CLine(''))
1052
1053 # packet header fields
1054 fcline_groups = []
1055
1056 for fname, ftype in self._doc.trace.packet_header.fields.items():
1057 # magic number
1058 if fname == 'magic':
1059 fclines = self._field_to_clines(fname, ftype, 'packet.header',
1060 lambda x: '0xc1fc1fc1UL')
1061 fcline_groups.append(fclines)
1062
1063 # stream ID
1064 elif fname == 'stream_id':
1065 fclines = self._field_to_clines(fname, ftype, 'packet.header',
1066 lambda x: str(stream.id))
1067 fcline_groups.append(fclines)
1068
1069 clines += self._join_cline_groups(fcline_groups)
1070
1071 # get source
1072 cblock = _CBlock(clines)
1073 src = self._cblock_to_source(cblock)
1074
1075 return src
1076
1077 def _gen_barectf_func_init(self, stream, gen_body, hide_sid=False):
1078 # fill template
1079 sid = ''
1080
1081 if not hide_sid:
1082 sid = stream.id
1083
1084 params = ''
1085
1086 if not self._manual_clock:
1087 ts_ftype = stream.event_header['timestamp']
1088 ts_ptype = self._get_obj_param_ctype(ts_ftype)
1089 fmt = ',\n\t{} (*clock_cb)(void*),\n\tvoid* clock_cb_data'
1090 params = fmt.format(ts_ptype)
1091
1092 t = barectf.templates.FUNC_INIT
1093 func = t.format(si=self._si_str, prefix=self._prefix, sid=sid,
1094 params=params)
1095
1096 if gen_body:
1097 func += '\n{\n'
1098 func += self._gen_barectf_func_init_body(stream)
1099 func += '\n}'
1100 else:
1101 func += ';'
1102
1103 return func
1104
1105 def _gen_get_clock_value(self):
1106 if self._manual_clock:
1107 return 'param_clock'
1108 else:
1109 return self._CTX_CALL_CLOCK_CB
1110
1111 def _stream_has_timestamp_begin_end(self, stream):
1112 return self._has_timestamp_begin_end[stream.id]
1113
1114 def _gen_write_ctx_field_integer(self, src_name, prefix, name, obj):
1115 clines = []
1116
1117 # save buffer position
1118 line = 'ctx_at_bkup = {};'.format(self._CTX_AT)
1119 clines.append(_CLine(line))
1120
1121 # go back to field offset
1122 offvar = self._get_offvar_name(name, prefix)
1123 line = '{} = ctx->{};'.format(self._CTX_AT, offvar)
1124 clines.append(_CLine(line))
1125
1126 # write value
1127 clines += self._write_field_integer(None, src_name, obj)
1128
1129 # restore buffer position
1130 line = '{} = ctx_at_bkup;'.format(self._CTX_AT)
1131 clines.append(_CLine(line))
1132
1133 return clines
1134
1135 def _gen_barectf_func_close_body(self, stream):
1136 clines = []
1137
1138 line = 'uint32_t ctx_at_bkup;'
1139 clines.append(_CLine(line))
1140
1141 # update timestamp end if present
1142 if self._stream_has_timestamp_begin_end(stream):
1143 clines.append(_CLine(''))
1144 clines.append(_CLine("/* update packet context's timestamp_end */"))
1145
1146 # get clock value ASAP
1147 clk_type = self._get_clock_type(stream)
1148 clk = self._gen_get_clock_value()
1149 line = '{} clk_value = {};'.format(clk_type, clk)
1150 clines.append(_CLine(line))
1151
1152 # write timestamp_end
1153 timestamp_end_integer = stream.packet_context['timestamp_end']
1154 clines += self._gen_write_ctx_field_integer('clk_value', 'pc',
1155 'timestamp_end',
1156 timestamp_end_integer)
1157
1158 # update content_size
1159 clines.append(_CLine(''))
1160 clines.append(_CLine("/* update packet context's content_size */"))
1161 content_size_integer = stream.packet_context['content_size']
1162 clines += self._gen_write_ctx_field_integer('ctx_at_bkup', 'pc',
1163 'content_size',
1164 content_size_integer)
1165
1166 # get source
1167 cblock = _CBlock(clines)
1168 src = self._cblock_to_source(cblock)
1169
1170 return src
1171
1172 def _gen_barectf_func_close(self, stream, gen_body, hide_sid=False):
1173 # fill template
1174 sid = ''
1175
1176 if not hide_sid:
1177 sid = stream.id
1178
1179 params = ''
1180
1181 if self._manual_clock:
1182 clock_param = self._gen_manual_clock_param(stream)
1183 params = ',\n\t{}'.format(clock_param)
1184
1185 t = barectf.templates.FUNC_CLOSE
1186 func = t.format(si=self._si_str, prefix=self._prefix, sid=sid,
1187 params=params)
1188
1189 if gen_body:
1190 func += '\n{\n'
1191 func += self._gen_barectf_func_close_body(stream)
1192 func += '\n}'
1193 else:
1194 func += ';'
1195
1196 return func
1197
1198 def _gen_barectf_funcs_init(self, gen_body):
1199 hide_sid = False
1200
1201 if len(self._doc.streams) == 1:
1202 hide_sid = True
1203
1204 funcs = []
1205
1206 for stream in self._doc.streams.values():
1207 funcs.append(self._gen_barectf_func_init(stream, gen_body,
1208 hide_sid))
1209
1210 return funcs
1211
1212 def _gen_barectf_funcs_open(self, gen_body):
1213 hide_sid = False
1214
1215 if len(self._doc.streams) == 1:
1216 hide_sid = True
1217
1218 funcs = []
1219
1220 for stream in self._doc.streams.values():
1221 funcs.append(self._gen_barectf_func_open(stream, gen_body,
1222 hide_sid))
1223
1224 return funcs
1225
1226 def _gen_barectf_func_trace_event(self, stream, event, gen_body, hide_sid):
1227 params = []
1228
1229 # manual clock
1230 if self._manual_clock:
1231 clock_param = self._gen_manual_clock_param(stream)
1232 params.append(clock_param)
1233
1234 # stream event context params
1235 if stream.event_context is not None:
1236 for fname, ftype in stream.event_context.fields.items():
1237 ptype = self._get_obj_param_ctype(ftype)
1238 pname = self._ev_sec_name_to_param_name(fname)
1239 param = '{} {}'.format(ptype, pname)
1240 params.append(param)
1241
1242 # event context params
1243 if event.context is not None:
1244 for fname, ftype in event.context.fields.items():
1245 ptype = self._get_obj_param_ctype(ftype)
1246 pname = self._ev_c_name_to_param_name(fname)
1247 param = '{} {}'.format(ptype, pname)
1248 params.append(param)
1249
1250 # event fields params
1251 if event.fields is not None:
1252 for fname, ftype in event.fields.fields.items():
1253 ptype = self._get_obj_param_ctype(ftype)
1254 pname = self._ev_f_name_to_param_name(fname)
1255 param = '{} {}'.format(ptype, pname)
1256 params.append(param)
1257
1258 params_str = ''
1259
1260 if params:
1261 params_str = ',\n\t'.join([''] + params)
1262
1263 # fill template
1264 sid = ''
1265
1266 if not hide_sid:
1267 sid = stream.id
1268
1269 t = barectf.templates.FUNC_TRACE
1270 func = t.format(si=self._si_str, prefix=self._prefix, sid=sid,
1271 evname=event.name, params=params_str)
1272
1273 if gen_body:
1274 func += '\n{\n'
1275 #func += self._gen_barectf_func_open_body(stream)
1276 func += '\n}'
1277 else:
1278 func += ';'
1279
1280 return func
1281
1282 def _gen_barectf_funcs_trace_stream(self, stream, gen_body, hide_sid):
1283 funcs = []
1284
1285 for event in stream.events:
1286 funcs.append(self._gen_barectf_func_trace_event(stream, event,
1287 gen_body, hide_sid))
1288
1289 return funcs
1290
1291 def _gen_barectf_funcs_trace(self, gen_body):
1292 hide_sid = False
1293
1294 if len(self._doc.streams) == 1:
1295 hide_sid = True
1296
1297 funcs = []
1298
1299 for stream in self._doc.streams.values():
1300 funcs += self._gen_barectf_funcs_trace_stream(stream, gen_body,
1301 hide_sid)
1302
1303 return funcs
1304
1305 def _gen_barectf_funcs_close(self, gen_body):
1306 hide_sid = False
1307
1308 if len(self._doc.streams) == 1:
1309 hide_sid = True
1310
1311 funcs = []
1312
1313 for stream in self._doc.streams.values():
1314 funcs.append(self._gen_barectf_func_close(stream, gen_body,
1315 hide_sid))
1316
1317 return funcs
1318
1319 def _gen_barectf_header(self):
1320 ctx_structs = self._gen_barectf_contexts_struct()
1321 init_funcs = self._gen_barectf_funcs_init(self._static_inline)
1322 open_funcs = self._gen_barectf_funcs_open(self._static_inline)
1323 close_funcs = self._gen_barectf_funcs_close(self._static_inline)
1324 trace_funcs = self._gen_barectf_funcs_trace(self._static_inline)
1325 functions = init_funcs + open_funcs + close_funcs + trace_funcs
1326 functions_str = '\n\n'.join(functions)
1327 t = barectf.templates.HEADER
1328 header = t.format(prefix=self._prefix, ucprefix=self._prefix.upper(),
1329 barectf_ctx=ctx_structs, functions=functions_str)
1330
1331 return header
1332
1333 def _cblock_to_source_lines(self, cblock, indent=1):
1334 src = []
1335 indentstr = '\t' * indent
1336
1337 for line in cblock:
1338 if type(line) is _CBlock:
1339 src += self._cblock_to_source_lines(line, indent + 1)
1340 else:
1341 src.append(indentstr + line)
1342
1343 return src
1344
1345 def _cblock_to_source(self, cblock, indent=1):
1346 lines = self._cblock_to_source_lines(cblock, indent)
1347
1348 return '\n'.join(lines)
1349
1350 def _set_params(self):
1351 self._has_timestamp_begin_end = {}
1352
1353 for stream in self._doc.streams.values():
1354 has = 'timestamp_begin' in stream.packet_context.fields
1355 self._has_timestamp_begin_end[stream.id] = has
1356
1357 def gen_barectf(self, metadata, output, prefix, static_inline,
1358 manual_clock):
1359 self._metadata = metadata
1360 self._output = output
1361 self._prefix = prefix
1362 self._static_inline = static_inline
1363 self._manual_clock = manual_clock
1364 self._si_str = ''
1365
1366 if static_inline:
1367 self._si_str = 'static inline '
1368
1369 # open CTF metadata file
1370 try:
1371 with open(metadata) as f:
1372 self._tsdl = f.read()
1373 except:
1374 _perror('cannot open/read CTF metadata file "{}"'.format(metadata))
1375
1376 # parse CTF metadata
1377 try:
1378 self._doc = self._parser.parse(self._tsdl)
1379 except pytsdl.parser.ParseError as e:
1380 _perror('parse error: {}'.format(e))
1381
1382 # validate CTF metadata against barectf constraints
1383 self._validate_metadata()
1384
1385 # set parameters for this generation
1386 self._set_params()
1387
1388
1389 print(self._gen_barectf_header())
1390
1391 """
1392 clines = self._struct_to_clines(self._doc.streams[0].get_event(0).fields,
1393 'stream event context',
1394 self._ev_f_name_to_param_name)
1395 source = self._cblock_to_source(clines)
1396 print(source)
1397 """
1398
1399
1400 def run():
1401 args = _parse_args()
1402 generator = BarectfCodeGenerator()
1403 generator.gen_barectf(args.metadata, args.output, args.prefix,
1404 args.static_inline, args.manual_clock)
This page took 0.143132 seconds and 5 git commands to generate.