def generate_c_sources(self):
if self._c_sources is None:
- bitfield_header_name = f'{self._file_name_prefix}-bitfield.h'
self._c_sources = [
_GeneratedFile(f'{self._file_name_prefix}.c',
self._ccode_gen.generate_c_src(self._barectf_header_name,
self._actions.append(_SerializeSerializationAction(offset_in_byte, ft, self._names))
-_PREFIX_TPH = 'tph_'
-_PREFIX_SPC = 'spc_'
-_PREFIX_SEH = 'seh_'
-_PREFIX_SEC = 'sec_'
-_PREFIX_EC = 'ec_'
-_PREFIX_EP = 'ep_'
-_PREFIX_TO_NAME = {
- _PREFIX_TPH: 'trace packet header',
- _PREFIX_SPC: 'stream packet context',
- _PREFIX_SEH: 'stream event header',
- _PREFIX_SEC: 'stream event context',
- _PREFIX_EC: 'event context',
- _PREFIX_EP: 'event payload',
+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',
}
self._cg = barectf_codegen._CodeGenerator('\t')
self._saved_serialization_actions = {}
+ @property
+ def _template_filters(self):
+ return {
+ 'ft_c_type': self._get_ft_c_type,
+ }
+
def _create_template(self, name: str) -> barectf_template._Template:
- return barectf_template._Template(name, cfg=self._cfg)
+ return barectf_template._Template(name, False, self._cfg, self._template_filters)
def _create_file_template(self, name: str) -> barectf_template._Template:
- return barectf_template._Template(name, True, self._cfg)
+ return barectf_template._Template(name, True, self._cfg, self._template_filters)
@property
def _trace_type(self):
def _clk_type_c_type(self, clk_type):
return self._cfg.options.code_generation_options.clock_type_c_types[clk_type]
- def _generate_ctx_parent(self):
- tmpl = barectf_templates._CTX_PARENT
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix))
-
- def _generate_ctx(self, stream_type):
- tmpl = barectf_templates._CTX_BEGIN
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name))
- self._cg.indent()
- pkt_header_ft = self._trace_type._pkt_header_ft
-
- if pkt_header_ft is not None:
- for member_name in pkt_header_ft.members:
- self._cg.add_lines(f'uint32_t off_tph_{member_name};')
-
- for member_name in stream_type._pkt_ctx_ft.members:
- self._cg.add_lines(f'uint32_t off_spc_{member_name};')
-
- if stream_type.default_clock_type is not None:
- self._cg.add_line(f'{self._clk_type_c_type(stream_type.default_clock_type)} cur_last_event_ts;')
-
- self._cg.unindent()
- tmpl = barectf_templates._CTX_END
- self._cg.add_lines(tmpl)
-
- def _generate_ctxs(self):
- for stream_type in self._trace_type.stream_types:
- self._generate_ctx(stream_type)
-
- def _generate_clock_cb(self, clk_type):
- tmpl = barectf_templates._CLOCK_CB
- self._cg.add_lines(tmpl.format(return_ctype=self._clk_type_c_type(clk_type),
- cname=clk_type.name))
-
- def _generate_clock_cbs(self):
- clk_names = set()
-
- for stream_type in self._trace_type.stream_types:
- def_clk_type = stream_type.default_clock_type
-
- if def_clk_type is not None and def_clk_type not in clk_names:
- self._generate_clock_cb(def_clk_type)
- clk_names.add(def_clk_type)
-
- def _generate_platform_callbacks(self):
- tmpl = barectf_templates._PLATFORM_CALLBACKS_BEGIN
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix))
- self._cg.indent()
- self._generate_clock_cbs()
- self._cg.unindent()
- tmpl = barectf_templates._PLATFORM_CALLBACKS_END
- self._cg.add_lines(tmpl)
-
def generate_bitfield_header(self):
return self._create_file_template('bitfield.h.j2').render()
self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name))
if self._trace_type._pkt_header_ft is not None:
- self._generate_proto_params(self._trace_type._pkt_header_ft, _PREFIX_TPH,
+ self._generate_proto_params(self._trace_type._pkt_header_ft, _RootFtPrefixes.TPH,
{'magic', 'stream_id', 'uuid'})
exclude_set = {
'content_size',
'events_discarded',
}
- self._generate_proto_params(stream_type._pkt_ctx_ft, _PREFIX_SPC, exclude_set)
+ 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)
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, _PREFIX_SEH, {'id', 'timestamp'})
+ self._generate_proto_params(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, _PREFIX_SEC)
+ self._generate_proto_params(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, _PREFIX_EC)
+ self._generate_proto_params(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, _PREFIX_EP)
+ 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
tmpl = barectf_templates._FUNC_TRACE_PROTO_END
self._cg.add_lines(tmpl)
- def _punctuate_proto(self):
- self._cg.append_to_last_line(';')
-
def generate_header(self):
- self._cg.reset()
- dt = datetime.datetime.now().isoformat()
- prefix_def = ''
- def_stream_type_name_def = ''
- cg_opts = self._cfg.options.code_generation_options
- header_opts = cg_opts.header_options
-
- if header_opts.identifier_prefix_definition:
- prefix_def = f'#define _BARECTF_PREFIX {self._iden_prefix}'
-
- def_stream_type = cg_opts.default_stream_type
-
- if header_opts.default_stream_type_name_definition and def_stream_type is not None:
- def_stream_type_name_def = f'#define _BARECTF_DEFAULT_STREAM {def_stream_type.name}'
-
- def_stream_type_trace_defs = ''
-
- if def_stream_type is not None:
- lines = []
-
- for ev_type in def_stream_type.event_types:
- tmpl = barectf_templates._DEFINE_DEFAULT_STREAM_TRACE
- define = tmpl.format(prefix=self._iden_prefix, sname=def_stream_type.name,
- evname=ev_type.name)
- lines.append(define)
-
- def_stream_type_trace_defs = '\n'.join(lines)
-
- tmpl = barectf_templates._HEADER_BEGIN
- self._cg.add_lines(tmpl.format(prefix=self._iden_prefix,
- ucprefix=self._iden_prefix.upper(),
- version=barectf_version.__version__, date=dt,
- prefix_def=prefix_def,
- default_stream_def=def_stream_type_name_def,
- default_stream_trace_defs=def_stream_type_trace_defs))
- self._cg.add_empty_line()
-
- # platform callbacks structure
- self._generate_platform_callbacks()
- self._cg.add_empty_line()
-
- # context parent
- self._generate_ctx_parent()
- self._cg.add_empty_line()
-
- # stream contexts
- self._generate_ctxs()
- self._cg.add_empty_line()
-
- # initialization function prototype
- self._generate_func_init_proto()
- self._punctuate_proto()
- self._cg.add_empty_line()
-
- for stream_type in self._trace_type.stream_types:
- self._generate_func_open_proto(stream_type)
- self._punctuate_proto()
- self._cg.add_empty_line()
- self._generate_func_close_proto(stream_type)
- self._punctuate_proto()
- self._cg.add_empty_line()
-
- for ev_type in stream_type.event_types:
- self._generate_func_trace_proto(stream_type, ev_type)
- self._punctuate_proto()
- self._cg.add_empty_line()
-
- tmpl = barectf_templates._HEADER_END
- self._cg.add_lines(tmpl.format(ucprefix=self._iden_prefix.upper()))
- return self._cg.code
+ return self._create_file_template('barectf.h.j2').render(root_ft_prefixes=_RootFtPrefixes)
def _get_call_event_param_list_from_struct_ft(self, ft, prefix, exclude_set=None):
if exclude_set is None:
if stream_type._ev_header_ft is not None:
lst += self._get_call_event_param_list_from_struct_ft(stream_type._ev_header_ft,
- _PREFIX_SEH, {'id', 'timestamp'})
+ _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,
- _PREFIX_SEC)
+ _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,
- _PREFIX_EC)
+ _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,
- _PREFIX_EP)
+ _RootFtPrefixes.EP)
return lst
self._cg.add_empty_line()
self._cg.indent()
ser_actions = _SerializationActions()
- ser_actions.append_root_scope_ft(stream_type._ev_header_ft, _PREFIX_SEH)
- ser_actions.append_root_scope_ft(stream_type.event_common_context_field_type, _PREFIX_SEC)
- ser_actions.append_root_scope_ft(ev_type.specific_context_field_type, _PREFIX_EC)
- ser_actions.append_root_scope_ft(ev_type.payload_field_type, _PREFIX_EP)
+ 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 {_PREFIX_TO_NAME[action.names[0]]} structure'
+ line = f'align {_ROOT_FT_PREFIX_TO_NAME[action.names[0]]} structure'
else:
- line = f'align field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})'
+ line = f'align field `{action.names[-1]}` ({_ROOT_FT_PREFIX_TO_NAME[action.names[0]]})'
self._cg.add_cc_line(line)
else:
assert type(action) is _SerializeSerializationAction
assert(len(action.names) >= 2)
- line = f'add size of field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})'
+ 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:
if type(action) is _AlignSerializationAction:
if action.names:
if len(action.names) == 1:
- line = f'align {_PREFIX_TO_NAME[action.names[0]]} structure'
+ line = f'align {_ROOT_FT_PREFIX_TO_NAME[action.names[0]]} structure'
else:
- line = f'align field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})'
+ line = f'align field `{action.names[-1]}` ({_ROOT_FT_PREFIX_TO_NAME[action.names[0]]})'
self._cg.add_cc_line(line)
assert type(action) is _SerializeSerializationAction
assert(len(action.names) >= 2)
member_name = action.names[-1]
- line = f'serialize field `{member_name}` ({_PREFIX_TO_NAME[action.names[0]]})'
+ 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 stream_type._ev_header_ft is not None:
params = self._get_call_event_param_list_from_struct_ft(stream_type._ev_header_ft,
- _PREFIX_SEH,
+ _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});'
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,
- _PREFIX_SEC)
+ _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)
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, _PREFIX_EC)
+ 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(_PREFIX_EC, ser_action_iter)
+ 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, _PREFIX_EP)
+ 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(_PREFIX_EP, ser_action_iter)
+ 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.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, _PREFIX_SEH,
+ 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.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, _PREFIX_SEC)
+ 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)
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(_PREFIX_SEH, ser_action_iter,
+ self._generate_serialize_statements_from_actions(_RootFtPrefixes.SEH, ser_action_iter,
spec_src)
self._cg.unindent()
self._cg.indent()
if stream_type.event_common_context_field_type is not None:
- self._generate_serialize_statements_from_actions(_PREFIX_SEC, ser_action_iter)
+ 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_cc_line('trace packet header')
self._cg.add_line('{')
self._cg.indent()
- ser_actions.append_root_scope_ft(pkt_header_ft, _PREFIX_TPH)
+ ser_actions.append_root_scope_ft(pkt_header_ft, _RootFtPrefixes.TPH)
for action in ser_actions.actions:
if type(action) is _AlignSerializationAction:
member_name = action.names[-1]
line = f'serialize field `{member_name}`'
self._cg.add_cc_line(line)
- src = _PREFIX_TPH + member_name
+ src = _RootFtPrefixes.TPH + member_name
if member_name == 'magic':
src = '0xc1fc1fc1UL'
self._cg.add_cc_line('stream packet context')
self._cg.add_line('{')
self._cg.indent()
- ser_actions.append_root_scope_ft(pkt_ctx_ft, _PREFIX_SPC)
+ 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:
member_name = action.names[-1]
line = f'serialize field `{member_name}`'
self._cg.add_cc_line(line)
- src = _PREFIX_SPC + member_name
+ src = _RootFtPrefixes.SPC + member_name
skip_int = False
if member_name == 'timestamp_begin':
ser_actions = _SerializationActions()
if stream_type._ev_header_ft is not None:
- ser_actions.append_root_scope_ft(stream_type._ev_header_ft, _PREFIX_SEH)
+ 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,
- _PREFIX_SEC)
+ _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()
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-_CLOCK_CB = '{return_ctype} (*{cname}_clock_get_value)(void *);'
-
-
-_PLATFORM_CALLBACKS_BEGIN = '''/* barectf platform callbacks */
-struct {prefix}platform_callbacks {{
- /* clock callbacks */'''
-
-
-_PLATFORM_CALLBACKS_END = '''
- /* is back-end full? */
- int (*is_backend_full)(void *);
-
- /* open packet */
- void (*open_packet)(void *);
-
- /* close packet */
- void (*close_packet)(void *);
-};'''
-
-
-_CTX_PARENT = '''/* 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 size in bits */
- uint32_t packet_size;
-
- /* content size in bits */
- uint32_t content_size;
-
- /* current position from beginning of packet in bits */
- uint32_t at;
-
- /* packet header + context size (content offset) */
- uint32_t off_content;
-
- /* events discarded */
- uint32_t events_discarded;
-
- /* current packet is opened */
- int packet_is_open;
-
- /* in tracing code */
- volatile int in_tracing_section;
-
- /* tracing is enabled */
- volatile int is_tracing_enabled;
-
- /* use current/last event timestamp when opening/closing packets */
- int use_cur_last_event_ts;
-}};'''
-
-
-_CTX_BEGIN = '''/* context for stream `{sname}` */
-struct {prefix}{sname}_ctx {{
- /* parent */
- struct {prefix}ctx parent;
-
- /* config-specific members follow */'''
-
-
-_CTX_END = '};'
-
-
_FUNC_INIT_PROTO = '''/* initialize context */
void {prefix}init(
void *vctx,
}'''
-_DEFINE_DEFAULT_STREAM_TRACE = '#define {prefix}trace_{evname} {prefix}{sname}_trace_{evname}'
-
-
_FUNC_TRACE_PROTO_BEGIN = '''/* trace (stream `{sname}`, event `{evname}`) */
void {prefix}{sname}_trace_{evname}(
struct {prefix}{sname}_ctx *ctx'''
_FUNC_SERIALIZE_EVENT_BODY_END = '}'
-_HEADER_BEGIN = '''#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 {version}
- * on {date}.
- *
- * For more details, see <http://barectf.org>.
- */
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {{
-#endif
-
-{prefix_def}
-{default_stream_def}
-
-{default_stream_trace_defs}
-
-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);'''
-
-
-_HEADER_END = '''#ifdef __cplusplus
-}}
-#endif
-
-#endif /* _{ucprefix}H */
-'''
-
-
_C_SRC = '''/*
* The MIT License (MIT)
*
--- /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 */