+++ /dev/null
-# The MIT License (MIT)
-#
-# Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class _CodeGenerator:
- def __init__(self, indent_string):
- self._indent_string = indent_string
- self.reset()
-
- @property
- def code(self):
- return '\n'.join(self._lines)
-
- def reset(self):
- self._lines = []
- self._indent = 0
- self._glue = False
-
- def add_line(self, line):
- if self._glue:
- self.append_to_last_line(line)
- self._glue = False
- return
-
- indent_string = self._get_indent_string()
- self._lines.append(indent_string + str(line))
-
- def add_lines(self, lines):
- if type(lines) is str:
- lines = lines.split('\n')
-
- for line in lines:
- self.add_line(line)
-
- def add_glue(self):
- self._glue = True
-
- def append_to_last_line(self, s):
- if self._lines:
- self._lines[-1] += str(s)
-
- def add_empty_line(self):
- self._lines.append('')
-
- def add_cc_line(self, comment):
- self.add_line('/* {} */'.format(comment))
-
- def append_cc_to_last_line(self, comment, with_space=True):
- if with_space:
- sp = ' '
- else:
- sp = ''
-
- self.append_to_last_line('{}/* {} */'.format(sp, comment))
-
- def indent(self):
- self._indent += 1
-
- def unindent(self):
- self._indent = max(self._indent - 1, 0)
-
- def _get_indent_string(self):
- return self._indent_string * self._indent
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import barectf.tsdl182gen as barectf_tsdl182gen
-import barectf.templates as barectf_templates
import barectf.template as barectf_template
-import barectf.codegen as barectf_codegen
import barectf.config as barectf_config
import barectf.version as barectf_version
import itertools
import datetime
+import collections
import copy
+# A file generated by a `CodeGenerator` object.
+#
+# A generated file has a name (influenced by the configuration's
+# file name prefix option) and contents.
class _GeneratedFile:
def __init__(self, name, contents):
self._name = name
return self._contents
+# A barectf code generator.
+#
+# Build a code generator with a barectf configuration.
+#
+# A code generator can generate the TSDL `metadata` file and C source
+# and header files.
class CodeGenerator:
def __init__(self, configuration):
self._config = configuration
return self._metadata_stream
-def _align(v, align):
- return (v + (align - 1)) & -align
+# A tuple containing serialization and size computation function
+# templates for a given operation.
+_OpTemplates = collections.namedtuple('_OpTemplates', ['serialize', 'size'])
-class _SerializationAction:
- def __init__(self, offset_in_byte, ft, names):
+# Base class of any operation within source code.
+#
+# Any operation has:
+#
+# * An offset at which to start to write within the current byte.
+#
+# * A field type.
+#
+# * A list of names which, when joined with `_`, form the generic C
+# source variable name.
+#
+# * Serialization and size computation templates to generate the
+# operation's source code for those functions.
+class _Op:
+ def __init__(self, offset_in_byte, ft, names, templates):
assert(offset_in_byte >= 0 and offset_in_byte < 8)
self._offset_in_byte = offset_in_byte
self._ft = ft
- self._names = copy.deepcopy(names)
+ self._names = copy.copy(names)
+ self._templates = templates
@property
def offset_in_byte(self):
def names(self):
return self._names
+ @property
+ def top_name(self):
+ return self._names[-1]
-class _AlignSerializationAction(_SerializationAction):
- def __init__(self, offset_in_byte, ft, names, value):
- super().__init__(offset_in_byte, ft, names)
+ def _render_template(self, templ, **kwargs):
+ return templ.render(op=self, root_ft_prefixes=_RootFtPrefixes,
+ root_ft_prefix_names=_ROOT_FT_PREFIX_NAMES, **kwargs)
+
+ def serialize_str(self, **kwargs):
+ return self._render_template(self._templates.serialize, **kwargs)
+
+ def size_str(self, **kwargs):
+ return self._render_template(self._templates.size, **kwargs)
+
+
+# An "align" operation.
+class _AlignOp(_Op):
+ def __init__(self, offset_in_byte, ft, names, templates, value):
+ super().__init__(offset_in_byte, ft, names, templates)
self._value = value
@property
return self._value
-class _SerializeSerializationAction(_SerializationAction):
+# A "write" operation.
+class _WriteOp(_Op):
pass
-class _SerializationActions:
- def __init__(self):
- self.reset()
-
- def reset(self):
+# A builder of a chain of operations.
+#
+# Such a builder is closely connected to a `_CCodeGenerator` object
+# using it to find generic templates.
+#
+# Call append_root_ft() to make an operation builder append operations
+# to itself for each member, recursively, of the structure field type.
+#
+# Get an operation builder's operations with its `ops` property.
+class _OpsBuilder:
+ def __init__(self, cg):
self._last_alignment = None
self._last_bit_array_size = None
- self._actions = []
+ self._ops = []
self._names = []
self._offset_in_byte = 0
+ self._cg = cg
- def append_root_scope_ft(self, ft, name):
+ @property
+ def ops(self):
+ return self._ops
+
+ # Creates and appends the operations for the members, recursively,
+ # of the root structure field type `ft` named `name`.
+ #
+ # `spec_serialize_write_templates` is a mapping of first level
+ # member names to specialized serialization "write" templates.
+ def append_root_ft(self, ft, name, spec_serialize_write_templates=None):
if ft is None:
return
- assert(type(ft) is barectf_config.StructureFieldType)
- self._names = [name]
- self._append_ft(ft)
+ if spec_serialize_write_templates is None:
+ spec_serialize_write_templates = {}
+
+ assert type(ft) is barectf_config.StructureFieldType
+ assert len(self._names) == 0
+ self._append_ft(ft, name, spec_serialize_write_templates)
+
+ # Creates and appends the operations of a given field type `ft`
+ # named `name`.
+ #
+ # See append_root_ft() for `spec_serialize_write_templates`.
+ def _append_ft(self, ft, name, spec_serialize_write_templates):
+ def top_name():
+ return self._names[-1]
+
+ # Appends a "write" operation for the field type `ft`.
+ #
+ # This function considers `spec_serialize_write_templates` to
+ # override generic templates.
+ def append_write_op(ft):
+ assert type(ft) is not barectf_config.StructureFieldType
+ offset_in_byte = self._offset_in_byte
+
+ if isinstance(ft, barectf_config._BitArrayFieldType):
+ self._offset_in_byte += ft.size
+ self._offset_in_byte %= 8
+
+ serialize_write_templ = None
+
+ if len(self._names) == 2:
+ serialize_write_templ = spec_serialize_write_templates.get(top_name())
+
+ if serialize_write_templ is None:
+ if isinstance(ft, barectf_config._IntegerFieldType):
+ serialize_write_templ = self._cg._serialize_write_int_statements_templ
+ elif type(ft) is barectf_config.RealFieldType:
+ serialize_write_templ = self._cg._serialize_write_real_statements_templ
+ else:
+ assert type(ft) is barectf_config.StringFieldType
+ serialize_write_templ = self._cg._serialize_write_string_statements_templ
+
+ size_write_templ = None
- @property
- def actions(self):
- return self._actions
+ if isinstance(ft, barectf_config._BitArrayFieldType):
+ size_write_templ = self._cg._size_write_bit_array_statements_templ
+ elif type(ft) is barectf_config.StringFieldType:
+ size_write_templ = self._cg._size_write_string_statements_templ
+
+ self._ops.append(_WriteOp(offset_in_byte, ft, self._names,
+ _OpTemplates(serialize_write_templ, size_write_templ)))
+
+ # Creates and appends an "align" operation for the field type
+ # `ft` if needed.
+ #
+ # This function updates the builder's state.
+ def try_append_align_op(alignment, do_align, ft):
+ def align(v, alignment):
+ return (v + (alignment - 1)) & -alignment
+
+ offset_in_byte = self._offset_in_byte
+ self._offset_in_byte = align(self._offset_in_byte, alignment) % 8
+
+ if do_align and alignment > 1:
+ self._ops.append(_AlignOp(offset_in_byte, ft, self._names,
+ _OpTemplates(self._cg._serialize_align_statements_templ,
+ self._cg._size_align_statements_templ),
+ alignment))
- def align(self, alignment):
- do_align = self._must_align(alignment)
- self._last_alignment = alignment
- self._last_bit_array_size = alignment
- self._try_append_align_action(alignment, do_align)
+ # Returns whether or not, considering the alignment requirement
+ # `align_req` and the builder's current state, we must create
+ # and append an "align" operation.
+ def must_align(align_req):
+ return self._last_alignment != align_req or self._last_bit_array_size % align_req != 0
- def _must_align(self, align_req):
- return self._last_alignment != align_req or self._last_bit_array_size % align_req != 0
+ # push field type's name to the builder's name stack initially
+ self._names.append(name)
- def _append_ft(self, ft):
if isinstance(ft, (barectf_config.StringFieldType, barectf_config._ArrayFieldType)):
- assert(type(ft) is barectf_config.StringFieldType or self._names[-1] == 'uuid')
- do_align = self._must_align(8)
+ assert type(ft) is barectf_config.StringFieldType or top_name() == 'uuid'
+
+ # strings and arrays are always byte-aligned
+ do_align = must_align(8)
self._last_alignment = 8
self._last_bit_array_size = 8
- self._try_append_align_action(8, do_align, ft)
- self._append_serialize_action(ft)
+ try_append_align_op(8, do_align, ft)
+ append_write_op(ft)
else:
- do_align = self._must_align(ft.alignment)
+ do_align = must_align(ft.alignment)
self._last_alignment = ft.alignment
if type(ft) is barectf_config.StructureFieldType:
else:
self._last_bit_array_size = ft.size
- self._try_append_align_action(ft.alignment, do_align, ft)
+ try_append_align_op(ft.alignment, do_align, ft)
if type(ft) is barectf_config.StructureFieldType:
for member_name, member in ft.members.items():
- self._names.append(member_name)
- self._append_ft(member.field_type)
- del self._names[-1]
+ self._append_ft(member.field_type, member_name, spec_serialize_write_templates)
else:
- self._append_serialize_action(ft)
+ append_write_op(ft)
+
+ # exiting for this field type: pop its name
+ del self._names[-1]
- def _try_append_align_action(self, alignment, do_align, ft=None):
- offset_in_byte = self._offset_in_byte
- self._offset_in_byte = _align(self._offset_in_byte, alignment) % 8
- if do_align and alignment > 1:
- self._actions.append(_AlignSerializationAction(offset_in_byte, ft, self._names,
- alignment))
+# The operations for an event.
+#
+# The available operations are:
+#
+# * Specific context operations.
+# * Payload operations.
+class _EventOps:
+ def __init__(self, spec_ctx_ops, payload_ops):
+ self._spec_ctx_ops = copy.copy(spec_ctx_ops)
+ self._payload_ops = copy.copy(payload_ops)
- def _append_serialize_action(self, ft):
- assert(type(ft) is not barectf_config.StructureFieldType)
- offset_in_byte = self._offset_in_byte
+ @property
+ def spec_ctx_ops(self):
+ return self._spec_ctx_ops
- if isinstance(ft, barectf_config._BitArrayFieldType):
- self._offset_in_byte += ft.size
- self._offset_in_byte %= 8
+ @property
+ def payload_ops(self):
+ return self._payload_ops
- self._actions.append(_SerializeSerializationAction(offset_in_byte, ft, self._names))
+# The operations for a stream.
+#
+# The available operations are:
+#
+# * Packet header operations.
+# * Packet context operations.
+# * Event header operations.
+# * Event common context operations.
+# * Event operations (`_EventOps`).
+class _StreamOps:
+ def __init__(self, pkt_header_ops, pkt_ctx_ops, ev_header_ops,
+ ev_common_ctx_ops, ev_ops):
+ self._pkt_header_ops = copy.copy(pkt_header_ops)
+ self._pkt_ctx_ops = copy.copy(pkt_ctx_ops)
+ self._ev_header_ops = copy.copy(ev_header_ops)
+ self._ev_common_ctx_ops = copy.copy(ev_common_ctx_ops)
+ self._ev_ops = copy.copy(ev_ops)
+ @property
+ def pkt_header_ops(self):
+ return self._pkt_header_ops
+
+ @property
+ def pkt_ctx_ops(self):
+ return self._pkt_ctx_ops
+
+ @property
+ def ev_header_ops(self):
+ return self._ev_header_ops
+
+ @property
+ def ev_common_ctx_ops(self):
+ return self._ev_common_ctx_ops
+
+ @property
+ def ev_ops(self):
+ return self._ev_ops
+
+
+# The C variable name prefixes for the six kinds of root field types.
class _RootFtPrefixes:
- TPH = 'tph_'
- SPC = 'spc_'
- SEH = 'seh_'
- SEC = 'sec_'
- EC = 'ec_'
- EP = 'ep_'
-
-
-_ROOT_FT_PREFIX_TO_NAME = {
- _RootFtPrefixes.TPH: 'trace packet header',
- _RootFtPrefixes.SPC: 'stream packet context',
- _RootFtPrefixes.SEH: 'stream event header',
- _RootFtPrefixes.SEC: 'stream event context',
- _RootFtPrefixes.EC: 'event context',
- _RootFtPrefixes.EP: 'event payload',
+ TPH = 'tph'
+ SPC = 'spc'
+ SEH = 'seh'
+ SEC = 'sec'
+ EC = 'ec'
+ EP = 'ep'
+
+
+# The human-readable names of the `_RootFtPrefixes` members.
+_ROOT_FT_PREFIX_NAMES = {
+ _RootFtPrefixes.TPH: 'packet header',
+ _RootFtPrefixes.SPC: 'packet context',
+ _RootFtPrefixes.SEH: 'event header',
+ _RootFtPrefixes.SEC: 'event common context',
+ _RootFtPrefixes.EC: 'specific context',
+ _RootFtPrefixes.EP: 'payload',
}
+# A named function parameter for a given field type.
+_FtParam = collections.namedtuple('_FtParam', ['ft', 'name'])
+
+
+# A C code generator.
+#
+# Such a code generator can generate:
+#
+# * The bitfield header (generate_bitfield_header()).
+# * The public header (generate_header()).
+# * The source code (generate_c_src()).
class _CCodeGenerator:
def __init__(self, cfg):
self._cfg = cfg
- code_gen_opts = cfg.options.code_generation_options
- self._iden_prefix = code_gen_opts.identifier_prefix
- self._cg = barectf_codegen._CodeGenerator('\t')
- self._saved_serialization_actions = {}
-
- @property
- def _template_filters(self):
- return {
- 'ft_c_type': self._get_ft_c_type,
+ self._iden_prefix = cfg.options.code_generation_options.identifier_prefix
+ self._saved_serialization_ops = {}
+ self._templ_filters = {
+ 'ft_c_type': self._ft_c_type,
+ 'open_func_params_str': self._open_func_params_str,
+ 'trace_func_params_str': self._trace_func_params_str,
+ 'serialize_ev_common_ctx_func_params_str': self._serialize_ev_common_ctx_func_params_str,
}
-
+ self._func_proto_params_templ = self._create_template('func-proto-params.j2')
+ self._serialize_align_statements_templ = self._create_template('serialize-align-statements.j2')
+ self._serialize_write_int_statements_templ = self._create_template('serialize-write-int-statements.j2')
+ self._serialize_write_real_statements_templ = self._create_template('serialize-write-real-statements.j2')
+ self._serialize_write_string_statements_templ = self._create_template('serialize-write-string-statements.j2')
+ self._serialize_write_magic_statements_templ = self._create_template('serialize-write-magic-statements.j2')
+ self._serialize_write_uuid_statements_templ = self._create_template('serialize-write-uuid-statements.j2')
+ self._serialize_write_stream_type_id_statements_templ = self._create_template('serialize-write-stream-type-id-statements.j2')
+ self._serialize_write_time_statements_templ = self._create_template('serialize-write-time-statements.j2')
+ self._serialize_write_packet_size_statements_templ = self._create_template('serialize-write-packet-size-statements.j2')
+ self._serialize_write_skip_save_statements_templ = self._create_template('serialize-write-skip-save-statements.j2')
+ self._serialize_write_ev_type_id_statements_templ = self._create_template('serialize-write-ev-type-id-statements.j2')
+ self._size_align_statements_templ = self._create_template('size-align-statements.j2')
+ self._size_write_bit_array_statements_templ = self._create_template('size-write-bit-array-statements.j2')
+ self._size_write_string_statements_templ = self._create_template('size-write-string-statements.j2')
+
+ # Creates and returns a template named `name` which is a file
+ # template if `is_file_template` is `True`.
+ #
+ # `name` is the file name, including the `.j2` extension, within the
+ # `c` directory.
+ #
+ # Such a template has the filters custom filters
+ # `self._templ_filters`.
+ def _create_template_base(self, name: str, is_file_template: bool):
+ return barectf_template._Template(f'c/{name}', is_file_template, self._cfg,
+ self._templ_filters)
+
+ # Creates and returns a non-file template named `name`.
+ #
+ # See _create_template_base() for `name`.
def _create_template(self, name: str) -> barectf_template._Template:
- return barectf_template._Template(name, False, self._cfg, self._template_filters)
+ return self._create_template_base(name, False)
+ # Creates and returns a file template named `name`.
+ #
+ # See _create_template_base() for `name`.
def _create_file_template(self, name: str) -> barectf_template._Template:
- return barectf_template._Template(name, True, self._cfg, self._template_filters)
+ return self._create_template_base(name, True)
+ # Trace type of this code generator's barectf configuration.
@property
def _trace_type(self):
return self._cfg.trace.type
- def _clk_type_c_type(self, clk_type):
- return self._cfg.options.code_generation_options.clock_type_c_types[clk_type]
-
- def generate_bitfield_header(self):
- return self._create_file_template('bitfield.h.j2').render()
-
- def _generate_func_init_proto(self):
- tmpl = barectf_templates._FUNC_INIT_PROTO
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix))
-
- def _get_ft_c_type(self, ft):
+ # Returns the C type for the field type `ft`.
+ def _ft_c_type(self, ft):
if isinstance(ft, barectf_config._IntegerFieldType):
sign_prefix = 'u' if isinstance(ft, barectf_config.UnsignedIntegerFieldType) else ''
elif ft.size <= 32:
sz = 32
else:
- assert ft.size == 64
+ assert ft.size <= 64
sz = 64
return f'{sign_prefix}int{sz}_t'
assert type(ft) is barectf_config.StringFieldType
return 'const char *'
- def _generate_ft_c_type(self, ft):
- c_type = self._get_ft_c_type(ft)
- self._cg.append_to_last_line(c_type)
-
- def _generate_proto_param(self, ft, name):
- self._generate_ft_c_type(ft)
- self._cg.append_to_last_line(' ')
- self._cg.append_to_last_line(name)
+ # Returns the function prototype parameters for the members of the
+ # root structure field type `root_ft`.
+ #
+ # Each parameter has the prefix `name_prefix` followed with `_`.
+ #
+ # Members of which the name is in `exclude_set` are excluded.
+ def _proto_params_str(self, root_ft, name_prefix, exclude_set=None):
+ if root_ft is None:
+ return
- def _generate_proto_params(self, ft, name_prefix, exclude_set=None):
if exclude_set is None:
exclude_set = set()
- self._cg.indent()
+ params = []
- for member_name, member in ft.members.items():
+ for member_name, member in root_ft.members.items():
if member_name in exclude_set:
continue
- self._cg.append_to_last_line(',')
- self._cg.add_line('')
- self._generate_proto_param(member.field_type, name_prefix + member_name)
-
- self._cg.unindent()
+ params.append(_FtParam(member.field_type, member_name))
- def _generate_func_open_proto(self, stream_type):
- tmpl = barectf_templates._FUNC_OPEN_PROTO_BEGIN
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name))
+ return self._func_proto_params_templ.render(params=params, prefix=name_prefix)
- if self._trace_type._pkt_header_ft is not None:
- self._generate_proto_params(self._trace_type._pkt_header_ft, _RootFtPrefixes.TPH,
- {'magic', 'stream_id', 'uuid'})
+ # Returns the packet opening function prototype parameters for the
+ # stream type `stream_type`.
+ def _open_func_params_str(self, stream_type):
+ parts = []
+ parts.append(self._proto_params_str(self._trace_type._pkt_header_ft, _RootFtPrefixes.TPH,
+ {'magic', 'stream_id', 'uuid'}))
exclude_set = {
'timestamp_begin',
'content_size',
'events_discarded',
}
- self._generate_proto_params(stream_type._pkt_ctx_ft, _RootFtPrefixes.SPC, exclude_set)
- tmpl = barectf_templates._FUNC_OPEN_PROTO_END
- self._cg.add_lines(tmpl)
+ parts.append(self._proto_params_str(stream_type._pkt_ctx_ft, _RootFtPrefixes.SPC,
+ exclude_set))
+ return ''.join(parts)
- def _generate_func_close_proto(self, stream_type):
- tmpl = barectf_templates._FUNC_CLOSE_PROTO
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name))
+ # Returns the tracing function prototype parameters for the stream
+ # and event types `stream_ev_types`.
+ def _trace_func_params_str(self, stream_ev_types):
+ stream_type = stream_ev_types[0]
+ ev_type = stream_ev_types[1]
+ parts = []
- def _generate_func_trace_proto_params(self, stream_type, ev_type):
if stream_type._ev_header_ft is not None:
- self._generate_proto_params(stream_type._ev_header_ft,
- _RootFtPrefixes.SEH, {'id', 'timestamp'})
+ parts.append(self._proto_params_str(stream_type._ev_header_ft, _RootFtPrefixes.SEH,
+ {'id', 'timestamp'}))
if stream_type.event_common_context_field_type is not None:
- self._generate_proto_params(stream_type.event_common_context_field_type,
- _RootFtPrefixes.SEC)
+ parts.append(self._proto_params_str(stream_type.event_common_context_field_type,
+ _RootFtPrefixes.SEC))
if ev_type.specific_context_field_type is not None:
- self._generate_proto_params(ev_type.specific_context_field_type, _RootFtPrefixes.EC)
+ parts.append(self._proto_params_str(ev_type.specific_context_field_type,
+ _RootFtPrefixes.EC))
if ev_type.payload_field_type is not None:
- self._generate_proto_params(ev_type.payload_field_type, _RootFtPrefixes.EP)
-
- def _generate_func_trace_proto(self, stream_type, ev_type):
- tmpl = barectf_templates._FUNC_TRACE_PROTO_BEGIN
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name,
- evname=ev_type.name))
- self._generate_func_trace_proto_params(stream_type, ev_type)
- tmpl = barectf_templates._FUNC_TRACE_PROTO_END
- self._cg.add_lines(tmpl)
-
- def generate_header(self):
- return self._create_file_template('barectf.h.j2').render(root_ft_prefixes=_RootFtPrefixes)
+ parts.append(self._proto_params_str(ev_type.payload_field_type, _RootFtPrefixes.EP))
- def _get_call_event_param_list_from_struct_ft(self, ft, prefix, exclude_set=None):
- if exclude_set is None:
- exclude_set = set()
+ return ''.join(parts)
- lst = ''
+ # Returns the event header serialization function prototype
+ # parameters for the stream type `stream_type`.
+ def _serialize_ev_common_ctx_func_params_str(self, stream_type):
+ return self._proto_params_str(stream_type.event_common_context_field_type,
+ _RootFtPrefixes.SEC);
- for member_name in ft.members:
- if member_name in exclude_set:
- continue
-
- lst += f', {prefix}{member_name}'
-
- return lst
-
- def _get_call_event_param_list(self, stream_type, ev_type):
- lst = ''
-
- if stream_type._ev_header_ft is not None:
- lst += self._get_call_event_param_list_from_struct_ft(stream_type._ev_header_ft,
- _RootFtPrefixes.SEH, {'id', 'timestamp'})
-
- if stream_type.event_common_context_field_type is not None:
- lst += self._get_call_event_param_list_from_struct_ft(stream_type.event_common_context_field_type,
- _RootFtPrefixes.SEC)
-
- if ev_type.specific_context_field_type is not None:
- lst += self._get_call_event_param_list_from_struct_ft(ev_type.specific_context_field_type,
- _RootFtPrefixes.EC)
-
- if ev_type.payload_field_type is not None:
- lst += self._get_call_event_param_list_from_struct_ft(ev_type.payload_field_type,
- _RootFtPrefixes.EP)
-
- return lst
-
- def _generate_align(self, at, align):
- self._cg.add_line(f'_ALIGN({at}, {align});')
-
- def _generate_incr_pos(self, var, value):
- self._cg.add_line(f'{var} += {value};')
-
- def _generate_incr_pos_bytes(self, var, value):
- self._generate_incr_pos(var, f'_BYTES_TO_BITS({value})')
-
- def _generate_func_get_event_size_proto(self, stream_type, ev_type):
- tmpl = barectf_templates._FUNC_GET_EVENT_SIZE_PROTO_BEGIN
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name,
- evname=ev_type.name))
- self._generate_func_trace_proto_params(stream_type, ev_type)
- tmpl = barectf_templates._FUNC_GET_EVENT_SIZE_PROTO_END
- self._cg.add_lines(tmpl)
-
- def _generate_func_get_event_size(self, stream_type, ev_type):
- self._generate_func_get_event_size_proto(stream_type, ev_type)
- tmpl = barectf_templates._FUNC_GET_EVENT_SIZE_BODY_BEGIN
- lines = tmpl.format(prefix=self._iden_prefix)
- self._cg.add_lines(lines)
- self._cg.add_empty_line()
- self._cg.indent()
- ser_actions = _SerializationActions()
- ser_actions.append_root_scope_ft(stream_type._ev_header_ft, _RootFtPrefixes.SEH)
- ser_actions.append_root_scope_ft(stream_type.event_common_context_field_type,
- _RootFtPrefixes.SEC)
- ser_actions.append_root_scope_ft(ev_type.specific_context_field_type, _RootFtPrefixes.EC)
- ser_actions.append_root_scope_ft(ev_type.payload_field_type, _RootFtPrefixes.EP)
-
- for action in ser_actions.actions:
- if type(action) is _AlignSerializationAction:
- if action.names:
- if len(action.names) == 1:
- line = f'align {_ROOT_FT_PREFIX_TO_NAME[action.names[0]]} structure'
- else:
- line = f'align field `{action.names[-1]}` ({_ROOT_FT_PREFIX_TO_NAME[action.names[0]]})'
-
- self._cg.add_cc_line(line)
-
- self._generate_align('at', action.value)
- self._cg.add_empty_line()
- else:
- assert type(action) is _SerializeSerializationAction
- assert(len(action.names) >= 2)
- line = f'add size of field `{action.names[-1]}` ({_ROOT_FT_PREFIX_TO_NAME[action.names[0]]})'
- self._cg.add_cc_line(line)
-
- if type(action.ft) is barectf_config.StringFieldType:
- param = ''.join(action.names)
- self._generate_incr_pos_bytes('at', f'strlen({param}) + 1')
- else:
- self._generate_incr_pos('at', action.ft.size)
-
- self._cg.add_empty_line()
-
- self._cg.unindent()
- tmpl = barectf_templates._FUNC_GET_EVENT_SIZE_BODY_END
- self._cg.add_lines(tmpl)
-
- def _generate_func_serialize_event_proto(self, stream_type, ev_type):
- tmpl = barectf_templates._FUNC_SERIALIZE_EVENT_PROTO_BEGIN
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name,
- evname=ev_type.name))
- self._generate_func_trace_proto_params(stream_type, ev_type)
- tmpl = barectf_templates._FUNC_SERIALIZE_EVENT_PROTO_END
- self._cg.add_lines(tmpl)
-
- def _generate_serialize_from_action(self, var, ctx, action):
- def gen_bitfield_write(c_type, var, ctx, action):
- ptr = f'&{ctx}->buf[_BITS_TO_BYTES({ctx}->at)]'
- start = action.offset_in_byte
- suffix = 'le' if action.ft.byte_order is barectf_config.ByteOrder.LITTLE_ENDIAN else 'be'
- func = f'{self._iden_prefix}bt_bitfield_write_{suffix}'
- call = f'{func}({ptr}, uint8_t, {start}, {action.ft.size}, {c_type}, ({c_type}) {var});'
- self._cg.add_line(call)
-
- def gen_serialize_int(var, ctx, action):
- c_type = self._get_ft_c_type(action.ft)
- gen_bitfield_write(c_type, var, ctx, action)
- self._generate_incr_pos(f'{ctx}->at', action.ft.size)
-
- def gen_serialize_real(var, ctx, action):
- c_type = self._get_ft_c_type(action.ft)
- flt_dbl = False
-
- if c_type == 'float' or c_type == 'double':
- flt_dbl = True
-
- if c_type == 'float':
- union_name = 'f2u'
- int_c_type = 'uint32_t'
- else:
- assert c_type == 'double'
- union_name = 'd2u'
- int_c_type = 'uint64_t'
-
- # union for reading the bytes of the floating point number
- self._cg.add_empty_line()
- self._cg.add_line('{')
- self._cg.indent()
- self._cg.add_line(f'union {union_name} {union_name};')
- self._cg.add_empty_line()
- self._cg.add_line(f'{union_name}.f = {var};')
- bf_var = f'{union_name}.u'
- else:
- bf_var = f'({c_type}) {var}'
- int_c_type = c_type
-
- gen_bitfield_write(int_c_type, bf_var, ctx, action)
-
- if flt_dbl:
- self._cg.unindent()
- self._cg.add_line('}')
- self._cg.add_empty_line()
-
- self._generate_incr_pos(f'{ctx}->at', action.ft.size)
-
- def gen_serialize_string(var, ctx, action):
- self._cg.add_lines(f'_write_cstring({ctx}, {var});')
-
- if isinstance(action.ft, barectf_config._IntegerFieldType):
- return gen_serialize_int(var, ctx, action)
- elif type(action.ft) is barectf_config.RealFieldType:
- return gen_serialize_real(var, ctx, action)
- else:
- assert type(action.ft) is barectf_config.StringFieldType
- return gen_serialize_string(var, ctx, action)
-
- def _generate_serialize_statements_from_actions(self, prefix, action_iter, spec_src=None):
- for action in action_iter:
- if type(action) is _AlignSerializationAction:
- if action.names:
- if len(action.names) == 1:
- line = f'align {_ROOT_FT_PREFIX_TO_NAME[action.names[0]]} structure'
- else:
- line = f'align field `{action.names[-1]}` ({_ROOT_FT_PREFIX_TO_NAME[action.names[0]]})'
-
- self._cg.add_cc_line(line)
-
- self._generate_align('ctx->at', action.value)
- self._cg.add_empty_line()
- else:
- assert type(action) is _SerializeSerializationAction
- assert(len(action.names) >= 2)
- member_name = action.names[-1]
- line = f'serialize field `{member_name}` ({_ROOT_FT_PREFIX_TO_NAME[action.names[0]]})'
- self._cg.add_cc_line(line)
- src = prefix + member_name
-
- if spec_src is not None and member_name in spec_src:
- src = spec_src[member_name]
-
- self._generate_serialize_from_action(src, 'ctx', action)
- self._cg.add_empty_line()
-
- def _generate_func_serialize_event(self, stream_type, ev_type, orig_ser_actions):
- self._generate_func_serialize_event_proto(stream_type, ev_type)
- tmpl = barectf_templates._FUNC_SERIALIZE_EVENT_BODY_BEGIN
- lines = tmpl.format(prefix=self._iden_prefix)
- self._cg.add_lines(lines)
- self._cg.indent()
- self._cg.add_empty_line()
-
- if stream_type._ev_header_ft is not None:
- params = self._get_call_event_param_list_from_struct_ft(stream_type._ev_header_ft,
- _RootFtPrefixes.SEH,
- {'timestamp', 'id'})
- self._cg.add_cc_line('stream event header')
- line = f'_serialize_stream_event_header_{stream_type.name}(ctx, {ev_type.id}{params});'
- self._cg.add_line(line)
- self._cg.add_empty_line()
-
- if stream_type.event_common_context_field_type is not None:
- params = self._get_call_event_param_list_from_struct_ft(stream_type.event_common_context_field_type,
- _RootFtPrefixes.SEC)
- self._cg.add_cc_line('stream event context')
- line = f'_serialize_stream_event_context_{stream_type.name}(ctx{params});'
- self._cg.add_line(line)
- self._cg.add_empty_line()
-
- if ev_type.specific_context_field_type is not None or ev_type.payload_field_type is not None:
- ser_actions = copy.deepcopy(orig_ser_actions)
-
- if ev_type.specific_context_field_type is not None:
- ser_action_index = len(ser_actions.actions)
- ser_actions.append_root_scope_ft(ev_type.specific_context_field_type, _RootFtPrefixes.EC)
- ser_action_iter = itertools.islice(ser_actions.actions, ser_action_index, None)
- self._generate_serialize_statements_from_actions(_RootFtPrefixes.EC, ser_action_iter)
-
- if ev_type.payload_field_type is not None:
- ser_action_index = len(ser_actions.actions)
- ser_actions.append_root_scope_ft(ev_type.payload_field_type, _RootFtPrefixes.EP)
- ser_action_iter = itertools.islice(ser_actions.actions, ser_action_index, None)
- self._generate_serialize_statements_from_actions(_RootFtPrefixes.EP, ser_action_iter)
-
- self._cg.unindent()
- tmpl = barectf_templates._FUNC_SERIALIZE_EVENT_BODY_END
- self._cg.add_lines(tmpl)
-
- def _generate_func_serialize_event_header_proto(self, stream_type):
- tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_BEGIN
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name))
-
- if stream_type._ev_header_ft is not None:
- self._generate_proto_params(stream_type._ev_header_ft, _RootFtPrefixes.SEH,
- {'id', 'timestamp'})
-
- tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_END
- self._cg.add_lines(tmpl)
-
- def _generate_func_serialize_event_common_context_proto(self, stream_type):
- tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_BEGIN
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name))
-
- if stream_type.event_common_context_field_type is not None:
- self._generate_proto_params(stream_type.event_common_context_field_type, _RootFtPrefixes.SEC)
-
- tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_END
- self._cg.add_lines(tmpl)
-
- def _generate_func_serialize_event_header(self, stream_type, ser_action_iter):
- self._generate_func_serialize_event_header_proto(stream_type)
- tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_BEGIN
- lines = tmpl.format(prefix=self._iden_prefix, sname=stream_type.name)
- self._cg.add_lines(lines)
- self._cg.indent()
-
- if stream_type.default_clock_type is not None:
- line = f'struct {self._iden_prefix}{stream_type.name}_ctx *s_ctx = FROM_VOID_PTR(struct {self._iden_prefix}{stream_type.name}_ctx, vctx);'
- self._cg.add_line(line)
- line = f'const {self._clk_type_c_type(stream_type.default_clock_type)} ts = s_ctx->cur_last_event_ts;'
- self._cg.add_line(line)
-
- self._cg.add_empty_line()
-
- if stream_type._ev_header_ft is not None:
- spec_src = {}
- member_name = 'id'
- member = stream_type._ev_header_ft.members.get(member_name)
-
- if member is not None:
- spec_src[member_name] = f'({self._get_ft_c_type(member.field_type)}) event_id'
-
- member_name = 'timestamp'
- member = stream_type._ev_header_ft.members.get(member_name)
-
- if member is not None:
- spec_src[member_name] = f'({self._get_ft_c_type(member.field_type)}) ts'
-
- self._generate_serialize_statements_from_actions(_RootFtPrefixes.SEH, ser_action_iter,
- spec_src)
-
- self._cg.unindent()
- tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_END
- self._cg.add_lines(tmpl)
-
- def _generate_func_serialize_event_common_context(self, stream_type, ser_action_iter):
- self._generate_func_serialize_event_common_context_proto(stream_type)
- tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_BEGIN
- lines = tmpl.format(prefix=self._iden_prefix)
- self._cg.add_lines(lines)
- self._cg.indent()
-
- if stream_type.event_common_context_field_type is not None:
- self._generate_serialize_statements_from_actions(_RootFtPrefixes.SEC, ser_action_iter)
-
- self._cg.unindent()
- tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_END
- self._cg.add_lines(tmpl)
+ # Generates the bitfield header file contents.
+ def generate_bitfield_header(self):
+ return self._create_file_template('bitfield.h.j2').render()
- def _generate_func_trace(self, stream_type, ev_type):
- self._generate_func_trace_proto(stream_type, ev_type)
- params = self._get_call_event_param_list(stream_type, ev_type)
- def_clk_type = stream_type.default_clock_type
+ # Generates the public header file contents.
+ def generate_header(self):
+ return self._create_file_template('barectf.h.j2').render(root_ft_prefixes=_RootFtPrefixes)
- if def_clk_type is not None:
- save_ts_line = f'ctx->cur_last_event_ts = ctx->parent.cbs.{def_clk_type.name}_clock_get_value(ctx->parent.data);'
- else:
- save_ts_line = '/* (no clock) */'
-
- tmpl = barectf_templates._FUNC_TRACE_BODY
- self._cg.add_lines(tmpl.format(sname=stream_type.name, evname=ev_type.name, params=params,
- save_ts=save_ts_line))
-
- def _generate_func_init(self):
- self._generate_func_init_proto()
- tmpl = barectf_templates._FUNC_INIT_BODY
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix))
-
- def _generate_member_name_cc_line(self, member_name):
- self._cg.add_cc_line(f'`{member_name}` field')
-
- def _save_serialization_action(self, name, action):
- self._saved_serialization_actions[name] = action
-
- def _get_open_close_ts_line(self, stream_type):
- def_clk_type = stream_type.default_clock_type
-
- if def_clk_type is None:
- return ''
-
- c_type = self._clk_type_c_type(def_clk_type)
- return f'\tconst {c_type} ts = ctx->parent.use_cur_last_event_ts ? ctx->cur_last_event_ts : ctx->parent.cbs.{def_clk_type.name}_clock_get_value(ctx->parent.data);'
-
- def _generate_func_open(self, stream_type):
- def generate_save_offset(name, action):
- self._cg.add_line(f'ctx->off_spc_{name} = ctx->parent.at;')
- self._save_serialization_action(name, action)
-
- self._generate_func_open_proto(stream_type)
- tmpl = barectf_templates._FUNC_OPEN_BODY_BEGIN
- pkt_ctx_ft = stream_type._pkt_ctx_ft
- ts_line = self._get_open_close_ts_line(stream_type)
- lines = tmpl.format(ts=ts_line)
- self._cg.add_lines(lines)
- self._cg.indent()
- self._cg.add_cc_line('do not open a packet that is already open')
- self._cg.add_line('if (ctx->parent.packet_is_open) {')
- self._cg.indent()
- self._cg.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;')
- self._cg.add_line('return;')
- self._cg.unindent()
- self._cg.add_line('}')
- self._cg.add_empty_line()
- self._cg.add_line('ctx->parent.at = 0;')
- pkt_header_ft = self._trace_type._pkt_header_ft
- ser_actions = _SerializationActions()
-
- if pkt_header_ft is not None:
- self._cg.add_empty_line()
- self._cg.add_cc_line('trace packet header')
- self._cg.add_line('{')
- self._cg.indent()
- ser_actions.append_root_scope_ft(pkt_header_ft, _RootFtPrefixes.TPH)
-
- for action in ser_actions.actions:
- if type(action) is _AlignSerializationAction:
- if action.names:
- if len(action.names) == 1:
- line = 'align trace packet header structure'
- else:
- line = f'align field `{action.names[-1]}`'
-
- self._cg.add_cc_line(line)
-
- self._generate_align('ctx->parent.at', action.value)
- self._cg.add_empty_line()
- else:
- assert type(action) is _SerializeSerializationAction
- assert(len(action.names) >= 2)
- member_name = action.names[-1]
- line = f'serialize field `{member_name}`'
- self._cg.add_cc_line(line)
- src = _RootFtPrefixes.TPH + member_name
-
- if member_name == 'magic':
- src = '0xc1fc1fc1UL'
- elif member_name == 'stream_id':
- src = f'({self._get_ft_c_type(action.ft)}) {stream_type.id}'
- elif member_name == 'uuid':
- self._cg.add_line('{')
- self._cg.indent()
- self._cg.add_line('static uint8_t uuid[] = {')
- self._cg.indent()
-
- for b in self._trace_type.uuid.bytes:
- self._cg.add_line(f'{b},')
-
- self._cg.unindent()
- self._cg.add_line('};')
- self._cg.add_empty_line()
- self._generate_align('ctx->parent.at', 8)
- line = 'memcpy(&ctx->parent.buf[_BITS_TO_BYTES(ctx->parent.at)], uuid, 16);'
- self._cg.add_line(line)
- self._generate_incr_pos_bytes('ctx->parent.at', 16)
- self._cg.unindent()
- self._cg.add_line('}')
- self._cg.add_empty_line()
- continue
-
- self._generate_serialize_from_action(src, '(&ctx->parent)', action)
- self._cg.add_empty_line()
-
- self._cg.unindent()
- self._cg.add_lines('}')
-
- spc_action_index = len(ser_actions.actions)
- self._cg.add_empty_line()
- self._cg.add_cc_line('stream packet context')
- self._cg.add_line('{')
- self._cg.indent()
- ser_actions.append_root_scope_ft(pkt_ctx_ft, _RootFtPrefixes.SPC)
-
- for action in itertools.islice(ser_actions.actions, spc_action_index, None):
- if type(action) is _AlignSerializationAction:
- if action.names:
- if len(action.names) == 1:
- line = 'align stream packet context structure'
- else:
- line = f'align field `{action.names[-1]}`'
-
- self._cg.add_cc_line(line)
-
- self._generate_align('ctx->parent.at', action.value)
- self._cg.add_empty_line()
- else:
- assert type(action) is _SerializeSerializationAction
- assert(len(action.names) >= 2)
- member_name = action.names[-1]
- line = f'serialize field `{member_name}`'
- self._cg.add_cc_line(line)
- src = _RootFtPrefixes.SPC + member_name
- skip_int = False
-
- if member_name == 'timestamp_begin':
- src = f'({self._get_ft_c_type(action.ft)}) ts'
- elif member_name in {'timestamp_end', 'content_size', 'events_discarded'}:
- skip_int = True
- elif member_name == 'packet_size':
- src = f'({self._get_ft_c_type(action.ft)}) ctx->parent.packet_size'
-
- if skip_int:
- generate_save_offset(member_name, action)
- self._generate_incr_pos('ctx->parent.at', action.ft.size)
- else:
- self._generate_serialize_from_action(src, '(&ctx->parent)', action)
-
- self._cg.add_empty_line()
-
- self._cg.unindent()
- self._cg.add_lines('}')
- self._cg.unindent()
- tmpl = barectf_templates._FUNC_OPEN_BODY_END
- self._cg.add_lines(tmpl)
-
- def _generate_func_close(self, stream_type):
- def generate_goto_offset(name):
- self._cg.add_line(f'ctx->parent.at = ctx->off_spc_{name};')
-
- self._generate_func_close_proto(stream_type)
- tmpl = barectf_templates._FUNC_CLOSE_BODY_BEGIN
- pkt_ctx_ft = stream_type._pkt_ctx_ft
- ts_line = self._get_open_close_ts_line(stream_type)
- lines = tmpl.format(ts=ts_line)
- self._cg.add_lines(lines)
- self._cg.indent()
- self._cg.add_cc_line('do not close a packet that is not open')
- self._cg.add_line('if (!ctx->parent.packet_is_open) {')
- self._cg.indent()
- self._cg.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;')
- self._cg.add_line('return;')
- self._cg.unindent()
- self._cg.add_line('}')
- self._cg.add_empty_line()
- self._cg.add_cc_line('save content size')
- self._cg.add_line('ctx->parent.content_size = ctx->parent.at;')
- member_name = 'timestamp_end'
- member = pkt_ctx_ft.members.get(member_name)
-
- if member is not None:
- self._cg.add_empty_line()
- self._generate_member_name_cc_line(member_name)
- generate_goto_offset(member_name)
- action = self._saved_serialization_actions[member_name]
- c_type = self._get_ft_c_type(member.field_type)
- self._generate_serialize_from_action(f'({c_type}) ts', '(&ctx->parent)', action)
-
- member_name = 'content_size'
- member = pkt_ctx_ft.members.get(member_name)
-
- if member is not None:
- self._cg.add_empty_line()
- self._generate_member_name_cc_line(member_name)
- generate_goto_offset(member_name)
- action = self._saved_serialization_actions[member_name]
- c_type = self._get_ft_c_type(member.field_type)
- self._generate_serialize_from_action(f'({c_type}) ctx->parent.content_size',
- '(&ctx->parent)', action)
-
- member_name = 'events_discarded'
- member = pkt_ctx_ft.members.get(member_name)
-
- if member is not None:
- self._cg.add_empty_line()
- self._generate_member_name_cc_line(member_name)
- generate_goto_offset(member_name)
- action = self._saved_serialization_actions[member_name]
- c_type = self._get_ft_c_type(member.field_type)
- self._generate_serialize_from_action(f'({c_type}) ctx->parent.events_discarded',
- '(&ctx->parent)', action)
-
- self._cg.unindent()
- tmpl = barectf_templates._FUNC_CLOSE_BODY_END
- self._cg.add_lines(tmpl)
-
- def generate_c_src(self, header_name, bitfield_header_name):
- self._cg.reset()
- dt = datetime.datetime.now().isoformat()
- tmpl = barectf_templates._C_SRC
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, header_filename=header_name,
- bitfield_header_filename=bitfield_header_name,
- version=barectf_version.__version__, date=dt))
- self._cg.add_empty_line()
-
- # initialization function
- self._generate_func_init()
- self._cg.add_empty_line()
-
- for stream_type in self._trace_type.stream_types:
- self._generate_func_open(stream_type)
- self._cg.add_empty_line()
- self._generate_func_close(stream_type)
- self._cg.add_empty_line()
- ser_actions = _SerializationActions()
-
- if stream_type._ev_header_ft is not None:
- ser_actions.append_root_scope_ft(stream_type._ev_header_ft, _RootFtPrefixes.SEH)
- self._generate_func_serialize_event_header(stream_type, iter(ser_actions.actions))
- self._cg.add_empty_line()
-
- if stream_type.event_common_context_field_type is not None:
- ser_action_index = len(ser_actions.actions)
- ser_actions.append_root_scope_ft(stream_type.event_common_context_field_type,
- _RootFtPrefixes.SEC)
- ser_action_iter = itertools.islice(ser_actions.actions, ser_action_index, None)
- self._generate_func_serialize_event_common_context(stream_type, ser_action_iter)
- self._cg.add_empty_line()
-
- for ev_type in stream_type.event_types:
- self._generate_func_get_event_size(stream_type, ev_type)
- self._cg.add_empty_line()
- self._generate_func_serialize_event(stream_type, ev_type, ser_actions)
- self._cg.add_empty_line()
- self._generate_func_trace(stream_type, ev_type)
- self._cg.add_empty_line()
-
- return self._cg.code
+ # Generates the source code file contents.
+ def generate_c_src(self, header_file_name, bitfield_header_file_name):
+ # Creates and returns the operations for all the stream and for
+ # all their events.
+ def create_stream_ops():
+ stream_ser_ops = {}
+
+ for stream_type in self._trace_type.stream_types:
+ pkt_header_ser_ops = []
+ builder = _OpsBuilder(self)
+ pkt_header_ft = self._trace_type._pkt_header_ft
+
+ # packet header serialization operations
+ if pkt_header_ft is not None:
+ spec_serialize_write_templates = {
+ 'magic': self._serialize_write_magic_statements_templ,
+ 'uuid': self._serialize_write_uuid_statements_templ,
+ 'stream_id': self._serialize_write_stream_type_id_statements_templ,
+ }
+ builder.append_root_ft(pkt_header_ft, _RootFtPrefixes.TPH,
+ spec_serialize_write_templates)
+ pkt_header_ser_ops = copy.copy(builder.ops)
+
+ # packet context serialization operations
+ first_op_index = len(builder.ops)
+ spec_serialize_write_templates = {
+ 'timestamp_begin': self._serialize_write_time_statements_templ,
+ 'packet_size': self._serialize_write_packet_size_statements_templ,
+ 'timestamp_end': self._serialize_write_skip_save_statements_templ,
+ 'events_discarded': self._serialize_write_skip_save_statements_templ,
+ 'content_size': self._serialize_write_skip_save_statements_templ,
+ }
+ builder.append_root_ft(stream_type._pkt_ctx_ft, _RootFtPrefixes.SPC,
+ spec_serialize_write_templates)
+ pkt_ctx_ser_ops = copy.copy(builder.ops[first_op_index:])
+
+ # event header serialization operations
+ builder = _OpsBuilder(self)
+ ev_header_ser_ops = []
+
+ if stream_type._ev_header_ft is not None:
+ spec_serialize_write_templates = {
+ 'timestamp': self._serialize_write_time_statements_templ,
+ 'id': self._serialize_write_ev_type_id_statements_templ,
+ }
+ builder.append_root_ft(stream_type._ev_header_ft, _RootFtPrefixes.SEH,
+ spec_serialize_write_templates)
+ ev_header_ser_ops = copy.copy(builder.ops)
+
+ # event common context serialization operations
+ ev_common_ctx_ser_ops = []
+
+ if stream_type.event_common_context_field_type is not None:
+ first_op_index = len(builder.ops)
+ builder.append_root_ft(stream_type.event_common_context_field_type,
+ _RootFtPrefixes.SEC)
+ ev_common_ctx_ser_ops = copy.copy(builder.ops[first_op_index:])
+
+ # serialization operations specific to each event type
+ ev_ser_ops = {}
+
+ for ev_type in stream_type.event_types:
+ ev_builder = copy.copy(builder)
+
+ # specific context serialization operations
+ spec_ctx_ser_ops = []
+
+ if ev_type.specific_context_field_type is not None:
+ first_op_index = len(ev_builder.ops)
+ ev_builder.append_root_ft(ev_type.specific_context_field_type,
+ _RootFtPrefixes.EC)
+ spec_ctx_ser_ops = copy.copy(ev_builder.ops[first_op_index:])
+
+ # payload serialization operations
+ payload_ser_ops = []
+
+ if ev_type.payload_field_type is not None:
+ first_op_index = len(ev_builder.ops)
+ ev_builder.append_root_ft(ev_type.payload_field_type, _RootFtPrefixes.EP)
+ payload_ser_ops = copy.copy(ev_builder.ops[first_op_index:])
+
+ ev_ser_ops[ev_type] = _EventOps(spec_ctx_ser_ops, payload_ser_ops)
+
+ stream_ser_ops[stream_type] = _StreamOps(pkt_header_ser_ops, pkt_ctx_ser_ops,
+ ev_header_ser_ops, ev_common_ctx_ser_ops,
+ ev_ser_ops)
+
+ return stream_ser_ops
+
+ # Returns the "write" operation for the packet context member
+ # named `member_name` within the stream type `stream_type`.
+ def stream_op_pkt_ctx_op(stream_type, member_name):
+ for op in stream_ops[stream_type].pkt_ctx_ops:
+ if op.top_name == member_name and type(op) is _WriteOp:
+ return op
+
+ stream_ops = create_stream_ops()
+ return self._create_file_template('barectf.c.j2').render(header_file_name=header_file_name,
+ bitfield_header_file_name=bitfield_header_file_name,
+ root_ft_prefixes=_RootFtPrefixes,
+ root_ft_prefix_names=_ROOT_FT_PREFIX_NAMES,
+ stream_ops=stream_ops,
+ stream_op_pkt_ctx_op=stream_op_pkt_ctx_op)
+++ /dev/null
-# The MIT License (MIT)
-#
-# Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-_FUNC_INIT_PROTO = '''/* initialize context */
-void {prefix}init(
- void *vctx,
- uint8_t *buf,
- uint32_t buf_size,
- struct {prefix}platform_callbacks cbs,
- void *data
-)'''
-
-
-_FUNC_INIT_BODY = '''{{
- struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);
- ctx->cbs = cbs;
- ctx->data = data;
- ctx->buf = buf;
- ctx->packet_size = _BYTES_TO_BITS(buf_size);
- ctx->at = 0;
- ctx->events_discarded = 0;
- ctx->packet_is_open = 0;
- ctx->in_tracing_section = 0;
- ctx->is_tracing_enabled = 1;
- ctx->use_cur_last_event_ts = 0;
-}}'''
-
-
-_FUNC_OPEN_PROTO_BEGIN = '''/* open packet for stream `{sname}` */
-void {prefix}{sname}_open_packet(
- struct {prefix}{sname}_ctx *ctx'''
-
-
-_FUNC_OPEN_PROTO_END = ')'
-
-
-_FUNC_OPEN_BODY_BEGIN = '''{{
-{ts}
- const int saved_in_tracing_section = ctx->parent.in_tracing_section;
-
- /*
- * This function is either called by a tracing function, or
- * directly by the platform.
- *
- * If it's called by a tracing function, then
- * ctx->parent.in_tracing_section is 1, so it's safe to open
- * the packet here (alter the packet), even if tracing was
- * disabled in the meantime because we're already in a tracing
- * section (which finishes at the end of the tracing function
- * call).
- *
- * If it's called directly by the platform, then if tracing is
- * disabled, we don't want to alter the packet, and return
- * immediately.
- */
- if (!ctx->parent.is_tracing_enabled && !saved_in_tracing_section) {{
- ctx->parent.in_tracing_section = 0;
- return;
- }}
-
- /* we can modify the packet */
- ctx->parent.in_tracing_section = 1;
-'''
-
-
-_FUNC_OPEN_BODY_END = '''
- /* save content beginning's offset */
- ctx->parent.off_content = ctx->parent.at;
-
- /* mark current packet as open */
- ctx->parent.packet_is_open = 1;
-
- /* not tracing anymore */
- ctx->parent.in_tracing_section = saved_in_tracing_section;
-}'''
-
-
-_FUNC_CLOSE_PROTO = '''/* close packet for stream `{sname}` */
-void {prefix}{sname}_close_packet(struct {prefix}{sname}_ctx *ctx)'''
-
-
-_FUNC_CLOSE_BODY_BEGIN = '''{{
-{ts}
- const int saved_in_tracing_section = ctx->parent.in_tracing_section;
-
- /*
- * This function is either called by a tracing function, or
- * directly by the platform.
- *
- * If it's called by a tracing function, then
- * ctx->parent.in_tracing_section is 1, so it's safe to close
- * the packet here (alter the packet), even if tracing was
- * disabled in the meantime, because we're already in a tracing
- * section (which finishes at the end of the tracing function
- * call).
- *
- * If it's called directly by the platform, then if tracing is
- * disabled, we don't want to alter the packet, and return
- * immediately.
- */
- if (!ctx->parent.is_tracing_enabled && !saved_in_tracing_section) {{
- ctx->parent.in_tracing_section = 0;
- return;
- }}
-
- /* we can modify the packet */
- ctx->parent.in_tracing_section = 1;
-'''
-
-
-_FUNC_CLOSE_BODY_END = '''
- /* go back to end of packet */
- ctx->parent.at = ctx->parent.packet_size;
-
- /* mark packet as closed */
- ctx->parent.packet_is_open = 0;
-
- /* not tracing anymore */
- ctx->parent.in_tracing_section = saved_in_tracing_section;
-}'''
-
-
-_FUNC_TRACE_PROTO_BEGIN = '''/* trace (stream `{sname}`, event `{evname}`) */
-void {prefix}{sname}_trace_{evname}(
- struct {prefix}{sname}_ctx *ctx'''
-
-
-_FUNC_TRACE_PROTO_END = ')'
-
-
-_FUNC_TRACE_BODY = '''{{
- uint32_t ev_size;
-
- /* save timestamp */
- {save_ts}
-
- if (!ctx->parent.is_tracing_enabled) {{
- return;
- }}
-
- /* we can modify the packet */
- ctx->parent.in_tracing_section = 1;
-
- /* get event size */
- ev_size = _get_event_size_{sname}_{evname}(TO_VOID_PTR(ctx){params});
-
- /* do we have enough space to serialize? */
- if (!_reserve_event_space(TO_VOID_PTR(ctx), ev_size)) {{
- /* no: forget this */
- ctx->parent.in_tracing_section = 0;
- return;
- }}
-
- /* serialize event */
- _serialize_event_{sname}_{evname}(TO_VOID_PTR(ctx){params});
-
- /* commit event */
- _commit_event(TO_VOID_PTR(ctx));
-
- /* not tracing anymore */
- ctx->parent.in_tracing_section = 0;
-}}'''
-
-
-_FUNC_GET_EVENT_SIZE_PROTO_BEGIN = '''static uint32_t _get_event_size_{sname}_{evname}(
- void *vctx'''
-
-
-_FUNC_GET_EVENT_SIZE_PROTO_END = ')'
-
-
-_FUNC_GET_EVENT_SIZE_BODY_BEGIN = '''{{
- struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);
- uint32_t at = ctx->at;'''
-
-
-_FUNC_GET_EVENT_SIZE_BODY_END = ''' return at - ctx->at;
-}'''
-
-
-_FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_BEGIN = '''static void _serialize_stream_event_header_{sname}(
- void *vctx,
- uint32_t event_id'''
-
-
-_FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_END = ')'
-
-
-_FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_BEGIN = '''{{
- struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);'''
-
-
-_FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_END = '}'
-
-
-_FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_BEGIN = '''static void _serialize_stream_event_context_{sname}(
- void *vctx'''
-
-
-_FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_END = ')'
-
-
-_FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_BEGIN = '''{{
- struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);'''
-
-
-_FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_END = '}'
-
-
-_FUNC_SERIALIZE_EVENT_PROTO_BEGIN = '''static void _serialize_event_{sname}_{evname}(
- void *vctx'''
-
-
-_FUNC_SERIALIZE_EVENT_PROTO_END = ')'
-
-
-_FUNC_SERIALIZE_EVENT_BODY_BEGIN = '''{{
- struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);'''
-
-
-_FUNC_SERIALIZE_EVENT_BODY_END = '}'
-
-
-_C_SRC = '''/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- *
- * The following C code was generated by barectf {version}
- * on {date}.
- *
- * For more details, see <http://barectf.org>.
- */
-
-#include <stdint.h>
-#include <string.h>
-#include <assert.h>
-
-#include "{header_filename}"
-#include "{bitfield_header_filename}"
-
-#define _ALIGN(_at, _align) \\
- do {{ \\
- (_at) = ((_at) + ((_align) - 1)) & -(_align); \\
- }} while (0)
-
-#ifdef __cplusplus
-# define TO_VOID_PTR(_value) static_cast<void *>(_value)
-# define FROM_VOID_PTR(_type, _value) static_cast<_type *>(_value)
-#else
-# define TO_VOID_PTR(_value) ((void *) (_value))
-# define FROM_VOID_PTR(_type, _value) ((_type *) (_value))
-#endif
-
-#define _BITS_TO_BYTES(_x) ((_x) >> 3)
-#define _BYTES_TO_BITS(_x) ((_x) << 3)
-
-union f2u {{
- float f;
- uint32_t u;
-}};
-
-union d2u {{
- double f;
- uint64_t u;
-}};
-
-uint32_t {prefix}packet_size(void *ctx)
-{{
- return FROM_VOID_PTR(struct {prefix}ctx, ctx)->packet_size;
-}}
-
-int {prefix}packet_is_full(void *ctx)
-{{
- struct {prefix}ctx *cctx = FROM_VOID_PTR(struct {prefix}ctx, ctx);
-
- return cctx->at == cctx->packet_size;
-}}
-
-int {prefix}packet_is_empty(void *ctx)
-{{
- struct {prefix}ctx *cctx = FROM_VOID_PTR(struct {prefix}ctx, ctx);
-
- return cctx->at <= cctx->off_content;
-}}
-
-uint32_t {prefix}packet_events_discarded(void *ctx)
-{{
- return FROM_VOID_PTR(struct {prefix}ctx, ctx)->events_discarded;
-}}
-
-uint8_t *{prefix}packet_buf(void *ctx)
-{{
- return FROM_VOID_PTR(struct {prefix}ctx, ctx)->buf;
-}}
-
-uint32_t {prefix}packet_buf_size(void *ctx)
-{{
- struct {prefix}ctx *cctx = FROM_VOID_PTR(struct {prefix}ctx, ctx);
-
- return _BITS_TO_BYTES(cctx->packet_size);
-}}
-
-void {prefix}packet_set_buf(void *ctx, uint8_t *buf, uint32_t buf_size)
-{{
- struct {prefix}ctx *cctx = FROM_VOID_PTR(struct {prefix}ctx, ctx);
-
- cctx->buf = buf;
- cctx->packet_size = _BYTES_TO_BITS(buf_size);
-}}
-
-int {prefix}packet_is_open(void *ctx)
-{{
- return FROM_VOID_PTR(struct {prefix}ctx, ctx)->packet_is_open;
-}}
-
-int {prefix}is_in_tracing_section(void *ctx)
-{{
- return FROM_VOID_PTR(struct {prefix}ctx, ctx)->in_tracing_section;
-}}
-
-volatile const int *{prefix}is_in_tracing_section_ptr(void *ctx)
-{{
- return &FROM_VOID_PTR(struct {prefix}ctx, ctx)->in_tracing_section;
-}}
-
-int {prefix}is_tracing_enabled(void *ctx)
-{{
- return FROM_VOID_PTR(struct {prefix}ctx, ctx)->is_tracing_enabled;
-}}
-
-void {prefix}enable_tracing(void *ctx, int enable)
-{{
- FROM_VOID_PTR(struct {prefix}ctx, ctx)->is_tracing_enabled = enable;
-}}
-
-static
-void _write_cstring(struct {prefix}ctx *ctx, const char *src)
-{{
- uint32_t sz = strlen(src) + 1;
-
- memcpy(&ctx->buf[_BITS_TO_BYTES(ctx->at)], src, sz);
- ctx->at += _BYTES_TO_BITS(sz);
-}}
-
-static
-int _reserve_event_space(void *vctx, uint32_t ev_size)
-{{
- struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);
-
- /* event _cannot_ fit? */
- if (ev_size > (ctx->packet_size - ctx->off_content)) {{
- ctx->events_discarded++;
-
- return 0;
- }}
-
- /* packet is full? */
- if ({prefix}packet_is_full(ctx)) {{
- /* yes: is back-end full? */
- if (ctx->cbs.is_backend_full(ctx->data)) {{
- /* yes: discard event */
- ctx->events_discarded++;
-
- return 0;
- }}
-
- /* back-end is not full: open new packet */
- ctx->use_cur_last_event_ts = 1;
- ctx->cbs.open_packet(ctx->data);
- ctx->use_cur_last_event_ts = 0;
- }}
-
- /* event fits the current packet? */
- if (ev_size > (ctx->packet_size - ctx->at)) {{
- /* no: close packet now */
- ctx->use_cur_last_event_ts = 1;
- ctx->cbs.close_packet(ctx->data);
- ctx->use_cur_last_event_ts = 0;
-
- /* is back-end full? */
- if (ctx->cbs.is_backend_full(ctx->data)) {{
- /* yes: discard event */
- ctx->events_discarded++;
-
- return 0;
- }}
-
- /* back-end is not full: open new packet */
- ctx->use_cur_last_event_ts = 1;
- ctx->cbs.open_packet(ctx->data);
- ctx->use_cur_last_event_ts = 0;
- assert(ev_size <= (ctx->packet_size - ctx->at));
- }}
-
- return 1;
-}}
-
-static
-void _commit_event(void *vctx)
-{{
- struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);
-
- /* is packet full? */
- if ({prefix}packet_is_full(ctx)) {{
- /* yes: close it now */
- ctx->cbs.close_packet(ctx->data);
- }}
-}}'''
+++ /dev/null
-{% import 'common.j2' as common %}
-{% import 'c-common.j2' as c_common %}
-{% set prefix = common.prefix %}
-{% set ucprefix = common.ucprefix %}
-{% set trace_type = cfg.trace.type %}
-{% set cg_opts = cfg.options.code_generation_options %}
-{% set def_stream_type = cg_opts.default_stream_type %}
-{% set header_opts = cg_opts.header_options %}
-#ifndef _{{ ucprefix }}H
-#define _{{ ucprefix }}H
-
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- *
- * The following C code was generated by barectf v{{ barectf_version.__version__ }}
- * on {{ common.gen_date }}.
- *
- * For more details, see <https://barectf.org/>.
- */
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-{% if header_opts.identifier_prefix_definition %}
-#define _BARECTF_PREFIX {{ prefix }}
-{% endif %}
-{% if def_stream_type and header_opts.default_stream_type_name_definition %}
-#define _BARECTF_DEFAULT_STREAM {{ def_stream_type.name }}
-{% endif %}
-{% if def_stream_type %}
-
-{% for ev_type in def_stream_type.event_types | sort %}
-#define {{ prefix }}trace_{{ ev_type.name }} {{ c_common.trace_func_name(def_stream_type, ev_type) }}
-{% endfor %}
-{% endif %}
-
-struct {{ prefix }}ctx;
-
-uint32_t {{ prefix }}packet_size(void *ctx);
-int {{ prefix }}packet_is_full(void *ctx);
-int {{ prefix }}packet_is_empty(void *ctx);
-uint32_t {{ prefix }}packet_events_discarded(void *ctx);
-uint8_t *{{ prefix }}packet_buf(void *ctx);
-void {{ prefix }}packet_set_buf(void *ctx, uint8_t *buf, uint32_t buf_size);
-uint32_t {{ prefix }}packet_buf_size(void *ctx);
-int {{ prefix }}packet_is_open(void *ctx);
-int {{ prefix }}is_in_tracing_section(void *ctx);
-volatile const int *{{ prefix }}is_in_tracing_section_ptr(void *ctx);
-int {{ prefix }}is_tracing_enabled(void *ctx);
-void {{ prefix }}enable_tracing(void *ctx, int enable);
-
-/* barectf platform callbacks */
-struct {{ prefix }}platform_callbacks {
-{% set clk_types = trace_type.clock_types %}
-{% if clk_types %}
- /* clock callbacks */
-{% for clk_type in clk_types | sort %}
- {{ cg_opts.clock_type_c_types[clk_type]Â }} (*{{ clk_type.name }}_clock_get_value)(void *);
-{% endfor %}
-
-{% endif %}
- /* is back-end full? */
- int (*is_backend_full)(void *);
-
- /* open packet */
- void (*open_packet)(void *);
-
- /* close packet */
- void (*close_packet)(void *);
-};
-
-/* common barectf context */
-struct {{ prefix }}ctx {
- /* platform callbacks */
- struct {{ prefix }}platform_callbacks cbs;
-
- /* platform data (passed to callbacks) */
- void *data;
-
- /* output buffer (will contain a CTF binary packet) */
- uint8_t *buf;
-
- /* packet's total size (bits) */
- uint32_t packet_size;
-
- /* packet's content size (bits) */
- uint32_t content_size;
-
- /* current position from beginning of packet (bits) */
- uint32_t at;
-
- /* size of packet header + context fields (content offset) */
- uint32_t off_content;
-
- /* discarded event counter */
- uint32_t events_discarded;
-
- /* current packet is open? */
- int packet_is_open;
-
- /* in tracing code? */
- volatile int in_tracing_section;
-
- /* tracing is enabled? */
- volatile int is_tracing_enabled;
-
- /* use current/last event time when opening/closing packets */
- int use_cur_last_event_ts;
-};
-
-{% for stream_type in trace_type.stream_types | sort %}
-/* context for stream type `{{ stream_type.name }}` */
-struct {{ prefix }}{{ stream_type.name }}_ctx {
- /* parent */
- struct {{ prefix }}ctx parent;
-
- /* config-specific members follow */
-{% if trace_type._pkt_header_ft %}
-{% for member_name in trace_type._pkt_header_ft.members %}
- uint32_t off_tph_{{ member_name }};
-{% endfor %}
-{% endif %}
-{% for member_name in stream_type._pkt_ctx_ft.members %}
- uint32_t off_spc_{{ member_name }};
-{% endfor %}
-{% if stream_type.default_clock_type %}
- {{ cg_opts.clock_type_c_types[stream_type.default_clock_type] }} cur_last_event_ts;
-{% endif %}
-};
-
-{% endfor %}
-{% include 'c-ctx-init-func-proto.j2' %};
-
-{% for stream_type in trace_type.stream_types | sort %}
-{% include 'c-open-func-proto.j2' %};
-
-{% include 'c-close-func-proto.j2' %};
-{% for ev_type in stream_type.event_types | sort %}
-
-{% include 'c-trace-func-proto.j2' %};
-{% endfor %}
-{% endfor %}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _{{ ucprefix }}H */
+++ /dev/null
-{% import 'common.j2' as common %}
-{% set prefix = common.prefix %}
-{% set ucprefix = common.ucprefix %}
-#ifndef _{{ ucprefix }}BITFIELD_H
-#define _{{ ucprefix }}BITFIELD_H
-
-/*
- * BabelTrace
- *
- * Bitfields read/write functions.
- *
- * Copyright (c) 2010-2020 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <limits.h>
-
-#ifdef __cplusplus
-# define {{ ucprefix }}CAST_PTR(_type, _value) \
- static_cast<_type>(static_cast<void *>(_value))
-#else
-# define {{ ucprefix }}CAST_PTR(_type, _value) ((void *) (_value))
-#endif
-
-{% set def_bo = cfg.trace.type.default_byte_order %}
-{% set def_bo_str = 'LITTLE_ENDIAN' if def_bo == barectf_config.ByteOrder.LITTLE_ENDIAN else 'BIG_ENDIAN' %}
-#define {{ ucprefix }}BYTE_ORDER {{ def_bo_str }}
-
-
-/* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */
-#define _{{ prefix }}bt_piecewise_rshift(_vtype, _v, _shift) \
-do { \
- unsigned long ___shift = (_shift); \
- unsigned long sb = (___shift) / (sizeof(_v) * CHAR_BIT - 1); \
- unsigned long final = (___shift) % (sizeof(_v) * CHAR_BIT - 1); \
- \
- for (; sb; sb--) \
- _v >>= sizeof(_v) * CHAR_BIT - 1; \
- _v >>= final; \
-} while (0)
-
-/*
- * {{ prefix }}bt_bitfield_write - write integer to a bitfield in native endianness
- *
- * Save integer to the bitfield, which starts at the "start" bit, has "len"
- * bits.
- * The inside of a bitfield is from high bits to low bits.
- * Uses native endianness.
- * For unsigned "v", pad MSB with 0 if bitfield is larger than v.
- * For signed "v", sign-extend v if bitfield is larger than v.
- *
- * On little endian, bytes are placed from the less significant to the most
- * significant. Also, consecutive bitfields are placed from lower bits to higher
- * bits.
- *
- * On big endian, bytes are places from most significant to less significant.
- * Also, consecutive bitfields are placed from higher to lower bits.
- */
-
-#define _{{ prefix }}bt_bitfield_write_le(_ptr, type, _start, _length, _vtype, _v) \
-do { \
- _vtype __v = (_v); \
- type *__ptr = {{ ucprefix }}CAST_PTR(type *, _ptr); \
- unsigned long __start = (_start), __length = (_length); \
- type mask, cmask; \
- unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
- unsigned long start_unit, end_unit, this_unit; \
- unsigned long end, cshift; /* cshift is "complement shift" */ \
- \
- if (!__length) \
- break; \
- \
- end = __start + __length; \
- start_unit = __start / ts; \
- end_unit = (end + (ts - 1)) / ts; \
- \
- /* Trim v high bits */ \
- if (__length < sizeof(__v) * CHAR_BIT) \
- __v &= ~((~(_vtype) 0) << __length); \
- \
- /* We can now append v with a simple "or", shift it piece-wise */ \
- this_unit = start_unit; \
- if (start_unit == end_unit - 1) { \
- mask = ~((~(type) 0) << (__start % ts)); \
- if (end % ts) \
- mask |= (~(type) 0) << (end % ts); \
- cmask = (type) __v << (__start % ts); \
- cmask &= ~mask; \
- __ptr[this_unit] &= mask; \
- __ptr[this_unit] |= cmask; \
- break; \
- } \
- if (__start % ts) { \
- cshift = __start % ts; \
- mask = ~((~(type) 0) << cshift); \
- cmask = (type) __v << cshift; \
- cmask &= ~mask; \
- __ptr[this_unit] &= mask; \
- __ptr[this_unit] |= cmask; \
- _{{ prefix }}bt_piecewise_rshift(_vtype, __v, ts - cshift); \
- __start += ts - cshift; \
- this_unit++; \
- } \
- for (; this_unit < end_unit - 1; this_unit++) { \
- __ptr[this_unit] = (type) __v; \
- _{{ prefix }}bt_piecewise_rshift(_vtype, __v, ts); \
- __start += ts; \
- } \
- if (end % ts) { \
- mask = (~(type) 0) << (end % ts); \
- cmask = (type) __v; \
- cmask &= ~mask; \
- __ptr[this_unit] &= mask; \
- __ptr[this_unit] |= cmask; \
- } else \
- __ptr[this_unit] = (type) __v; \
-} while (0)
-
-#define _{{ prefix }}bt_bitfield_write_be(_ptr, type, _start, _length, _vtype, _v) \
-do { \
- _vtype __v = (_v); \
- type *__ptr = {{ ucprefix }}CAST_PTR(type *, _ptr); \
- unsigned long __start = (_start), __length = (_length); \
- type mask, cmask; \
- unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
- unsigned long start_unit, end_unit, this_unit; \
- unsigned long end, cshift; /* cshift is "complement shift" */ \
- \
- if (!__length) \
- break; \
- \
- end = __start + __length; \
- start_unit = __start / ts; \
- end_unit = (end + (ts - 1)) / ts; \
- \
- /* Trim v high bits */ \
- if (__length < sizeof(__v) * CHAR_BIT) \
- __v &= ~((~(_vtype) 0) << __length); \
- \
- /* We can now append v with a simple "or", shift it piece-wise */ \
- this_unit = end_unit - 1; \
- if (start_unit == end_unit - 1) { \
- mask = ~((~(type) 0) << ((ts - (end % ts)) % ts)); \
- if (__start % ts) \
- mask |= (~((type) 0)) << (ts - (__start % ts)); \
- cmask = (type) __v << ((ts - (end % ts)) % ts); \
- cmask &= ~mask; \
- __ptr[this_unit] &= mask; \
- __ptr[this_unit] |= cmask; \
- break; \
- } \
- if (end % ts) { \
- cshift = end % ts; \
- mask = ~((~(type) 0) << (ts - cshift)); \
- cmask = (type) __v << (ts - cshift); \
- cmask &= ~mask; \
- __ptr[this_unit] &= mask; \
- __ptr[this_unit] |= cmask; \
- _{{ prefix }}bt_piecewise_rshift(_vtype, __v, cshift); \
- end -= cshift; \
- this_unit--; \
- } \
- for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
- __ptr[this_unit] = (type) __v; \
- _{{ prefix }}bt_piecewise_rshift(_vtype, __v, ts); \
- end -= ts; \
- } \
- if (__start % ts) { \
- mask = (~(type) 0) << (ts - (__start % ts)); \
- cmask = (type) __v; \
- cmask &= ~mask; \
- __ptr[this_unit] &= mask; \
- __ptr[this_unit] |= cmask; \
- } else \
- __ptr[this_unit] = (type) __v; \
-} while (0)
-
-/*
- * {{ prefix }}bt_bitfield_write_le - write integer to a bitfield in little endian
- * {{ prefix }}bt_bitfield_write_be - write integer to a bitfield in big endian
- */
-
-#if ({{ ucprefix }}BYTE_ORDER == LITTLE_ENDIAN)
-
-#define {{ prefix }}bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v) \
- _{{ prefix }}bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v)
-
-#define {{ prefix }}bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v) \
- _{{ prefix }}bt_bitfield_write_be(ptr, unsigned char, _start, _length, _vtype, _v)
-
-#elif ({{ ucprefix }}BYTE_ORDER == BIG_ENDIAN)
-
-#define {{ prefix }}bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v) \
- _{{ prefix }}bt_bitfield_write_le(ptr, unsigned char, _start, _length, _vtype, _v)
-
-#define {{ prefix }}bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v) \
- _{{ prefix }}bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v)
-
-#else /* ({{ ucprefix }}BYTE_ORDER == PDP_ENDIAN) */
-
-#error "Byte order not supported"
-
-#endif
-
-#endif /* _{{ ucprefix }}BITFIELD_H */
+++ /dev/null
-/* close packet for stream type `{{ stream_type.name }}` */
-void {{ prefix }}{{ stream_type.name }}_close_packet(struct {{ prefix }}{{ stream_type.name }}_ctx *ctx)
+++ /dev/null
-{#
- # Common variables and macros (for C templates).
- #}
-
-{% import 'common.j2' as common %}
-
-{#
- # Generates the name of a tracing function for the stream type
- # `stream_type` and the event type `ev_type`.
- #}
-{% macro trace_func_name(stream_type, ev_type) -%}
-{{ common.prefix }}{{ stream_type.name }}_trace_{{ ev_type.name }}
-{%- endmacro %}
-
-{#
- # Generates the name of a single function parameter named `name` for
- # the field type `ft`.
- #}
-{% macro func_param(name, ft) -%}
-{{ ft | ft_c_type }} {{ name }}
-{%- endmacro %}
-
-{#
- # Generates a list of parameters for the members of a given structure
- # field type `struct_ft`.
- #
- # Each parameter has the prefix `name_prefix` and starts with an
- # immediate comma followed with a newline and a tab. For example:
- #
- # ,
- # const char * msg,
- # uint32_t msg_id
- #
- # This macro does not generate a parameter line for a member name which
- # is part of `exclude_list`.
- #}
-{% macro func_params(struct_ft, name_prefix, exclude_list) -%}
-{% for name, member in struct_ft.members.items() if name not in exclude_list -%}
-,
- {{ func_param(name_prefix + name, member.field_type) }}
-{%- endfor %}
-{%- endmacro %}
+++ /dev/null
-/* initialize context */
-void {{ prefix }}init(
- void *vctx,
- uint8_t *buf,
- uint32_t buf_size,
- struct {{ prefix }}platform_callbacks cbs,
- void *data)
+++ /dev/null
-{% set pkt_header_exclude_list = ['magic', 'stream_id', 'uuid'] %}
-{% set pkt_ctx_exclude_list = [
- 'timestamp_begin',
- 'timestamp_end',
- 'packet_size',
- 'content_size',
- 'events_discarded'
-] %}
-/* open packet for stream type `{{ stream_type.name }}` */
-void {{ prefix }}{{ stream_type.name }}_open_packet(
- struct {{ prefix }}{{ stream_type.name }}_ctx *ctx
- {%- if trace_type._pkt_header_ft -%}
- {{ c_common.func_params(trace_type._pkt_header_ft,
- root_ft_prefixes.TPH, pkt_header_exclude_list) }}
- {%- endif -%}
- {{ c_common.func_params(stream_type._pkt_ctx_ft, root_ft_prefixes.SPC, pkt_ctx_exclude_list) }})
+++ /dev/null
-{% set ev_header_exclude_list = ['id', 'timestamp'] %}
-/* trace (stream type `{{ stream_type.name }}`, event type `{{ ev_type.name }}`) */
-void {{ prefix }}{{ stream_type.name }}_trace_{{ ev_type.name }}(
- struct {{ prefix }}{{ stream_type.name }}_ctx *ctx
- {%- if stream_type._ev_header_ft -%}
- {{ c_common.func_params(stream_type._ev_header_ft,
- root_ft_prefixes.SEH, ev_header_exclude_list) }}
- {%- endif -%}
- {%- if stream_type.event_common_context_field_type -%}
- {{ c_common.func_params(stream_type.event_common_context_field_type,
- root_ft_prefixes.SEC, []) }}
- {%- endif -%}
- {%- if ev_type.specific_context_field_type -%}
- {{ c_common.func_params(ev_type.specific_context_field_type, root_ft_prefixes.EC, []) }}
- {%- endif -%}
- {%- if ev_type.payload_field_type -%}
- {{ c_common.func_params(ev_type.payload_field_type, root_ft_prefixes.EP, []) }}
- {%- endif -%})
--- /dev/null
+{% if op.names %}
+ {% if op.names | length == 1 %}
+/* align for {{ root_ft_prefix_names[op.top_name] }} structure */
+ {%- else %}
+/* align for `{{ op.top_name }}` field */
+ {%- endif %}
+{% endif %}
--- /dev/null
+{% import 'common.j2' as common %}
+
+{% set prefix = common.prefix %}
+{% set ucprefix = common.ucprefix %}
+{% set cg_opts = cfg.options.code_generation_options %}
+
+{#
+ # Generates the preamble of the packet opening/closing functions for
+ # the stream type `stream_type`.
+ #}
+{% macro open_close_func_preamble(stream_type) %}
+struct {{ prefix }}ctx *ctx = &sctx->parent;
+{% if stream_type.default_clock_type %}
+const {{ cg_opts.clock_type_c_types[stream_type.default_clock_type] }} ts = ctx->use_cur_last_event_ts ?
+ sctx->cur_last_event_ts :
+ ctx->cbs.{{ stream_type.default_clock_type.name }}_clock_get_value(ctx->data);
+{% endif %}
+const int saved_in_tracing_section = ctx->in_tracing_section;
+{%- endmacro %}
+
+{#
+ # Generates a list of function call parameters for the members of
+ # the structure field type `ft`.
+ #
+ # Each parameter has the prefix `param_prefix`.
+ #
+ # The list always starts with a comma (if there's at least one member).
+ #
+ # Example:
+ #
+ # , sec_peer_id, sec_addr, ep_msg_id, ep_msg
+ #}
+{% macro ft_call_params(param_prefix, ft) %}
+{% if ft %}
+ {% for member_name in ft.members %}
+, {{ param_prefix }}_{{ member_name }}
+ {%- endfor %}
+{% endif %}
+{% endmacro %}
--- /dev/null
+{% import 'common.j2' as common %}
+{% import 'c/common.j2' as c_common %}
+{% import 'c/barectf.c-macros.j2' as macros %}
+{% set prefix = common.prefix %}
+{% set ucprefix = common.ucprefix %}
+{% set ctx_struct_name = c_common.ctx_struct_name %}
+{% set cg_opts = cfg.options.code_generation_options %}
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ *
+ * The following C code was generated by barectf v{{ barectf_version.__version__ }}
+ * on {{ common.gen_date }}.
+ *
+ * For more details, see <https://barectf.org/>.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include "{{ header_file_name }}"
+#include "{{ bitfield_header_file_name }}"
+
+#define _ALIGN(_at, _align) \
+ do { \
+ (_at) = ((_at) + ((_align) - 1)) & -(_align); \
+ } while (0)
+
+#ifdef __cplusplus
+# define _TO_VOID_PTR(_value) static_cast<void *>(_value)
+# define _FROM_VOID_PTR(_type, _value) static_cast<_type *>(_value)
+#else
+# define _TO_VOID_PTR(_value) ((void *) (_value))
+# define _FROM_VOID_PTR(_type, _value) ((_type *) (_value))
+#endif
+
+#define _BITS_TO_BYTES(_x) ((_x) >> 3)
+#define _BYTES_TO_BITS(_x) ((_x) << 3)
+
+union _f2u {
+ float f;
+ uint32_t u;
+};
+
+union _d2u {
+ double f;
+ uint64_t u;
+};
+
+uint32_t {{ prefix }}packet_size(void *ctx)
+{
+ return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, ctx)->packet_size;
+}
+
+int {{ prefix }}packet_is_full(void *vctx)
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+
+ return ctx->at == ctx->packet_size;
+}
+
+int {{ prefix }}packet_is_empty(void *vctx)
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+
+ return ctx->at <= ctx->off_content;
+}
+
+uint32_t {{ prefix }}packet_events_discarded(void *vctx)
+{
+ return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->events_discarded;
+}
+
+uint8_t *{{ prefix }}packet_buf(void *vctx)
+{
+ return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->buf;
+}
+
+uint32_t {{ prefix }}packet_buf_size(void *vctx)
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+
+ return _BITS_TO_BYTES(ctx->packet_size);
+}
+
+void {{ prefix }}packet_set_buf(void *vctx, uint8_t *buf, uint32_t buf_size)
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+
+ ctx->buf = buf;
+ ctx->packet_size = _BYTES_TO_BITS(buf_size);
+}
+
+int {{ prefix }}packet_is_open(void *vctx)
+{
+ return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->packet_is_open;
+}
+
+int {{ prefix }}is_in_tracing_section(void *vctx)
+{
+ return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->in_tracing_section;
+}
+
+volatile const int *{{ prefix }}is_in_tracing_section_ptr(void *vctx)
+{
+ return &_FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->in_tracing_section;
+}
+
+int {{ prefix }}is_tracing_enabled(void *vctx)
+{
+ return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->is_tracing_enabled;
+}
+
+void {{ prefix }}enable_tracing(void *vctx, int enable)
+{
+ _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->is_tracing_enabled = enable;
+}
+
+static
+void _write_c_str(struct {{ ctx_struct_name }} *ctx, const char *src)
+{
+ uint32_t sz = strlen(src) + 1;
+
+ memcpy(&ctx->buf[_BITS_TO_BYTES(ctx->at)], src, sz);
+ ctx->at += _BYTES_TO_BITS(sz);
+}
+
+static
+int _reserve_ev_space(void *vctx, uint32_t ev_size)
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+
+ /* event _cannot_ fit? */
+ if (ev_size > (ctx->packet_size - ctx->off_content)) {
+ ctx->events_discarded++;
+ return 0;
+ }
+
+ /* packet is full? */
+ if ({{ prefix }}packet_is_full(ctx)) {
+ /* yes: is back-end full? */
+ if (ctx->cbs.is_backend_full(ctx->data)) {
+ /* yes: discard event */
+ ctx->events_discarded++;
+ return 0;
+ }
+
+ /* back-end is not full: open new packet */
+ ctx->use_cur_last_event_ts = 1;
+ ctx->cbs.open_packet(ctx->data);
+ ctx->use_cur_last_event_ts = 0;
+ }
+
+ /* event fits the current packet? */
+ if (ev_size > (ctx->packet_size - ctx->at)) {
+ /* no: close packet now */
+ ctx->use_cur_last_event_ts = 1;
+ ctx->cbs.close_packet(ctx->data);
+ ctx->use_cur_last_event_ts = 0;
+
+ /* is back-end full? */
+ if (ctx->cbs.is_backend_full(ctx->data)) {
+ /* yes: discard event */
+ ctx->events_discarded++;
+ return 0;
+ }
+
+ /* back-end is not full: open new packet */
+ ctx->use_cur_last_event_ts = 1;
+ ctx->cbs.open_packet(ctx->data);
+ ctx->use_cur_last_event_ts = 0;
+ assert(ev_size <= (ctx->packet_size - ctx->at));
+ }
+
+ return 1;
+}
+
+static
+void _commit_ev(void *vctx)
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+
+ /* is packet full? */
+ if ({{ prefix }}packet_is_full(ctx)) {
+ /* yes: close it now */
+ ctx->cbs.close_packet(ctx->data);
+ }
+}
+
+{% include 'c/ctx-init-func-proto.j2' %}
+
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+ ctx->cbs = cbs;
+ ctx->data = data;
+ ctx->buf = buf;
+ ctx->packet_size = _BYTES_TO_BITS(buf_size);
+ ctx->at = 0;
+ ctx->events_discarded = 0;
+ ctx->packet_is_open = 0;
+ ctx->in_tracing_section = 0;
+ ctx->is_tracing_enabled = 1;
+ ctx->use_cur_last_event_ts = 0;
+}
+
+{% for stream_type in cfg.trace.type.stream_types | sort %}
+ {% set def_clk_type = stream_type.default_clock_type %}
+ {% set sctx_name %}{{ prefix }}{{ stream_type.name }}{% endset %}
+ {% set this_stream_ops = stream_ops[stream_type] %}
+ {% include 'c/open-func-proto.j2' %}
+
+{
+ {{ macros.open_close_func_preamble(stream_type) | indent_tab }}
+
+ /*
+ * This function is either called by a tracing function, or
+ * directly by the platform.
+ *
+ * If it's called by a tracing function, then
+ * `ctx->in_tracing_section` is 1, so it's safe to open
+ * the packet here (alter the packet), even if tracing was
+ * disabled in the meantime because we're already in a tracing
+ * section (which finishes at the end of the tracing function
+ * call).
+ *
+ * If it's called directly by the platform, then if tracing is
+ * disabled, we don't want to alter the packet, and return
+ * immediately.
+ */
+ if (!ctx->is_tracing_enabled && !saved_in_tracing_section) {
+ ctx->in_tracing_section = 0;
+ return;
+ }
+
+ /* we can alter the packet */
+ ctx->in_tracing_section = 1;
+
+ /* do not open a packet that is already open */
+ if (ctx->packet_is_open) {
+ ctx->in_tracing_section = saved_in_tracing_section;
+ return;
+ }
+
+ ctx->at = 0;
+ {% set pkt_header_ops = this_stream_ops.pkt_header_ops %}
+ {% if pkt_header_ops %}
+
+ /* serialize packet header */
+ {
+ {% for op in pkt_header_ops %}
+ {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+ {% endif %}
+
+ /* serialize packet context */
+ {
+ {% for op in this_stream_ops.pkt_ctx_ops %}
+ {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+
+ /* save content beginning's offset */
+ ctx->off_content = ctx->at;
+
+ /* mark current packet as open */
+ ctx->packet_is_open = 1;
+
+ /* not tracing anymore */
+ ctx->in_tracing_section = saved_in_tracing_section;
+}
+
+ {% include 'c/close-func-proto.j2' %}
+
+{
+ {{ macros.open_close_func_preamble(stream_type) | indent_tab }}
+
+ /*
+ * This function is either called by a tracing function, or
+ * directly by the platform.
+ *
+ * If it's called by a tracing function, then
+ * `ctx->in_tracing_section` is 1, so it's safe to close
+ * the packet here (alter the packet), even if tracing was
+ * disabled in the meantime, because we're already in a tracing
+ * section (which finishes at the end of the tracing function
+ * call).
+ *
+ * If it's called directly by the platform, then if tracing is
+ * disabled, we don't want to alter the packet, and return
+ * immediately.
+ */
+ if (!ctx->is_tracing_enabled && !saved_in_tracing_section) {
+ ctx->in_tracing_section = 0;
+ return;
+ }
+
+ /* we can alter the packet */
+ ctx->in_tracing_section = 1;
+
+ /* do not close a packet that is not open */
+ if (!ctx->packet_is_open) {
+ ctx->in_tracing_section = saved_in_tracing_section;
+ return;
+ }
+
+ /* save content size */
+ ctx->content_size = ctx->at;
+ {% if 'timestamp_end' in stream_type._pkt_ctx_ft.members %}
+ {% set op = stream_op_pkt_ctx_op(stream_type, 'timestamp_end') %}
+
+ /* go back to `timestamp_end` field offset */
+ ctx->at = sctx->off_{{ c_common.op_src(op) }};
+
+ {% set src = 'ts' %}
+ {% filter indent_tab(indent_first=True) %}
+ {% include 'c/serialize-write-saved-int-statements.j2' %}
+
+ {% endfilter %}
+ {% endif %}
+ {% if 'content_size' in stream_type._pkt_ctx_ft.members %}
+ {% set op = stream_op_pkt_ctx_op(stream_type, 'content_size') %}
+
+ /* go back to `content_size` field offset */
+ ctx->at = sctx->off_{{ c_common.op_src(op) }};
+
+ {% set src = 'ctx->content_size' %}
+ {% filter indent_tab(indent_first=True) %}
+ {% include 'c/serialize-write-saved-int-statements.j2' %}
+
+ {% endfilter %}
+ {% endif %}
+ {% if 'events_discarded' in stream_type._pkt_ctx_ft.members %}
+ {% set op = stream_op_pkt_ctx_op(stream_type, 'events_discarded') %}
+
+ /* go back to `events_discarded` field offset */
+ ctx->at = sctx->off_{{ c_common.op_src(op) }};
+
+ {% set src = 'ctx->events_discarded' %}
+ {% filter indent_tab(indent_first=True) %}
+ {% include 'c/serialize-write-saved-int-statements.j2' %}
+
+ {% endfilter %}
+ {% endif %}
+
+ /* go back to end of packet */
+ ctx->at = ctx->packet_size;
+
+ /* mark packet as closed */
+ ctx->packet_is_open = 0;
+
+ /* not tracing anymore */
+ ctx->in_tracing_section = saved_in_tracing_section;
+}
+ {% if stream_type._ev_header_ft %}
+
+static void _serialize_ev_header_{{Â stream_type.name }}(void *vctx,
+ uint32_t ev_type_id)
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+ {% if def_clk_type %}
+ struct {{ sctx_name }}_ctx *sctx = _FROM_VOID_PTR(struct {{ sctx_name }}_ctx, vctx);
+ const {{ cg_opts.clock_type_c_types[def_clk_type] }} ts = sctx->cur_last_event_ts;
+ {% endif %}
+
+ /* serialize event header */
+ {
+ {% for op in this_stream_ops.ev_header_ops %}
+ {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+}
+ {% endif %}
+ {% if stream_type.event_common_context_field_type %}
+
+static void _serialize_ev_common_ctx_{{Â stream_type.name }}(void *vctx{{ stream_type | serialize_ev_common_ctx_func_params_str }})
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+
+ /* serialize event common context */
+ {
+ {% for op in this_stream_ops.ev_common_ctx_ops %}
+ {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+}
+ {% endif %}
+ {# internal serialization functions #}
+ {% for ev_type in stream_type.event_types | sort %}
+
+static void _serialize_ev_{{ stream_type.name }}_{{ ev_type.name }}(void *vctx{{ (stream_type, ev_type) | trace_func_params_str }})
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+ {% if stream_type._ev_header_ft %}
+
+ /* serialize header */
+ _serialize_ev_header_{{ stream_type.name }}(ctx, {{ ev_type.id }});
+ {% endif %}
+ {% if stream_type.event_common_context_field_type %}
+
+ /* serialize common context */
+ {% set params = macros.ft_call_params(root_ft_prefixes.SEC, stream_type.event_common_context_field_type) %}
+ _serialize_ev_common_ctx_{{ stream_type.name }}(ctx{{ params }});
+ {% endif %}
+ {% set this_ev_ops = this_stream_ops.ev_ops[ev_type] %}
+ {% if this_ev_ops.spec_ctx_ops %}
+
+ /* serialize specific context */
+ {
+ {% for op in this_ev_ops.spec_ctx_ops %}
+ {{ op.serialize_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+ {% endif %}
+ {% if this_ev_ops.payload_ops %}
+
+ /* serialize payload */
+ {
+ {% for op in this_ev_ops.payload_ops %}
+ {{ op.serialize_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+ {% endif %}
+}
+ {% endfor %}
+ {# internal size functions #}
+ {% for ev_type in stream_type.event_types | sort %}
+ {% set this_ev_ops = this_stream_ops.ev_ops[ev_type] %}
+
+static uint32_t _ev_size_{{ stream_type.name }}_{{ ev_type.name }}(void *vctx{{ (stream_type, ev_type) | trace_func_params_str }})
+{
+ struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
+ uint32_t at = ctx->at;
+ {% if this_stream_ops.ev_header_ops %}
+
+ /* add header size */
+ {
+ {% for op in this_stream_ops.ev_header_ops %}
+ {{ op.size_str(stream_type=stream_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+ {% endif %}
+ {% if this_stream_ops.ev_common_ctx_ops %}
+
+ /* add common context size */
+ {
+ {% for op in this_stream_ops.ev_common_ctx_ops %}
+ {{ op.size_str(stream_type=stream_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+ {% endif %}
+ {% if this_ev_ops.spec_ctx_ops %}
+
+ /* add specific context size */
+ {
+ {% for op in this_ev_ops.spec_ctx_ops %}
+ {{ op.size_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+ {% endif %}
+ {% if this_ev_ops.payload_ops %}
+
+ /* add payload size */
+ {
+ {% for op in this_ev_ops.payload_ops %}
+ {{ op.size_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
+
+ {% endfor %}
+ }
+ {% endif %}
+
+ return at - ctx->at;
+}
+ {% endfor %}
+ {# public tracing functions #}
+ {% for ev_type in stream_type.event_types | sort %}
+
+ {% include 'c/trace-func-proto.j2' %}
+
+{
+ struct {{ ctx_struct_name }} *ctx = &sctx->parent;
+ uint32_t ev_size;
+
+ {% if def_clk_type %}
+ /* save time */
+ sctx->cur_last_event_ts = ctx->cbs.{{ def_clk_type.name }}_clock_get_value(ctx->data);
+
+ {% endif %}
+
+ if (!ctx->is_tracing_enabled) {
+ return;
+ }
+
+ /* we can alter the packet */
+ ctx->in_tracing_section = 1;
+
+ /* compute event size */
+ {% set ev_common_ctx_params = macros.ft_call_params(root_ft_prefixes.SEC, stream_type.event_common_context_field_type) %}
+ {% set spec_ctx_params = macros.ft_call_params(root_ft_prefixes.EC, ev_type.specific_context_field_type) %}
+ {% set payload_params = macros.ft_call_params(root_ft_prefixes.EP, ev_type.payload_field_type) %}
+ {% set params %}{{ ev_common_ctx_params }}{{ spec_ctx_params }}{{ payload_params }}{% endset %}
+ ev_size = _ev_size_{{ stream_type.name }}_{{ ev_type.name }}(_TO_VOID_PTR(ctx){{ params }});
+
+ /* do we have enough space to serialize? */
+ if (!_reserve_ev_space(_TO_VOID_PTR(ctx), ev_size)) {
+ /* no: forget this */
+ ctx->in_tracing_section = 0;
+ return;
+ }
+
+ /* serialize event */
+ _serialize_ev_{{ stream_type.name }}_{{ ev_type.name }}(_TO_VOID_PTR(ctx){{ params }});
+
+ /* commit event */
+ _commit_ev(_TO_VOID_PTR(ctx));
+
+ /* not tracing anymore */
+ ctx->in_tracing_section = 0;
+}
+ {% endfor %}
+{% endfor %}
--- /dev/null
+{% import 'common.j2' as common %}
+{% import 'c/common.j2' as c_common %}
+{% set prefix = common.prefix %}
+{% set ucprefix = common.ucprefix %}
+{% set trace_type = cfg.trace.type %}
+{% set cg_opts = cfg.options.code_generation_options %}
+{% set def_stream_type = cg_opts.default_stream_type %}
+{% set header_opts = cg_opts.header_options %}
+#ifndef _{{ ucprefix }}H
+#define _{{ ucprefix }}H
+
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ *
+ * The following C code was generated by barectf v{{ barectf_version.__version__ }}
+ * on {{ common.gen_date }}.
+ *
+ * For more details, see <https://barectf.org/>.
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if header_opts.identifier_prefix_definition %}
+#define _BARECTF_PREFIX {{ prefix }}
+{% endif %}
+{% if def_stream_type and header_opts.default_stream_type_name_definition %}
+#define _BARECTF_DEFAULT_STREAM {{ def_stream_type.name }}
+{% endif %}
+{% if def_stream_type %}
+
+ {% for ev_type in def_stream_type.event_types | sort %}
+#define {{ prefix }}trace_{{ ev_type.name }} {{ c_common.trace_func_name(def_stream_type, ev_type) }}
+ {% endfor %}
+{% endif %}
+
+struct {{ prefix }}ctx;
+
+uint32_t {{ prefix }}packet_size(void *ctx);
+int {{ prefix }}packet_is_full(void *ctx);
+int {{ prefix }}packet_is_empty(void *ctx);
+uint32_t {{ prefix }}packet_events_discarded(void *ctx);
+uint8_t *{{ prefix }}packet_buf(void *ctx);
+void {{ prefix }}packet_set_buf(void *ctx, uint8_t *buf, uint32_t buf_size);
+uint32_t {{ prefix }}packet_buf_size(void *ctx);
+int {{ prefix }}packet_is_open(void *ctx);
+int {{ prefix }}is_in_tracing_section(void *ctx);
+volatile const int *{{ prefix }}is_in_tracing_section_ptr(void *ctx);
+int {{ prefix }}is_tracing_enabled(void *ctx);
+void {{ prefix }}enable_tracing(void *ctx, int enable);
+
+/* barectf platform callbacks */
+struct {{ prefix }}platform_callbacks {
+{% set clk_types = trace_type.clock_types %}
+{% if clk_types %}
+ /* clock callbacks */
+ {% for clk_type in clk_types | sort %}
+ {{ cg_opts.clock_type_c_types[clk_type]Â }} (*{{ clk_type.name }}_clock_get_value)(void *);
+ {% endfor %}
+
+{% endif %}
+ /* is back-end full? */
+ int (*is_backend_full)(void *);
+
+ /* open packet */
+ void (*open_packet)(void *);
+
+ /* close packet */
+ void (*close_packet)(void *);
+};
+
+/* common barectf context */
+struct {{ prefix }}ctx {
+ /* platform callbacks */
+ struct {{ prefix }}platform_callbacks cbs;
+
+ /* platform data (passed to callbacks) */
+ void *data;
+
+ /* output buffer (will contain a CTF binary packet) */
+ uint8_t *buf;
+
+ /* packet's total size (bits) */
+ uint32_t packet_size;
+
+ /* packet's content size (bits) */
+ uint32_t content_size;
+
+ /* current position from beginning of packet (bits) */
+ uint32_t at;
+
+ /* size of packet header + context fields (content offset) */
+ uint32_t off_content;
+
+ /* discarded event counter */
+ uint32_t events_discarded;
+
+ /* current packet is open? */
+ int packet_is_open;
+
+ /* in tracing code? */
+ volatile int in_tracing_section;
+
+ /* tracing is enabled? */
+ volatile int is_tracing_enabled;
+
+ /* use current/last event time when opening/closing packets */
+ int use_cur_last_event_ts;
+};
+
+{% for stream_type in trace_type.stream_types | sort %}
+/* context for stream type `{{ stream_type.name }}` */
+struct {{ prefix }}{{ stream_type.name }}_ctx {
+ /* parent */
+ struct {{ prefix }}ctx parent;
+
+ /* config-specific members follow */
+ {% if trace_type._pkt_header_ft %}
+ {% for member_name in trace_type._pkt_header_ft.members %}
+ uint32_t off_tph_{{ member_name }};
+ {% endfor %}
+ {% endif %}
+ {% for member_name in stream_type._pkt_ctx_ft.members %}
+ uint32_t off_spc_{{ member_name }};
+ {% endfor %}
+ {% if stream_type.default_clock_type %}
+ {{ cg_opts.clock_type_c_types[stream_type.default_clock_type] }} cur_last_event_ts;
+ {% endif %}
+};
+
+{% endfor %}
+{% include 'c/ctx-init-func-proto.j2' %};
+
+{% for stream_type in trace_type.stream_types | sort %}
+ {% include 'c/open-func-proto.j2' %};
+
+ {% include 'c/close-func-proto.j2' %};
+ {% for ev_type in stream_type.event_types | sort %}
+
+ {% include 'c/trace-func-proto.j2' %};
+ {% endfor %}
+{% endfor %}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _{{ ucprefix }}H */
--- /dev/null
+{% import 'common.j2' as common %}
+{% set prefix = common.prefix %}
+{% set ucprefix = common.ucprefix %}
+#ifndef _{{ ucprefix }}BITFIELD_H
+#define _{{ ucprefix }}BITFIELD_H
+
+/*
+ * BabelTrace
+ *
+ * Bitfields read/write functions.
+ *
+ * Copyright (c) 2010-2020 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <limits.h>
+
+#ifdef __cplusplus
+# define {{ ucprefix }}CAST_PTR(_type, _value) \
+ static_cast<_type>(static_cast<void *>(_value))
+#else
+# define {{ ucprefix }}CAST_PTR(_type, _value) ((void *) (_value))
+#endif
+
+{% set def_bo = cfg.trace.type.default_byte_order %}
+{% set def_bo_str = 'LITTLE_ENDIAN' if def_bo == barectf_config.ByteOrder.LITTLE_ENDIAN else 'BIG_ENDIAN' %}
+#define {{ ucprefix }}BYTE_ORDER {{ def_bo_str }}
+
+
+/* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */
+#define _{{ prefix }}bt_piecewise_rshift(_vtype, _v, _shift) \
+do { \
+ unsigned long ___shift = (_shift); \
+ unsigned long sb = (___shift) / (sizeof(_v) * CHAR_BIT - 1); \
+ unsigned long final = (___shift) % (sizeof(_v) * CHAR_BIT - 1); \
+ \
+ for (; sb; sb--) \
+ _v >>= sizeof(_v) * CHAR_BIT - 1; \
+ _v >>= final; \
+} while (0)
+
+/*
+ * {{ prefix }}bt_bitfield_write - write integer to a bitfield in native endianness
+ *
+ * Save integer to the bitfield, which starts at the "start" bit, has "len"
+ * bits.
+ * The inside of a bitfield is from high bits to low bits.
+ * Uses native endianness.
+ * For unsigned "v", pad MSB with 0 if bitfield is larger than v.
+ * For signed "v", sign-extend v if bitfield is larger than v.
+ *
+ * On little endian, bytes are placed from the less significant to the most
+ * significant. Also, consecutive bitfields are placed from lower bits to higher
+ * bits.
+ *
+ * On big endian, bytes are places from most significant to less significant.
+ * Also, consecutive bitfields are placed from higher to lower bits.
+ */
+
+#define _{{ prefix }}bt_bitfield_write_le(_ptr, type, _start, _length, _vtype, _v) \
+do { \
+ _vtype __v = (_v); \
+ type *__ptr = {{ ucprefix }}CAST_PTR(type *, _ptr); \
+ unsigned long __start = (_start), __length = (_length); \
+ type mask, cmask; \
+ unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
+ unsigned long start_unit, end_unit, this_unit; \
+ unsigned long end, cshift; /* cshift is "complement shift" */ \
+ \
+ if (!__length) \
+ break; \
+ \
+ end = __start + __length; \
+ start_unit = __start / ts; \
+ end_unit = (end + (ts - 1)) / ts; \
+ \
+ /* Trim v high bits */ \
+ if (__length < sizeof(__v) * CHAR_BIT) \
+ __v &= ~((~(_vtype) 0) << __length); \
+ \
+ /* We can now append v with a simple "or", shift it piece-wise */ \
+ this_unit = start_unit; \
+ if (start_unit == end_unit - 1) { \
+ mask = ~((~(type) 0) << (__start % ts)); \
+ if (end % ts) \
+ mask |= (~(type) 0) << (end % ts); \
+ cmask = (type) __v << (__start % ts); \
+ cmask &= ~mask; \
+ __ptr[this_unit] &= mask; \
+ __ptr[this_unit] |= cmask; \
+ break; \
+ } \
+ if (__start % ts) { \
+ cshift = __start % ts; \
+ mask = ~((~(type) 0) << cshift); \
+ cmask = (type) __v << cshift; \
+ cmask &= ~mask; \
+ __ptr[this_unit] &= mask; \
+ __ptr[this_unit] |= cmask; \
+ _{{ prefix }}bt_piecewise_rshift(_vtype, __v, ts - cshift); \
+ __start += ts - cshift; \
+ this_unit++; \
+ } \
+ for (; this_unit < end_unit - 1; this_unit++) { \
+ __ptr[this_unit] = (type) __v; \
+ _{{ prefix }}bt_piecewise_rshift(_vtype, __v, ts); \
+ __start += ts; \
+ } \
+ if (end % ts) { \
+ mask = (~(type) 0) << (end % ts); \
+ cmask = (type) __v; \
+ cmask &= ~mask; \
+ __ptr[this_unit] &= mask; \
+ __ptr[this_unit] |= cmask; \
+ } else \
+ __ptr[this_unit] = (type) __v; \
+} while (0)
+
+#define _{{ prefix }}bt_bitfield_write_be(_ptr, type, _start, _length, _vtype, _v) \
+do { \
+ _vtype __v = (_v); \
+ type *__ptr = {{ ucprefix }}CAST_PTR(type *, _ptr); \
+ unsigned long __start = (_start), __length = (_length); \
+ type mask, cmask; \
+ unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
+ unsigned long start_unit, end_unit, this_unit; \
+ unsigned long end, cshift; /* cshift is "complement shift" */ \
+ \
+ if (!__length) \
+ break; \
+ \
+ end = __start + __length; \
+ start_unit = __start / ts; \
+ end_unit = (end + (ts - 1)) / ts; \
+ \
+ /* Trim v high bits */ \
+ if (__length < sizeof(__v) * CHAR_BIT) \
+ __v &= ~((~(_vtype) 0) << __length); \
+ \
+ /* We can now append v with a simple "or", shift it piece-wise */ \
+ this_unit = end_unit - 1; \
+ if (start_unit == end_unit - 1) { \
+ mask = ~((~(type) 0) << ((ts - (end % ts)) % ts)); \
+ if (__start % ts) \
+ mask |= (~((type) 0)) << (ts - (__start % ts)); \
+ cmask = (type) __v << ((ts - (end % ts)) % ts); \
+ cmask &= ~mask; \
+ __ptr[this_unit] &= mask; \
+ __ptr[this_unit] |= cmask; \
+ break; \
+ } \
+ if (end % ts) { \
+ cshift = end % ts; \
+ mask = ~((~(type) 0) << (ts - cshift)); \
+ cmask = (type) __v << (ts - cshift); \
+ cmask &= ~mask; \
+ __ptr[this_unit] &= mask; \
+ __ptr[this_unit] |= cmask; \
+ _{{ prefix }}bt_piecewise_rshift(_vtype, __v, cshift); \
+ end -= cshift; \
+ this_unit--; \
+ } \
+ for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
+ __ptr[this_unit] = (type) __v; \
+ _{{ prefix }}bt_piecewise_rshift(_vtype, __v, ts); \
+ end -= ts; \
+ } \
+ if (__start % ts) { \
+ mask = (~(type) 0) << (ts - (__start % ts)); \
+ cmask = (type) __v; \
+ cmask &= ~mask; \
+ __ptr[this_unit] &= mask; \
+ __ptr[this_unit] |= cmask; \
+ } else \
+ __ptr[this_unit] = (type) __v; \
+} while (0)
+
+/*
+ * {{ prefix }}bt_bitfield_write_le - write integer to a bitfield in little endian
+ * {{ prefix }}bt_bitfield_write_be - write integer to a bitfield in big endian
+ */
+
+#if ({{ ucprefix }}BYTE_ORDER == LITTLE_ENDIAN)
+
+#define {{ prefix }}bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v) \
+ _{{ prefix }}bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v)
+
+#define {{ prefix }}bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v) \
+ _{{ prefix }}bt_bitfield_write_be(ptr, unsigned char, _start, _length, _vtype, _v)
+
+#elif ({{ ucprefix }}BYTE_ORDER == BIG_ENDIAN)
+
+#define {{ prefix }}bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v) \
+ _{{ prefix }}bt_bitfield_write_le(ptr, unsigned char, _start, _length, _vtype, _v)
+
+#define {{ prefix }}bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v) \
+ _{{ prefix }}bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v)
+
+#else /* ({{ ucprefix }}BYTE_ORDER == PDP_ENDIAN) */
+
+#error "Byte order not supported"
+
+#endif
+
+#endif /* _{{ ucprefix }}BITFIELD_H */
--- /dev/null
+{% import 'common.j2' as common %}
+/* close packet for stream type `{{ stream_type.name }}` */
+void {{ common.prefix }}{{ stream_type.name }}_close_packet(struct {{ common.prefix }}{{ stream_type.name }}_ctx *sctx)
--- /dev/null
+{#
+ # Common variables and macros (for C templates).
+ #}
+
+{% import 'common.j2' as common %}
+
+{# generic barectf context structure name #}
+{% set ctx_struct_name %}{{ common.prefix }}ctx{% endset %}
+
+{#
+ # Generates the name of a tracing function for the stream type
+ # `stream_type` and the event type `ev_type`.
+ #
+ # Example:
+ #
+ # barectf_my_stream_trace_my_event
+ #}
+{% macro trace_func_name(stream_type, ev_type) %}
+{{ common.prefix }}{{ stream_type.name }}_trace_{{ ev_type.name }}
+{%- endmacro %}
+
+{#
+ # Generates the name of a source variable from the names of the
+ # operation `op`.
+ #
+ # Example:
+ #
+ # ep_msg_id
+ #}
+{% macro op_src(op) %}
+{{ op.names | join('_') }}
+{%- endmacro %}
--- /dev/null
+{% import 'common.j2' as common %}
+/* initialize context */
+void {{ common.prefix }}init(void *vctx,
+ uint8_t *buf, uint32_t buf_size,
+ struct {{ common.prefix }}platform_callbacks cbs, void *data)
--- /dev/null
+{% for param in params %}
+ {% set c_type = param.ft | ft_c_type %},
+ {{ c_type }}{{ ' ' if not c_type.endswith('*') }}{{ prefix }}_{{ param.name }}
+{%- endfor %}
--- /dev/null
+{% import 'common.j2' as common %}
+/* open packet for stream type `{{ stream_type.name }}` */
+void {{ common.prefix }}{{ stream_type.name }}_open_packet(
+ struct {{ common.prefix }}{{ stream_type.name }}_ctx *sctx{{ stream_type | open_func_params_str }})
--- /dev/null
+{% include 'c/align-statements-comment.j2' %}
+
+_ALIGN(ctx->at, {{ op.value }});
--- /dev/null
+{% import 'common.j2' as common %}
+{% set bo = 'le' if op.ft.byte_order == barectf_config.ByteOrder.LITTLE_ENDIAN else 'be' %}
+{{ common.prefix }}bt_bitfield_write_{{ bo }}(&ctx->buf[_BITS_TO_BYTES(ctx->at)],
+ uint8_t, {{ op.offset_in_byte }}, {{ op.ft.size }}, {{ c_type }},
+ ({{ c_type }}) {{ src }});
+ctx->at += {{ op.ft.size }};
--- /dev/null
+{% set c_type = op.ft | ft_c_type %}
+{% set src = 'ev_type_id' %}
+/* write event type ID field */
+{% include 'c/serialize-write-bit-array-statements.j2' %}
--- /dev/null
+{% import 'c/common.j2' as c_common %}
+{% set c_type = op.ft | ft_c_type %}
+{% set src = c_common.op_src(op) %}
+{% include 'c/serialize-write-statements-comment.j2' %}
+
+{% include 'c/serialize-write-bit-array-statements.j2' %}
--- /dev/null
+{% set c_type = op.ft | ft_c_type %}
+{% set src = '0xc1fc1fc1UL' %}
+/* write magic number field */
+{% include 'c/serialize-write-bit-array-statements.j2' %}
--- /dev/null
+{% set c_type = op.ft | ft_c_type %}
+{% set src = 'ctx->packet_size' %}
+/* write packet total size field */
+{% include 'c/serialize-write-bit-array-statements.j2' %}
--- /dev/null
+{% import 'c/common.j2' as c_common %}
+{% set union_name = 'f2u' if op.ft.size == 32 else 'd2u' %}
+{% set c_type = 'uint32_t' if op.ft.size == 32 else 'uint64_t' %}
+{% set src %}{{ union_name }}.u{% endset %}
+{% include 'c/serialize-write-statements-comment.j2' %}
+
+{
+ union _{{ union_name }} {{ union_name }};
+
+ {{ union_name }}.f = {{ c_common.op_src(op) }};
+{% filter indent_tab(indent_first=True) %}
+ {% include 'c/serialize-write-bit-array-statements.j2' %}
+
+{% endfilter %}
+}
--- /dev/null
+{% import 'c/common.j2' as c_common %}
+{% set c_type = op.ft | ft_c_type %}
+{% include 'c/serialize-write-statements-comment.j2' %}
+
+{% include 'c/serialize-write-bit-array-statements.j2' %}
--- /dev/null
+{% import 'c/common.j2' as c_common %}
+/* do not write `{{ op.top_name }}` field; save its offset */
+sctx->off_{{ c_common.op_src(op) }} = ctx->at;
+ctx->at += {{ op.ft.size }};
--- /dev/null
+/* write `{{ op.top_name }}` field */
--- /dev/null
+{% set c_type = op.ft | ft_c_type %}
+{% set src = stream_type.id %}
+/* write stream type ID field */
+{% include 'c/serialize-write-bit-array-statements.j2' %}
--- /dev/null
+{% import 'c/common.j2' as c_common %}
+{% include 'c/serialize-write-statements-comment.j2' %}
+
+_write_c_str(ctx, {{ c_common.op_src(op) }});
--- /dev/null
+{% set c_type = op.ft | ft_c_type %}
+{% set src = 'ts' %}
+/* write {{ 'beginning ' if op.top_name == 'timestamp_begin' }}time field */
+{% include 'c/serialize-write-bit-array-statements.j2' %}
--- /dev/null
+/* write UUID */
+{
+ static uint8_t uuid[] = {
+{% for row in cfg.trace.type.uuid.bytes | batch(4) %}
+ {{ row | join(', ') }},
+{% endfor %}
+ };
+
+ _ALIGN(ctx->at, 8);
+ memcpy(&ctx->buf[_BITS_TO_BYTES(ctx->at)], uuid, 16);
+ ctx->at += _BYTES_TO_BITS(16);
+}
--- /dev/null
+{% include 'c/align-statements-comment.j2' %}
+
+_ALIGN(at, {{ op.value }});
--- /dev/null
+/* add `{{ op.top_name }}` bit array field's size */
+at += {{ op.ft.size }};
--- /dev/null
+{% import 'c/common.j2' as c_common %}
+/* add `{{ op.top_name }}` string field's size */
+at += _BYTES_TO_BITS(strlen({{ c_common.op_src(op) }}) + 1);
--- /dev/null
+{% import 'common.j2' as common %}
+/* trace (stream type `{{ stream_type.name }}`, event type `{{ ev_type.name }}`) */
+void {{ common.prefix }}{{ stream_type.name }}_trace_{{ ev_type.name }}(struct {{ common.prefix }}{{ stream_type.name }}_ctx *sctx{{ (stream_type, ev_type) | trace_func_params_str }})
+++ /dev/null
-enum : {{ ft | int_ft_str }} {
-{% for label, mapping in ft.mappings.items() %}
-{% for rg in mapping.ranges %}
- {% if rg.lower == rg.upper %}
- {% set rg_str = rg.lower %}
- {% else %}
- {% set rg_str %}{{ rg.lower }} ... {{ rg.upper }}{% endset %}
- {% endif %}
- "{{ label | escape_dq }}" = {{ rg_str }},
-{% endfor %}
-{% endfor %}
-}
+++ /dev/null
-integer {
- signed = {{ 'true' if is_signed else 'false' }};
- size = {{ ft.size }};
- align = {{ ft.alignment }};
- byte_order = {{ ft.byte_order | bo_str }};
- base = {{ ft.preferred_display_base | disp_base_int }};
- {% if ft._mapped_clk_type_name %}
- map = clock.{{ ft._mapped_clk_type_name }}.value;
- {% endif %}
-}
+++ /dev/null
-floating_point {
- mant_dig = {{ 24 if ft.size == 32 else 53 }};
- exp_dig = {{ 8 if ft.size == 32 else 11 }};
- align = {{ ft.alignment }};
- byte_order = {{ ft.byte_order | bo_str }};
-}
+++ /dev/null
-string {
- encoding = UTF8;
-}
+++ /dev/null
-struct {
-{% for name, member in ft.members.items() %}
-{#
- # `chain` is a list of static array field types terminated with a
- # non-array field type (the most nested).
- #}
-{% set chain = ft_chain(member.field_type) %}
- {{ chain[-1] | ft_str | indent_tab }} {{ name }}
- {%- for array_ft in chain[:-1] %}[{{ array_ft.length }}]{% endfor %};
-{% endfor %}
-} align({{ ft.minimum_alignment }})
+++ /dev/null
-{% import 'common.j2' as common %}
-/* CTF 1.8 */
-
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- *
- * The following TSDL code was generated by barectf v{{ barectf_version.__version__ }}
- * on {{ common.gen_date }}.
- *
- * For more details, see <https://barectf.org/>.
- */
-{#
- # Generates a root field type string named `name` for the field type
- # `rft` with all the lines except the first one indented with a single
- # tab.
- #}
-{% macro root_ft(name, rft) -%}
-{{ name }} := {{ rft | ft_str | indent_tab }};
-{%- endmacro %}
-
-trace {
- major = 1;
- minor = 8;
- byte_order = {{ cfg.trace.type.default_byte_order | bo_str }};
- {% if cfg.trace.type.uuid %}
- uuid = "{{ cfg.trace.type.uuid }}";
- {% endif %}
- {% if cfg.trace.type._pkt_header_ft %}
- {{ root_ft('packet.header', cfg.trace.type._pkt_header_ft) }}
- {% endif %}
-};
-
-env {
-{% for name, value in cfg.trace.environment.items() %}
- {{ name }} = {{ value if value is number else '"{}"'.format(value | escape_dq) }};
-{% endfor %}
-};
-
-{# all clock types (stream types's default clock types) #}
-{% for clk_type in cfg.trace.type.clock_types | sort %}
-clock {
- name = {{ clk_type.name }};
- {% if clk_type.description %}
- description = "{{ clk_type.description | escape_dq }}";
- {% endif %}
- {% if clk_type.uuid %}
- uuid = "{{ clk_type.uuid }}";
- {% endif %}
- freq = {{ clk_type.frequency }};
- precision = {{ clk_type.precision }};
- offset_s = {{ clk_type.offset.seconds }};
- offset = {{ clk_type.offset.cycles }};
- absolute = {{ 'true' if clk_type.origin_is_unix_epoch else 'false' }};
-};
-
-{% endfor %}
-{# stream types and their event types #}
-{%- for stream_type in cfg.trace.type.stream_types | sort %}
-/* Stream type `{{ stream_type.name }}` */
-stream {
- id = {{ stream_type.id }};
- {{ root_ft('packet.context', stream_type._pkt_ctx_ft) }}
- {% if stream_type._ev_header_ft %}
- {{ root_ft('event.header', stream_type._ev_header_ft) }}
- {% endif %}
- {% if stream_type.event_common_context_field_type %}
- {{ root_ft('event.context', stream_type.event_common_context_field_type) }}
- {% endif %}
-};
-
-{# stream type's event types #}
-{% for ev_type in stream_type.event_types | sort %}
-event {
- id = {{ ev_type.id }};
- stream_id = {{ stream_type.id }};
- name = "{{ ev_type.name }}";
- {% if ev_type.log_level %}
- loglevel = {{ ev_type.log_level }};
- {% endif %}
- {% if ev_type.specific_context_field_type %}
- {{ root_ft('context', ev_type.specific_context_field_type) }}
- {% endif %}
- {% if ev_type.payload_field_type %}
- {{ root_ft('fields', ev_type.payload_field_type) }}
- {% endif %}
-};
-
-{% endfor %}
-{% endfor %}
--- /dev/null
+enum : {{ ft | int_ft_str }} {
+{% for label, mapping in ft.mappings.items() %}
+{% for rg in mapping.ranges %}
+ {% if rg.lower == rg.upper %}
+ {% set rg_str = rg.lower %}
+ {% else %}
+ {% set rg_str %}{{ rg.lower }} ... {{ rg.upper }}{% endset %}
+ {% endif %}
+ "{{ label | escape_dq }}" = {{ rg_str }},
+{% endfor %}
+{% endfor %}
+}
--- /dev/null
+integer {
+ signed = {{ 'true' if is_signed else 'false' }};
+ size = {{ ft.size }};
+ align = {{ ft.alignment }};
+ byte_order = {{ ft.byte_order | bo_str }};
+ base = {{ ft.preferred_display_base | disp_base_int }};
+ {% if ft._mapped_clk_type_name %}
+ map = clock.{{ ft._mapped_clk_type_name }}.value;
+ {% endif %}
+}
--- /dev/null
+{% import 'common.j2' as common %}
+/* CTF 1.8 */
+
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ *
+ * The following TSDL code was generated by barectf v{{ barectf_version.__version__ }}
+ * on {{ common.gen_date }}.
+ *
+ * For more details, see <https://barectf.org/>.
+ */
+{#
+ # Generates a root field type string named `name` for the field type
+ # `rft` with all the lines except the first one indented with a single
+ # tab.
+ #}
+{% macro root_ft(name, rft) -%}
+{{ name }} := {{ rft | ft_str | indent_tab }};
+{%- endmacro %}
+
+trace {
+ major = 1;
+ minor = 8;
+ byte_order = {{ cfg.trace.type.default_byte_order | bo_str }};
+{% if cfg.trace.type.uuid %}
+ uuid = "{{ cfg.trace.type.uuid }}";
+{% endif %}
+{% if cfg.trace.type._pkt_header_ft %}
+ {{ root_ft('packet.header', cfg.trace.type._pkt_header_ft) }}
+{% endif %}
+};
+
+env {
+{% for name, value in cfg.trace.environment.items() %}
+ {{ name }} = {{ value if value is number else '"{}"'.format(value | escape_dq) }};
+{% endfor %}
+};
+
+{# all clock types (stream types's default clock types) #}
+{% for clk_type in cfg.trace.type.clock_types | sort %}
+clock {
+ name = {{ clk_type.name }};
+ {% if clk_type.description %}
+ description = "{{ clk_type.description | escape_dq }}";
+ {% endif %}
+ {% if clk_type.uuid %}
+ uuid = "{{ clk_type.uuid }}";
+ {% endif %}
+ freq = {{ clk_type.frequency }};
+ precision = {{ clk_type.precision }};
+ offset_s = {{ clk_type.offset.seconds }};
+ offset = {{ clk_type.offset.cycles }};
+ absolute = {{ 'true' if clk_type.origin_is_unix_epoch else 'false' }};
+};
+
+{% endfor %}
+{# stream types and their event types #}
+{%- for stream_type in cfg.trace.type.stream_types | sort %}
+/* Stream type `{{ stream_type.name }}` */
+stream {
+ id = {{ stream_type.id }};
+ {{ root_ft('packet.context', stream_type._pkt_ctx_ft) }}
+ {% if stream_type._ev_header_ft %}
+ {{ root_ft('event.header', stream_type._ev_header_ft) }}
+ {% endif %}
+ {% if stream_type.event_common_context_field_type %}
+ {{ root_ft('event.context', stream_type.event_common_context_field_type) }}
+ {% endif %}
+};
+
+ {# stream type's event types #}
+ {% for ev_type in stream_type.event_types | sort %}
+event {
+ id = {{ ev_type.id }};
+ stream_id = {{ stream_type.id }};
+ name = "{{ ev_type.name }}";
+ {% if ev_type.log_level %}
+ loglevel = {{ ev_type.log_level }};
+ {% endif %}
+ {% if ev_type.specific_context_field_type %}
+ {{ root_ft('context', ev_type.specific_context_field_type) }}
+ {% endif %}
+ {% if ev_type.payload_field_type %}
+ {{ root_ft('fields', ev_type.payload_field_type) }}
+ {% endif %}
+};
+
+ {% endfor %}
+{% endfor %}
--- /dev/null
+floating_point {
+ mant_dig = {{ 24 if ft.size == 32 else 53 }};
+ exp_dig = {{ 8 if ft.size == 32 else 11 }};
+ align = {{ ft.alignment }};
+ byte_order = {{ ft.byte_order | bo_str }};
+}
--- /dev/null
+string {
+ encoding = UTF8;
+}
--- /dev/null
+struct {
+{% for name, member in ft.members.items() %}
+{#
+ # `chain` is a list of static array field types terminated with a
+ # non-array field type (the most nested).
+ #}
+{% set chain = ft_chain(member.field_type) %}
+ {{ chain[-1] | ft_str | indent_tab }} {{ name }}
+ {%- for array_ft in chain[:-1] %}[{{ array_ft.length }}]{% endfor %};
+{% endfor %}
+} align({{ ft.minimum_alignment }})
def _create_template(name: str, is_file_template: bool = False,
cfg: Optional[barectf_config.Configuration] = None) -> barectf_template._Template:
- return barectf_template._Template(name, is_file_template, cfg,
+ return barectf_template._Template(f'metadata/{name}', is_file_template, cfg,
typing.cast(barectf_template._Filters, _TEMPL_FILTERS))
-_ENUM_FT_TEMPL = _create_template('metadata-enum-ft.j2')
-_INT_FT_TEMPL = _create_template('metadata-int-ft.j2')
-_REAL_FT_TEMPL = _create_template('metadata-real-ft.j2')
-_STR_FT_TEMPL = _create_template('metadata-str-ft.j2')
-_STRUCT_FT_TEMPL = _create_template('metadata-struct-ft.j2')
+_ENUM_FT_TEMPL = _create_template('enum-ft.j2')
+_INT_FT_TEMPL = _create_template('int-ft.j2')
+_REAL_FT_TEMPL = _create_template('real-ft.j2')
+_STR_FT_TEMPL = _create_template('str-ft.j2')
+_STRUCT_FT_TEMPL = _create_template('struct-ft.j2')
def _from_config(cfg: barectf_config.Configuration) -> str:
packet_size: uint32
content_size: uint32
events_discarded: uint32
+ salut: string
event-header-type:
class: struct
fields: