Create generator class, fix a few things
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sat, 8 Nov 2014 08:54:50 +0000 (03:54 -0500)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Sat, 8 Nov 2014 08:54:50 +0000 (03:54 -0500)
barectf/cli.py

index 20794a24a3f6825fd1a460c8d72fe1cddc6ecd6b..a0c65f0cf26c6fff066cc42f8522af535db9ad7b 100644 (file)
@@ -72,717 +72,755 @@ def _parse_args():
     return args
 
 
-# TODO: prettify this function
-def _validate_struct(struct):
-    # just in case we call this with the wrong type
-    if type(struct) is not pytsdl.tsdl.Struct:
-        raise RuntimeError('expecting a struct')
-
-    # make sure inner structures are at least byte-aligned
-    if _get_obj_alignment(struct) < 8:
-        raise RuntimeError('inner struct must be at least byte-aligned')
-
-    # check each field
-    for name, ftype in struct.fields.items():
-        if type(ftype) is pytsdl.tsdl.Sequence:
-            raise RuntimeError('field "{}" is a dynamic array (not allowed here)'.format(name))
-        elif type(ftype) is pytsdl.tsdl.Array:
-            # we need to check every element type until we find a terminal one
-            end = False
-            element = ftype.element
-
-            while not end:
-                if type(element) is pytsdl.tsdl.Sequence:
-                    raise RuntimeError('field "{}" contains a dynamic array (not allowed here)'.format(name))
-                elif type(element) is pytsdl.tsdl.Variant:
-                    raise RuntimeError('field "{}" contains a variant (unsupported)'.format(name))
-                elif type(element) is pytsdl.tsdl.String:
-                    raise RuntimeError('field "{}" contains a string (not allowed here)'.format(name))
-                elif type(element) is pytsdl.tsdl.Struct:
-                    _validate_struct(element)
-                elif type(element) is pytsdl.tsdl.Integer:
-                    if _get_integer_size(element) > 64:
-                        raise RuntimeError('integer field "{}" larger than 64-bit'.format(name))
-                elif type(element) is pytsdl.tsdl.FloatingPoint:
-                    if _get_floating_point_size(element) > 64:
-                        raise RuntimeError('floating point field "{}" larger than 64-bit'.format(name))
-                elif type(element) is pytsdl.tsdl.Enum:
-                    if _get_enum_size(element) > 64:
-                        raise RuntimeError('enum field "{}" larger than 64-bit'.format(name))
-
-                if type(element) is pytsdl.tsdl.Array:
-                    # still an array, continue
-                    element = element.element
-                else:
-                    # found the terminal element
-                    end = True
-        elif type(ftype) is pytsdl.tsdl.Variant:
-            raise RuntimeError('field "{}" is a variant (unsupported)'.format(name))
-        elif type(ftype) is pytsdl.tsdl.String:
-            raise RuntimeError('field "{}" is a string (not allowed here)'.format(name))
-        elif type(ftype) is pytsdl.tsdl.Struct:
-            _validate_struct(ftype)
-        elif type(ftype) is pytsdl.tsdl.Integer:
-            if _get_integer_size(ftype) > 64:
-                raise RuntimeError('integer field "{}" larger than 64-bit'.format(name))
-        elif type(ftype) is pytsdl.tsdl.FloatingPoint:
-            if _get_floating_point_size(ftype) > 64:
-                raise RuntimeError('floating point field "{}" larger than 64-bit'.format(name))
-        elif type(ftype) is pytsdl.tsdl.Enum:
-            if _get_enum_size(ftype) > 64:
-                raise RuntimeError('enum field "{}" larger than 64-bit'.format(name))
-
-
-def _validate_context_field(struct):
-    if type(struct) is not pytsdl.tsdl.Struct:
-        raise RuntimeError('expecting a struct')
-
-    for name, ftype in struct.fields.items():
-        if type(ftype) is pytsdl.tsdl.Variant:
-            raise RuntimeError('field "{}" is a variant (unsupported)'.format(name))
-        elif type(ftype) is pytsdl.tsdl.Struct:
-            # validate inner structure against barectf constraints
-            _validate_struct(ftype)
-
-
-def _validate_integer(integer, size=None, align=None, signed=None):
-    if type(integer) is not pytsdl.tsdl.Integer:
-        raise RuntimeError('expected integer')
-
-    if size is not None:
-        if integer.size != size:
-            raise RuntimeError('expected {}-bit integer'.format(size))
-
-    if align is not None:
-        if integer.align != align:
-            raise RuntimeError('expected integer with {}-bit alignment'.format(align))
-
-    if signed is not None:
-        if integer.signed != signed:
-            raise RuntimeError('expected {} integer'.format('signed' if signed else 'unsigned'))
+class _CBlock(list):
+    pass
 
 
-def _validate_packet_header(packet_header):
-    try:
-        _validate_struct(packet_header)
-    except RuntimeError as e:
-        _perror('packet header: {}'.format(e))
+class _CLine(str):
+    pass
 
-    # magic must be the first field
-    if 'magic' in packet_header.fields:
-        if list(packet_header.fields.keys())[0] != 'magic':
-            _perror('packet header: "magic" must be the first field')
-    else:
-        _perror('packet header: missing "magic" field')
 
-    # magic must be a 32-bit unsigned integer, 32-bit aligned
-    try:
-        _validate_integer(packet_header['magic'], 32, 32, False)
-    except RuntimeError as e:
-        _perror('packet header: "magic": {}'.format(e))
+class BarectfCodeGenerator:
+    _CTX_AT = 'ctx->at'
+    _CTX_BUF = 'ctx->buf'
+    _CTX_BUF_SIZE = 'ctx->buf_size'
+    _CTX_BUF_AT = '{}[{} >> 3]'.format(_CTX_BUF, _CTX_AT)
+    _CTX_BUF_AT_ADDR = '&{}'.format(_CTX_BUF_AT)
+
+    _bo_suffixes_map = {
+        pytsdl.tsdl.ByteOrder.BE: 'be',
+        pytsdl.tsdl.ByteOrder.LE: 'le',
+    }
+
+    _tsdl_type_names_map = {
+        pytsdl.tsdl.Integer: 'integer',
+        pytsdl.tsdl.FloatingPoint: 'floating point',
+        pytsdl.tsdl.Enum: 'enumeration',
+        pytsdl.tsdl.String: 'string',
+        pytsdl.tsdl.Array: 'static array',
+        pytsdl.tsdl.Sequence: 'dynamic array',
+        pytsdl.tsdl.Struct: 'structure',
+    }
+
+    def __init__(self):
+        self._parser = pytsdl.parser.Parser()
+        self._obj_size_cb = {
+            pytsdl.tsdl.Struct: self._get_struct_size,
+            pytsdl.tsdl.Integer: self._get_integer_size,
+            pytsdl.tsdl.Enum: self._get_enum_size,
+            pytsdl.tsdl.FloatingPoint: self._get_floating_point_size,
+            pytsdl.tsdl.Array: self._get_array_size,
+        }
+        self._obj_alignment_cb = {
+            pytsdl.tsdl.Struct: self._get_struct_alignment,
+            pytsdl.tsdl.Integer: self._get_integer_alignment,
+            pytsdl.tsdl.Enum: self._get_enum_alignment,
+            pytsdl.tsdl.FloatingPoint: self._get_floating_point_alignment,
+            pytsdl.tsdl.Array: self._get_array_alignment,
+            pytsdl.tsdl.Sequence: self._get_sequence_alignment,
+            pytsdl.tsdl.String: self._get_string_alignment,
+        }
+        self._obj_param_ctype_cb = {
+            pytsdl.tsdl.Struct: lambda obj: 'const void*',
+            pytsdl.tsdl.Integer: self._get_integer_param_ctype,
+            pytsdl.tsdl.Enum: self._get_enum_param_ctype,
+            pytsdl.tsdl.FloatingPoint: self._get_floating_point_param_ctype,
+            pytsdl.tsdl.Array: lambda obj: 'const void*',
+            pytsdl.tsdl.Sequence: lambda obj: 'const void*',
+            pytsdl.tsdl.String: lambda obj: 'const char*',
+        }
+        self._write_field_obj_cb = {
+            pytsdl.tsdl.Struct: self._write_field_struct,
+            pytsdl.tsdl.Integer: self._write_field_integer,
+            pytsdl.tsdl.Enum: self._write_field_enum,
+            pytsdl.tsdl.FloatingPoint: self._write_field_floating_point,
+            pytsdl.tsdl.Array: self._write_field_array,
+            pytsdl.tsdl.Sequence: self._write_field_sequence,
+            pytsdl.tsdl.String: self._write_field_string,
+        }
+
+    # TODO: prettify this function
+    def _validate_struct(self, struct):
+        # just in case we call this with the wrong type
+        if type(struct) is not pytsdl.tsdl.Struct:
+            raise RuntimeError('expecting a struct')
+
+        # make sure inner structures are at least byte-aligned
+        if self._get_obj_alignment(struct) < 8:
+            raise RuntimeError('inner struct must be at least byte-aligned')
+
+        # check each field
+        for name, ftype in struct.fields.items():
+            if type(ftype) is pytsdl.tsdl.Sequence:
+                raise RuntimeError('field "{}" is a dynamic array (not allowed here)'.format(name))
+            elif type(ftype) is pytsdl.tsdl.Array:
+                # we need to check every element until we find a terminal one
+                element = ftype.element
+
+                while True:
+                    if type(element) is pytsdl.tsdl.Sequence:
+                        raise RuntimeError('field "{}" contains a dynamic array (not allowed here)'.format(name))
+                    elif type(element) is pytsdl.tsdl.Variant:
+                        raise RuntimeError('field "{}" contains a variant (unsupported)'.format(name))
+                    elif type(element) is pytsdl.tsdl.String:
+                        raise RuntimeError('field "{}" contains a string (not allowed here)'.format(name))
+                    elif type(element) is pytsdl.tsdl.Struct:
+                        _validate_struct(element)
+                    elif type(element) is pytsdl.tsdl.Integer:
+                        if self._get_obj_size(element) > 64:
+                            raise RuntimeError('integer field "{}" larger than 64-bit'.format(name))
+                    elif type(element) is pytsdl.tsdl.FloatingPoint:
+                        if self._get_obj_size(element) > 64:
+                            raise RuntimeError('floating point field "{}" larger than 64-bit'.format(name))
+                    elif type(element) is pytsdl.tsdl.Enum:
+                        if self._get_obj_size(element) > 64:
+                            raise RuntimeError('enum field "{}" larger than 64-bit'.format(name))
+
+                    if type(element) is pytsdl.tsdl.Array:
+                        # still an array, continue
+                        element = element.element
+                    else:
+                        # found the terminal element
+                        break
+            elif type(ftype) is pytsdl.tsdl.Variant:
+                raise RuntimeError('field "{}" is a variant (unsupported)'.format(name))
+            elif type(ftype) is pytsdl.tsdl.String:
+                raise RuntimeError('field "{}" is a string (not allowed here)'.format(name))
+            elif type(ftype) is pytsdl.tsdl.Struct:
+                _validate_struct(ftype)
+            elif type(ftype) is pytsdl.tsdl.Integer:
+                if self._get_obj_size(ftype) > 64:
+                    raise RuntimeError('integer field "{}" larger than 64-bit'.format(name))
+            elif type(ftype) is pytsdl.tsdl.FloatingPoint:
+                if self._get_obj_size(ftype) > 64:
+                    raise RuntimeError('floating point field "{}" larger than 64-bit'.format(name))
+            elif type(ftype) is pytsdl.tsdl.Enum:
+                if self._get_obj_size(ftype) > 64:
+                    raise RuntimeError('enum field "{}" larger than 64-bit'.format(name))
+
+    def _validate_context_field(self, struct):
+        if type(struct) is not pytsdl.tsdl.Struct:
+            raise RuntimeError('expecting a struct')
+
+        for name, ftype in struct.fields.items():
+            if type(ftype) is pytsdl.tsdl.Variant:
+                raise RuntimeError('field "{}" is a variant (unsupported)'.format(name))
+            elif type(ftype) is pytsdl.tsdl.Struct:
+                # validate inner structure against barectf constraints
+                self._validate_struct(ftype)
+
+    def _validate_integer(self, integer, size=None, align=None,
+                               signed=None):
+        if type(integer) is not pytsdl.tsdl.Integer:
+            raise RuntimeError('expected integer')
+
+        if size is not None:
+            if integer.size != size:
+                raise RuntimeError('expected {}-bit integer'.format(size))
+
+        if align is not None:
+            if integer.align != align:
+                raise RuntimeError('expected integer with {}-bit alignment'.format(align))
+
+        if signed is not None:
+            if integer.signed != signed:
+                raise RuntimeError('expected {} integer'.format('signed' if signed else 'unsigned'))
+
+    def _validate_packet_header(self, packet_header):
+        try:
+            self._validate_struct(packet_header)
+        except RuntimeError as e:
+            _perror('packet header: {}'.format(e))
 
-    # mandatory stream_id
-    if 'stream_id' not in packet_header.fields:
-        _perror('packet header: missing "stream_id" field')
+        # magic must be the first field
+        if 'magic' in packet_header.fields:
+            if list(packet_header.fields.keys())[0] != 'magic':
+                _perror('packet header: "magic" must be the first field')
+        else:
+            _perror('packet header: missing "magic" field')
 
-    # stream_id must be an unsigned integer
-    try:
-        _validate_integer(packet_header['stream_id'], signed=False)
-    except RuntimeError as e:
-        _perror('packet header: "stream_id": {}'.format(e))
+        # magic must be a 32-bit unsigned integer, 32-bit aligned
+        try:
+            self._validate_integer(packet_header['magic'], 32, 32, False)
+        except RuntimeError as e:
+            _perror('packet header: "magic": {}'.format(e))
 
+        # mandatory stream_id
+        if 'stream_id' not in packet_header.fields:
+            _perror('packet header: missing "stream_id" field')
 
-def _dot_name_to_str(name):
-    return '.'.join(name)
+        # stream_id must be an unsigned integer
+        try:
+            self._validate_integer(packet_header['stream_id'], signed=False)
+        except RuntimeError as e:
+            _perror('packet header: "stream_id": {}'.format(e))
 
+    def _dot_name_to_str(self, name):
+        return '.'.join(name)
 
-def _compare_integers(int1, int2):
-    if type(int1) is not pytsdl.tsdl.Integer:
-        return False
 
-    if type(int2) is not pytsdl.tsdl.Integer:
-        return False
+    def _compare_integers(self, int1, int2):
+        if type(int1) is not pytsdl.tsdl.Integer:
+            return False
 
-    size = int1.size == int2.size
-    align = int1.align == int2.align
-    cmap = int1.map == int2.map
-    base = int1.base == int2.base
-    encoding = int1.encoding == int2.encoding
-    signed = int1.signed == int2.signed
-    comps = (size, align, cmap, base, encoding, signed)
+        if type(int2) is not pytsdl.tsdl.Integer:
+            return False
 
-    # True means 1 for sum()
-    return sum(comps) == len(comps)
+        size = int1.size == int2.size
+        align = int1.align == int2.align
+        cmap = int1.map == int2.map
+        base = int1.base == int2.base
+        encoding = int1.encoding == int2.encoding
+        signed = int1.signed == int2.signed
+        comps = (size, align, cmap, base, encoding, signed)
 
+        # True means 1 for sum()
+        return sum(comps) == len(comps)
 
-def _validate_packet_context(doc, stream):
-    packet_context = stream.packet_context
-    sid = stream.id
+    def _validate_packet_context(self, stream):
+        packet_context = stream.packet_context
+        sid = stream.id
 
-    try:
-        _validate_struct(packet_context)
-    except RuntimeError as e:
-        _perror('stream {}: packet context: {}'.format(sid, e))
+        try:
+            self._validate_struct(packet_context)
+        except RuntimeError as e:
+            _perror('stream {}: packet context: {}'.format(sid, e))
 
-    fields = packet_context.fields
+        fields = packet_context.fields
 
-    # if timestamp_begin exists, timestamp_end must exist
-    if 'timestamp_begin' in fields or 'timestamp_end' in fields:
-        if 'timestamp_begin' not in fields or 'timestamp_end' not in fields:
-            _perror('stream {}: packet context: "timestamp_begin" must exist if "timestamp_end" exists'.format(sid))
-        else:
-            # timestamp_begin and timestamp_end must have the same integer
-            # as the event header's timestamp field (should exist by now)
-            timestamp = stream.event_header['timestamp']
+        # if timestamp_begin exists, timestamp_end must exist
+        if 'timestamp_begin' in fields or 'timestamp_end' in fields:
+            if 'timestamp_begin' not in fields or 'timestamp_end' not in fields:
+                _perror('stream {}: packet context: "timestamp_begin" must exist if "timestamp_end" exists'.format(sid))
+            else:
+                # timestamp_begin and timestamp_end must have the same integer
+                # as the event header's timestamp field (should exist by now)
+                timestamp = stream.event_header['timestamp']
 
-            if not _compare_integers(fields['timestamp_begin'], timestamp):
-                _perror('stream {}: packet context: "timestamp_begin": integer type different from event header\'s "timestamp" field'.format(sid))
+                if not self._compare_integers(fields['timestamp_begin'], timestamp):
+                    _perror('stream {}: packet context: "timestamp_begin": integer type different from event header\'s "timestamp" field'.format(sid))
 
-            if not _compare_integers(fields['timestamp_end'], timestamp):
-                _perror('stream {}: packet context: "timestamp_end": integer type different from event header\'s "timestamp" field'.format(sid))
+                if not self._compare_integers(fields['timestamp_end'], timestamp):
+                    _perror('stream {}: packet context: "timestamp_end": integer type different from event header\'s "timestamp" field'.format(sid))
 
-    # content_size must exist and be an unsigned integer
-    if 'content_size' not in fields:
-        _perror('stream {}: packet context: missing "content_size" field'.format(sid))
+        # content_size must exist and be an unsigned integer
+        if 'content_size' not in fields:
+            _perror('stream {}: packet context: missing "content_size" field'.format(sid))
 
-    try:
-        _validate_integer(fields['content_size'], 32, 32, False)
-    except:
         try:
-            _validate_integer(fields['content_size'], 64, 64, False)
+            self._validate_integer(fields['content_size'], 32, 32, False)
         except:
-            _perror('stream {}: packet context: "content_size": expecting unsigned 32-bit/64-bit integer'.format(sid))
+            try:
+                self._validate_integer(fields['content_size'], 64, 64, False)
+            except:
+                _perror('stream {}: packet context: "content_size": expecting unsigned 32-bit/64-bit integer'.format(sid))
 
-    # packet_size must exist and be an unsigned integer
-    if 'packet_size' not in fields:
-        _perror('stream {}: packet context: missing "packet_size" field'.format(sid))
+        # packet_size must exist and be an unsigned integer
+        if 'packet_size' not in fields:
+            _perror('stream {}: packet context: missing "packet_size" field'.format(sid))
 
-    try:
-        _validate_integer(fields['packet_size'], 32, 32, False)
-    except:
         try:
-            _validate_integer(fields['packet_size'], 64, 64, False)
+            self._validate_integer(fields['packet_size'], 32, 32, False)
         except:
-            _perror('stream {}: packet context: "packet_size": expecting unsigned 32-bit/64-bit integer'.format(sid))
+            try:
+                self._validate_integer(fields['packet_size'], 64, 64, False)
+            except:
+                _perror('stream {}: packet context: "packet_size": expecting unsigned 32-bit/64-bit integer'.format(sid))
+
+        # if cpu_id exists, must be an unsigned integer
+        if 'cpu_id' in fields:
+            try:
+                self._validate_integer(fields['cpu_id'], signed=False)
+            except RuntimeError as e:
+                _perror('stream {}: packet context: "cpu_id": {}'.format(sid, e))
+
+    def _validate_event_header(self, stream):
+        event_header = stream.event_header
+        sid = stream.id
 
-    # if cpu_id exists, must be an unsigned integer
-    if 'cpu_id' in fields:
         try:
-            _validate_integer(fields['cpu_id'], signed=False)
+            self._validate_struct(event_header)
         except RuntimeError as e:
-            _perror('stream {}: packet context: "cpu_id": {}'.format(sid, e))
-
-
-def _validate_event_header(doc, stream):
-    event_header = stream.event_header
-    sid = stream.id
-
-    try:
-        _validate_struct(event_header)
-    except RuntimeError as e:
-        _perror('stream {}: event header: {}'.format(sid, e))
-
-    fields = event_header.fields
-
-    # id must exist and be an unsigned integer
-    if 'id' not in fields:
-        _perror('stream {}: event header: missing "id" field'.format(sid))
+            _perror('stream {}: event header: {}'.format(sid, e))
 
-    try:
-        _validate_integer(fields['id'], signed=False)
-    except RuntimeError as e:
-        _perror('stream {}: "id": {}'.format(sid, format(e)))
+        fields = event_header.fields
 
+        # id must exist and be an unsigned integer
+        if 'id' not in fields:
+            _perror('stream {}: event header: missing "id" field'.format(sid))
 
-    # timestamp must exist, be an unsigned integer and be mapped to a valid clock
-    if 'timestamp' not in fields:
-        _perror('stream {}: event header: missing "timestamp" field'.format(sid))
-
-    try:
-        _validate_integer(fields['timestamp'], signed=False)
-    except RuntimeError as e:
-        _perror('stream {}: "timestamp": {}'.format(sid, format(e)))
-
-
-def _validate_stream_event_context(doc, stream):
-    stream_event_context = stream.event_context
-    sid = stream.id
-
-    if stream_event_context is None:
-        return
-
-    try:
-        _validate_context_field(stream_event_context)
-    except RuntimeError as e:
-        _perror('stream {}: event context: {}'.format(sid, e))
-
-
-def _validate_all_scopes(doc):
-    # packet header
-    _validate_packet_header(doc.trace.packet_header)
-
-    # stream stuff
-    for stream_id, stream in doc.streams.items():
-        _validate_event_header(doc, stream)
-        _validate_packet_context(doc, stream)
-        _validate_stream_event_context(doc, stream)
-
-
-def _validate_metadata(doc):
-    _validate_all_scopes(doc)
-
-
-# 3, 4 -> 4
-# 4, 4 -> 4
-# 5, 4 -> 8
-# 6, 4 -> 8
-# 7, 4 -> 8
-# 8, 4 -> 8
-# 9, 4 -> 12
-def _get_alignment(at, align):
-    return (at + align - 1) & -align
-
-
-def _offset_vars_tree_to_vars(offset_vars_tree, prefix='',
-                              offset_vars=collections.OrderedDict()):
-    for name, offset in offset_vars_tree.items():
-        varname = '{}_{}'.format(prefix, name)
-
-        if isinstance(offset, dict):
-            _offset_vars_tree_to_vars(offset, varname, offset_vars)
-        else:
-            offset_vars[varname] = offset
-
-    return offset_vars
-
-
-# returns the size of a struct with _static size_
-def _get_struct_size(struct, offset_vars_tree=collections.OrderedDict(),
-                     base_offset=0):
-    offset = 0
-
-    for fname, ftype in struct.fields.items():
-        field_alignment = _get_obj_alignment(ftype)
-        offset = _get_alignment(offset, field_alignment)
-
-        if type(ftype) is pytsdl.tsdl.Struct:
-            offset_vars_tree[fname] = collections.OrderedDict()
-            sz = _get_struct_size(ftype, offset_vars_tree[fname],
-                                  base_offset + offset)
-        else:
-            # only integers may act as sequence lengths
-            if type(ftype) is pytsdl.tsdl.Integer:
-                offset_vars_tree[fname] = base_offset + offset
-
-            sz = _get_obj_size(ftype)
-
-        offset += sz
-
-    return offset
-
+        try:
+            self._validate_integer(fields['id'], signed=False)
+        except RuntimeError as e:
+            _perror('stream {}: "id": {}'.format(sid, format(e)))
 
-def _get_array_size(array):
-    element = array.element
 
-    # effective size of one element includes its alignment after its size
-    size = _get_obj_size(element)
-    align = _get_obj_alignment(element)
+        # timestamp must exist, be an unsigned integer and be mapped to a valid clock
+        if 'timestamp' not in fields:
+            _perror('stream {}: event header: missing "timestamp" field'.format(sid))
 
-    return _get_alignment(size, align) * array.length
+        try:
+            self._validate_integer(fields['timestamp'], signed=False)
+        except RuntimeError as e:
+            _perror('stream {}: "timestamp": {}'.format(sid, format(e)))
 
+    def _validate_stream_event_context(self, stream):
+        stream_event_context = stream.event_context
+        sid = stream.id
 
-def _get_enum_size(enum):
-    return _get_obj_size(enum.integer)
+        if stream_event_context is None:
+            return
 
+        try:
+            self._validate_context_field(stream_event_context)
+        except RuntimeError as e:
+            _perror('stream {}: event context: {}'.format(sid, e))
+
+    def _validate_all_scopes(self):
+        # packet header
+        self._validate_packet_header(self._doc.trace.packet_header)
+
+        # stream stuff
+        for stream_id, stream in self._doc.streams.items():
+            self._validate_event_header(stream)
+            self._validate_packet_context(stream)
+            self._validate_stream_event_context(stream)
+
+    def _validate_metadata(self):
+        self._validate_all_scopes()
+
+    # 3, 4 -> 4
+    # 4, 4 -> 4
+    # 5, 4 -> 8
+    # 6, 4 -> 8
+    # 7, 4 -> 8
+    # 8, 4 -> 8
+    # 9, 4 -> 12
+    def _get_alignment(self, at, align):
+        return (at + align - 1) & -align
+
+    # this converts a tree of offset variables:
+    #
+    #     field
+    #       a -> 0
+    #       b -> 8
+    #       other_struct
+    #         field -> 16
+    #         yeah -> 20
+    #       c -> 32
+    #     len -> 36
+    #
+    # to a flat dict:
+    #
+    #     field_a -> 0
+    #     field_b -> 8
+    #     field_other_struct_field -> 16
+    #     field_other_struct_yeah -> 20
+    #     field_c -> 32
+    #     len -> 36
+    def _offvars_tree_to_vars(self, offvars_tree, prefix=None,
+                               off_vars=collections.OrderedDict()):
+        for name, offset in offvars_tree.items():
+            if prefix is not None:
+                varname = '{}_{}'.format(prefix, name)
+            else:
+                varname = name
 
-def _get_floating_point_size(floating_point):
-    return floating_point.exp_dig + floating_point.mant_dig
+            if isinstance(offset, dict):
+                self._offvars_tree_to_vars(offset, varname, off_vars)
+            else:
+                off_vars[varname] = offset
 
+        return off_vars
 
-def _get_integer_size(integer):
-    return integer.size
+    # returns the size of a struct with _static size_
+    def _get_struct_size(self, struct,
+                         offvars_tree=collections.OrderedDict(),
+                         base_offset=0):
+        offset = 0
 
+        for fname, ftype in struct.fields.items():
+            field_alignment = self._get_obj_alignment(ftype)
+            offset = self._get_alignment(offset, field_alignment)
 
-_obj_size_cb = {
-    pytsdl.tsdl.Struct: _get_struct_size,
-    pytsdl.tsdl.Integer: _get_integer_size,
-    pytsdl.tsdl.Enum: _get_enum_size,
-    pytsdl.tsdl.FloatingPoint: _get_floating_point_size,
-    pytsdl.tsdl.Array: _get_array_size,
-}
+            if type(ftype) is pytsdl.tsdl.Struct:
+                offvars_tree[fname] = collections.OrderedDict()
+                sz = self._get_struct_size(ftype, offvars_tree[fname],
+                                      base_offset + offset)
+            else:
+                # only integers may act as sequence lengths
+                if type(ftype) is pytsdl.tsdl.Integer:
+                    offvars_tree[fname] = base_offset + offset
 
+                sz = self._get_obj_size(ftype)
 
-def _get_obj_size(obj):
-    return _obj_size_cb[type(obj)](obj)
+            offset += sz
 
+        return offset
 
-def _get_struct_alignment(struct):
-    if struct.align is not None:
-        return struct.align
+    def _get_array_size(self, array):
+        element = array.element
 
-    cur_align = 1
+        # effective size of one element includes its alignment after its size
+        size = self._get_obj_size(element)
+        align = self._get_obj_alignment(element)
 
-    for fname, ftype in struct.fields.items():
-        cur_align = max(_get_obj_alignment(ftype), cur_align)
+        return self._get_alignment(size, align) * array.length
 
-    return cur_align
+    def _get_enum_size(self, enum):
+        return self._get_obj_size(enum.integer)
 
+    def _get_floating_point_size(self, floating_point):
+        return floating_point.exp_dig + floating_point.mant_dig
 
-def _get_integer_alignment(integer):
-    return integer.align
+    def _get_integer_size(self, integer):
+        return integer.size
 
+    def _get_obj_size(self, obj):
+        return self._obj_size_cb[type(obj)](obj)
 
-def _get_floating_point_alignment(floating_point):
-    return floating_point.align
+    def _get_struct_alignment(self, struct):
+        if struct.align is not None:
+            return struct.align
 
+        cur_align = 1
 
-def _get_enum_alignment(enum):
-    return _get_obj_alignment(enum.integer)
+        for fname, ftype in struct.fields.items():
+            cur_align = max(self._get_obj_alignment(ftype), cur_align)
 
+        return cur_align
 
-def _get_string_alignment(string):
-    return 8
+    def _get_integer_alignment(self, integer):
+        return integer.align
 
-def _get_array_alignment(array):
-    return _get_obj_alignment(array.element)
+    def _get_floating_point_alignment(self, floating_point):
+        return floating_point.align
 
+    def _get_enum_alignment(self, enum):
+        return self._get_obj_alignment(enum.integer)
 
-def _get_sequence_alignment(sequence):
-    return _get_obj_alignment(sequence.element)
+    def _get_string_alignment(self, string):
+        return 8
 
+    def _get_array_alignment(self, array):
+        return self._get_obj_alignment(array.element)
 
-_obj_alignment_cb = {
-    pytsdl.tsdl.Struct: _get_struct_alignment,
-    pytsdl.tsdl.Integer: _get_integer_alignment,
-    pytsdl.tsdl.Enum: _get_enum_alignment,
-    pytsdl.tsdl.FloatingPoint: _get_floating_point_alignment,
-    pytsdl.tsdl.Array: _get_array_alignment,
-    pytsdl.tsdl.Sequence: _get_sequence_alignment,
-    pytsdl.tsdl.String: _get_string_alignment,
-}
+    def _get_sequence_alignment(self, sequence):
+        return self._get_obj_alignment(sequence.element)
 
+    def _get_obj_alignment(self, obj):
+        return self._obj_alignment_cb[type(obj)](obj)
 
-def _get_obj_alignment(obj):
-    return _obj_alignment_cb[type(obj)](obj)
+    def _name_to_param_name(self, prefix, name):
+        return 'param_{}_{}'.format(prefix, name)
 
+    def _ev_f_name_to_param_name(self, name):
+        return self._name_to_param_name('evf', name)
 
-_CTX_AT = 'ctx->at'
-_CTX_BUF = 'ctx->buf'
-_CTX_BUF_SIZE = 'ctx->buf_size'
-_CTX_BUF_AT = '{}[{} >> 3]'.format(_CTX_BUF, _CTX_AT)
-_CTX_BUF_AT_ADDR = '&{}'.format(_CTX_BUF_AT)
-_ALIGN_OFFSET = 'ALIGN_OFFSET'
-_CHECK_OFFSET_OVERFLOW_FMT = \
-    'CHECK_OFFSET_OVERFLOW({}, {}, {{}});'.format(_CTX_AT, _CTX_BUF_SIZE)
+    def _ev_c_name_to_param_name(self, name):
+        return self._name_to_param_name('evc', name)
 
+    def _ev_sec_name_to_param_name(self, name):
+        return self._name_to_param_name('evsec', name)
 
-def _field_name_to_param_name(fname):
-    return 'param_{}'.format(fname)
+    def _ev_h_name_to_param_name(self, name):
+        return self._name_to_param_name('evh', name)
 
+    def _s_pc_name_to_param_name(self, name):
+        return self._name_to_param_name('spc', name)
 
-def _get_integer_param_type(integer):
-    signed = 'u' if not integer.signed else ''
+    def _s_ph_name_to_param_name(self, name):
+        return self._name_to_param_name('sph', name)
 
-    if integer.size == 8:
-        sz = '8'
-    elif integer.size == 16:
-        sz = '16'
-    elif integer.size == 32:
-        sz = '32'
-    elif integer.size == 64:
-        sz = '64'
-    else:
-        # if the integer is signed and of uncommon size, the sign bit is
-        # at a custom position anyway so we use a 64-bit unsigned
-        signed = 'u'
+    def _get_integer_param_ctype(self, integer):
+        signed = 'u' if not integer.signed else ''
 
-        if integer.signed:
+        if integer.size == 8:
+            sz = '8'
+        elif integer.size == 16:
+            sz = '16'
+        elif integer.size == 32:
+            sz = '32'
+        elif integer.size == 64:
             sz = '64'
         else:
-            if integer.size < 16:
-                sz = '8'
-            elif integer.size < 32:
-                sz = '16'
-            elif integer.size < 64:
-                sz = '32'
-            else:
-                sz = '64'
-
-    return '{}int{}_t'.format(signed, sz)
-
-
-def _get_enum_param_type(enum):
-    return _get_obj_param_type(enum.integer)
-
-
-def _get_floating_point_param_type(fp):
-    if fp.exp_dig == 8 and fp.mant_dig == 24 and fp.align == 32:
-        return 'float'
-    elif fp.exp_dig == 11 and fp.mant_dig == 53 and fp.align == 64:
-        return 'double'
-    else:
-        return 'uint64_t'
-
-
-_obj_param_type_cb = {
-    pytsdl.tsdl.Struct: lambda obj: 'const void*',
-    pytsdl.tsdl.Integer: _get_integer_param_type,
-    pytsdl.tsdl.Enum: _get_enum_param_type,
-    pytsdl.tsdl.FloatingPoint: _get_floating_point_param_type,
-    pytsdl.tsdl.Array: lambda obj: 'const void*',
-    pytsdl.tsdl.Sequence: lambda obj: 'const void*',
-    pytsdl.tsdl.String: lambda obj: 'const char*',
-}
-
-
-def _get_obj_param_type(obj):
-    return _obj_param_type_cb[type(obj)](obj)
-
-
-class _CBlock(list):
-    pass
-
-
-class _CLine(str):
-    pass
-
-
-def _get_check_offset_overflow_cline(size):
-    return _CLine(_CHECK_OFFSET_OVERFLOW_FMT.format(size))
-
-
-def _write_field_struct(doc, fname, struct):
-    size = _get_struct_size(struct)
-    size_bytes = _get_alignment(size, 8) // 8
-
-    dst = _CTX_BUF_AT_ADDR
-    src = _field_name_to_param_name(fname)
+            # if the integer is signed and of uncommon size, the sign bit is
+            # at a custom position anyway so we use a 64-bit unsigned
+            signed = 'u'
 
-    return [
-        # memcpy() is safe since barectf requires inner structures
-        # to be byte-aligned
-        _get_check_offset_overflow_cline(size),
-        _CLine('memcpy({}, {}, {});'.format(dst, src, size_bytes)),
-        _CLine('{} += {};'.format(_CTX_AT, size)),
-    ]
-
-
-_bo_suffixes_map = {
-    pytsdl.tsdl.ByteOrder.BE: 'be',
-    pytsdl.tsdl.ByteOrder.LE: 'le',
-}
-
-
-def _write_field_integer(doc, fname, integer):
-    bo = _bo_suffixes_map[integer.byte_order]
-    ptr = _CTX_BUF
-    t = _get_obj_param_type(integer)
-    start = _CTX_AT
-    length = _get_obj_size(integer)
-    value = _field_name_to_param_name(fname)
-    fmt = 'barectf_bitfield_write_{}({}, {}, {}, {}, {});'
-
-    return [
-        _get_check_offset_overflow_cline(length),
-        _CLine(fmt.format(bo, ptr, t, start, length, value)),
-        _CLine('{} += {};'.format(_CTX_AT, length))
-    ]
-
-
-def _write_field_enum(doc, fname, enum):
-    return _write_field_obj(doc, fname, enum.integer)
-
-
-def _write_field_floating_point(doc, fname, floating_point):
-    bo = _bo_suffixes_map[floating_point.byte_order]
-    ptr = _CTX_BUF
-    t = _get_obj_param_type(floating_point)
-    start = _CTX_AT
-    length = _get_obj_size(floating_point)
-    value = _field_name_to_param_name(fname)
-    fmt = 'barectf_bitfield_write_{}({}, {}, {}, {}, {});'
-
-    return [
-        _get_check_offset_overflow_cline(length),
-        _CLine(fmt.format(bo, ptr, t, start, length, value)),
-        _CLine('{} += {};'.format(_CTX_AT, length))
-    ]
-
-
-def _write_field_array(doc, fname, array):
-    lines = []
-
-    # array index variable declaration
-    iv = 'ia_{}'.format(fname)
-    lines.append(_CLine('uint32_t {};'.format(iv)))
-
-    # for loop using array's static length
-    line = 'for ({iv} = 0; {iv} < {l}; ++{iv}) {{'.format(iv=iv, l=array.length)
-    lines.append(_CLine(line))
-
-    # for loop statements
-    for_block = _CBlock()
+            if integer.signed:
+                sz = '64'
+            else:
+                if integer.size < 16:
+                    sz = '8'
+                elif integer.size < 32:
+                    sz = '16'
+                elif integer.size < 64:
+                    sz = '32'
+                else:
+                    sz = '64'
 
-    # align bit index before writing to the buffer
-    element_align = _get_obj_alignment(array.element)
-    line = '{}({}, {});'.format(_ALIGN_OFFSET, _CTX_AT, element_align)
-    for_block.append(_CLine(line))
+        return '{}int{}_t'.format(signed, sz)
 
-    # write element to the buffer
-    for_block += _write_field_obj(doc, fname, array.element)
-    lines.append(for_block)
+    def _get_enum_param_ctype(self, enum):
+        return self._get_obj_param_ctype(enum.integer)
 
-    # for loop end
-    lines.append(_CLine('}'))
+    def _get_floating_point_param_ctype(self, fp):
+        if fp.exp_dig == 8 and fp.mant_dig == 24 and fp.align == 32:
+            return 'float'
+        elif fp.exp_dig == 11 and fp.mant_dig == 53 and fp.align == 64:
+            return 'double'
+        else:
+            return 'uint64_t'
+
+    def _get_obj_param_ctype(self, obj):
+        return self._obj_param_ctype_cb[type(obj)](obj)
+
+    def _get_chk_offset_v(self, size):
+        fmt = '{}_CHK_OFFSET_V({}, {}, {});'
+        ret = fmt.format(self._prefix.upper(), self._CTX_AT,
+                       self._CTX_BUF_SIZE, size)
+
+        return ret
+
+    def _get_chk_offset_v_cline(self, size):
+        return _CLine(self._get_chk_offset_v(size))
+
+    def _get_align_offset(self, align):
+        fmt = '{}_ALIGN_OFFSET({}, {});'
+        ret = fmt.format(self._prefix.upper(), self._CTX_AT, align)
+
+        return ret
+
+    def _get_align_offset_cline(self, size):
+        return _CLine(self._get_align_offset(size))
+
+    def _write_field_struct(self, fname, src_name, struct):
+        size = self._get_struct_size(struct)
+        size_bytes = self._get_alignment(size, 8) // 8
+        dst = self._CTX_BUF_AT_ADDR
+
+        return [
+            # memcpy() is safe since barectf requires inner structures
+            # to be byte-aligned
+            self._get_chk_offset_v_cline(size),
+            _CLine('memcpy({}, {}, {});'.format(dst, src_name, size_bytes)),
+            _CLine('{} += {};'.format(self._CTX_AT, size)),
+        ]
+
+    def _write_field_integer(self, fname, src_name, integer):
+        bo = self._bo_suffixes_map[integer.byte_order]
+        ptr = self._CTX_BUF
+        t = self._get_obj_param_ctype(integer)
+        start = self._CTX_AT
+        length = self._get_obj_size(integer)
+        fmt = 'barectf_bitfield_write_{}({}, {}, {}, {}, {});'
+
+        return [
+            self._get_chk_offset_v_cline(length),
+            _CLine(fmt.format(bo, ptr, t, start, length, src_name)),
+            _CLine('{} += {};'.format(self._CTX_AT, length))
+        ]
+
+    def _write_field_enum(self, fname, src_name, enum):
+        return self._write_field_obj(fname, src_name, enum.integer)
+
+    def _write_field_floating_point(self, fname, src_name, floating_point):
+        bo = self._bo_suffixes_map[floating_point.byte_order]
+        ptr = self._CTX_BUF
+        t = self._get_obj_param_ctype(floating_point)
+        start = self._CTX_AT
+        length = self._get_obj_size(floating_point)
+        fmt = 'barectf_bitfield_write_{}({}, {}, {}, {}, {});'
+
+        return [
+            self._get_chk_offset_v_cline(length),
+            _CLine(fmt.format(bo, ptr, t, start, length, src_name)),
+            _CLine('{} += {};'.format(self._CTX_AT, length))
+        ]
+
+    def _write_field_array(self, fname, src_name, array):
+        lines = []
 
-    return lines
+        # array index variable declaration
+        iv = 'ia_{}'.format(fname)
+        lines.append(_CLine('uint32_t {};'.format(iv)))
 
+        # for loop using array's static length
+        line = 'for ({iv} = 0; {iv} < {l}; ++{iv}) {{'.format(iv=iv, l=array.length)
+        lines.append(_CLine(line))
 
-def _write_field_sequence(doc, fname, sequence):
-    return [
-        _CLine('would write sequence here;'),
-    ]
+        # for loop statements
+        for_block = _CBlock()
 
+        # align bit index before writing to the buffer
+        element_align = self._get_obj_alignment(array.element)
+        cline = self._get_align_offset_cline(element_align)
+        for_block.append(cline)
 
-def _write_field_string(doc, fname, string):
-    lines = []
+        # write element to the buffer
+        for_block += self._write_field_obj(fname, src_name, array.element)
+        lines.append(for_block)
 
-    # source pointer (function parameter)
-    src = _field_name_to_param_name(fname)
+        # for loop end
+        lines.append(_CLine('}'))
 
-    # string index variable declaration
-    iv = 'is_{}'.format(fname)
-    lines.append(_CLine('uint32_t {};'.format(iv)))
+        return lines
 
-    # for loop; loop until the end of the source string is reached
-    fmt = "for ({iv} = 0; {src}[{iv}] != '\\0'; ++{iv}, {ctxat} += 8) {{"
-    lines.append(_CLine(fmt.format(iv=iv, src=src, ctxat=_CTX_AT)))
+    def _write_field_sequence(self, fname, src_name, sequence):
+        return [
+            _CLine('would write sequence here;'),
+        ]
 
-    # for loop statements
-    for_block = _CBlock()
+    def _write_field_string(self, fname, src_name, string):
+        lines = []
 
-    # check offset overflow
-    for_block.append(_get_check_offset_overflow_cline(8))
+        # string index variable declaration
+        iv = 'is_{}'.format(fname)
+        lines.append(_CLine('uint32_t {};'.format(iv)))
 
-    # write byte to the buffer
-    line = '{} = {}[{}]'.format(_CTX_BUF_AT, src, iv)
-    for_block.append(_CLine(line))
+        # for loop; loop until the end of the source string is reached
+        fmt = "for ({iv} = 0; {src}[{iv}] != '\\0'; ++{iv}, {ctxat} += 8) {{"
+        line = fmt.format(iv=iv, src=src_name, ctxat=self._CTX_AT)
+        lines.append(_CLine(line))
 
-    # append for loop
-    lines.append(for_block)
-    lines.append(_CLine('}'))
+        # for loop statements
+        for_block = _CBlock()
 
-    # write NULL character to the buffer
-    lines.append(_CLine("{} = '\\0';".format(_CTX_BUF_AT)))
-    lines.append(_CLine('{} += 8;'.format(_CTX_AT)))
+        # check offset overflow
+        for_block.append(self._get_chk_offset_v_cline(8))
 
-    return lines
+        # write byte to the buffer
+        fmt = '{dst} = {src}[{iv}];'
+        line = fmt.format(dst=self._CTX_BUF_AT, iv=iv, src=src_name)
+        for_block.append(_CLine(line))
 
+        # append for loop
+        lines.append(for_block)
+        lines.append(_CLine('}'))
 
-_write_field_obj_cb = {
-    pytsdl.tsdl.Struct: _write_field_struct,
-    pytsdl.tsdl.Integer: _write_field_integer,
-    pytsdl.tsdl.Enum: _write_field_enum,
-    pytsdl.tsdl.FloatingPoint: _write_field_floating_point,
-    pytsdl.tsdl.Array: _write_field_array,
-    pytsdl.tsdl.Sequence: _write_field_sequence,
-    pytsdl.tsdl.String: _write_field_string,
-}
+        # write NULL character to the buffer
+        lines.append(_CLine("{} = '\\0';".format(self._CTX_BUF_AT)))
+        lines.append(_CLine('{} += 8;'.format(self._CTX_AT)))
 
+        return lines
 
-def _write_field_obj(doc, fname, ftype):
-    return _write_field_obj_cb[type(ftype)](doc, fname, ftype)
+    def _write_field_obj(self, fname, src_name, ftype):
+        return self._write_field_obj_cb[type(ftype)](fname, src_name, ftype)
 
+    def _get_offvar_name(self, name):
+        return 'off_{}'.format(name)
 
-def _struct_to_clines(doc, struct):
-    line_groups = []
+    def _get_offvar_name_from_expr(self, expr):
+        return self._get_offvar_name('_'.join(expr))
 
-    for fname, ftype in struct.fields.items():
+    def _field_to_cline(self, fname, ftype, scope_name, param_name_cb):
         lines = []
-        pname = _field_name_to_param_name(fname)
-        align = _get_obj_alignment(ftype)
+        pname = param_name_cb(fname)
+        align = self._get_obj_alignment(ftype)
+
+        # group comment
+        fmt = '/* write {} field "{}" ({}) */'
+        line = fmt.format(scope_name, fname,
+                          self._tsdl_type_names_map[type(ftype)])
+        lines.append(_CLine(line))
 
         # align bit index before writing to the buffer
-        line = '{}({}, {});'.format(_ALIGN_OFFSET, _CTX_AT, align)
-        lines.append(line)
+        cline = self._get_align_offset_cline(align)
+        lines.append(cline)
 
         # write offset variables
         if type(ftype) is pytsdl.tsdl.Struct:
-            offset_vars_tree = collections.OrderedDict()
-            _get_struct_size(ftype, offset_vars_tree)
-            offset_vars = _offset_vars_tree_to_vars(offset_vars_tree)
+            offvars_tree = collections.OrderedDict()
+            self._get_struct_size(ftype, offvars_tree)
+            off_vars = self._offvars_tree_to_vars(offvars_tree)
 
             # as many offset as there are child fields because a future
             # sequence could refer to any of those fields
-            for lname, offset in offset_vars.items():
-                fmt = 'uint32_t off_{}_{} = {} + {};'
-                line = fmt.format(fname, lname, _CTX_AT, offset);
+            for lname, offset in off_vars.items():
+                print(fname, lname)
+                offvar = self._get_offvar_name('_'.join([fname, lname]))
+                fmt = 'uint32_t {} = {} + {};'
+                line = fmt.format(offvar, self._CTX_AT, offset);
                 lines.append(_CLine(line))
         elif type(ftype) is pytsdl.tsdl.Integer:
             # offset of this simple field is the current bit index
-            line = 'uint32_t off_{} = {};'.format(fname, _CTX_AT)
+            offvar = self._get_offvar_name(fname)
+            line = 'uint32_t {} = {};'.format(offvar, self._CTX_AT)
             lines.append(_CLine(line))
 
-        lines += _write_field_obj(doc, fname, ftype)
-        line_groups.append(lines)
-
-    if not line_groups:
-        return line_groups
+        lines += self._write_field_obj(fname, pname, ftype)
 
-    output_lines = line_groups[0]
+        return lines
 
-    for lines in line_groups[1:]:
-        output_lines.append('')
-        output_lines += lines
+    def _struct_to_clines(self, struct, scope_name, param_name_cb):
+        line_groups = []
 
-    return output_lines
+        for fname, ftype in struct.fields.items():
+            lines = self._field_to_cline(fname, ftype, scope_name,
+                                         param_name_cb)
+            line_groups.append(lines)
 
+        if not line_groups:
+            return line_groups
 
-def _cblock_to_source_lines(cblock, indent=1):
-    src = []
-    indentstr = '\t' * indent
+        output_lines = line_groups[0]
 
-    for line in cblock:
-        if type(line) is _CBlock:
-            src += _cblock_to_source_lines(line, indent + 1)
-        else:
-            src.append(indentstr + line)
+        for lines in line_groups[1:]:
+            output_lines.append('')
+            output_lines += lines
 
-    return src
+        return output_lines
 
+    def _cblock_to_source_lines(self, cblock, indent=1):
+        src = []
+        indentstr = '\t' * indent
 
-def _cblock_to_source(cblock, indent=1):
-    lines = _cblock_to_source_lines(cblock, indent)
+        for line in cblock:
+            if type(line) is _CBlock:
+                src += self._cblock_to_source_lines(line, indent + 1)
+            else:
+                src.append(indentstr + line)
 
-    return '\n'.join(lines)
+        return src
 
+    def _cblock_to_source(self, cblock, indent=1):
+        lines = self._cblock_to_source_lines(cblock, indent)
 
-def gen_barectf(metadata, output, prefix, static_inline, manual_clock):
-    # open CTF metadata file
-    try:
-        with open(metadata) as f:
-            tsdl = f.read()
-    except:
-        _perror('cannot open/read CTF metadata file "{}"'.format(metadata))
+        return '\n'.join(lines)
 
-    # parse CTF metadata
-    parser = pytsdl.parser.Parser()
+    def gen_barectf(self, metadata, output, prefix, static_inline,
+                    manual_clock):
+        self._metadata = metadata
+        self._output = output
+        self._prefix = prefix
+        self._static_inline = static_inline
+        self._manual_clock = manual_clock
 
-    try:
-        doc = parser.parse(tsdl)
-    except pytsdl.parser.ParseError as e:
-        _perror('parse error: {}'.format(e))
+        # open CTF metadata file
+        try:
+            with open(metadata) as f:
+                self._tsdl = f.read()
+        except:
+            _perror('cannot open/read CTF metadata file "{}"'.format(metadata))
 
-    # validate CTF metadata against barectf constraints
-    _validate_metadata(doc)
+        # parse CTF metadata
+        try:
+            self._doc = self._parser.parse(self._tsdl)
+        except pytsdl.parser.ParseError as e:
+            _perror('parse error: {}'.format(e))
 
-    import json
+        # validate CTF metadata against barectf constraints
+        self._validate_metadata()
 
-    clines = _struct_to_clines(doc, doc.streams[0].get_event(0).fields)
-    print(_cblock_to_source(_CBlock(clines)))
+        clines = self._struct_to_clines(self._doc.streams[0].get_event(0).fields,
+                                        'stream event context',
+                                        self._ev_f_name_to_param_name)
+        source = self._cblock_to_source(_CBlock(clines))
 
 
 def run():
     args = _parse_args()
-    gen_barectf(args.metadata, args.output, args.prefix, args.static_inline,
-                args.manual_clock)
+    generator = BarectfCodeGenerator()
+    generator.gen_barectf(args.metadata, args.output, args.prefix,
+                          args.static_inline, args.manual_clock)
This page took 0.039368 seconds and 4 git commands to generate.