2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
10 #include <babeltrace2/babeltrace.h>
12 #include "common/assert.h"
13 #include "compat/endian.h" /* IWYU pragma: keep */
15 #include "fs-sink-ctf-meta.hpp"
16 #include "translate-ctf-ir-to-tsdl.hpp"
23 unsigned int indent_level
;
27 } /* namespace sink */
30 static inline void append_indent(ctf::sink::CtfIrToTsdlCtx
*ctx
)
34 for (i
= 0; i
< ctx
->indent_level
; i
++) {
35 g_string_append_c(ctx
->tsdl
, '\t');
39 static void append_uuid(ctf::sink::CtfIrToTsdlCtx
*ctx
, bt_uuid uuid
)
41 g_string_append_printf(ctx
->tsdl
, "\"" BT_UUID_FMT
"\"", BT_UUID_FMT_VALUES(uuid
));
44 static void append_quoted_string_content(ctf::sink::CtfIrToTsdlCtx
*ctx
, const char *str
)
48 for (ch
= str
; *ch
!= '\0'; ch
++) {
49 unsigned char uch
= (unsigned char) *ch
;
51 if (uch
< 32 || uch
>= 127) {
54 g_string_append(ctx
->tsdl
, "\\a");
57 g_string_append(ctx
->tsdl
, "\\b");
60 g_string_append(ctx
->tsdl
, "\\f");
63 g_string_append(ctx
->tsdl
, "\\n");
66 g_string_append(ctx
->tsdl
, "\\r");
69 g_string_append(ctx
->tsdl
, "\\t");
72 g_string_append(ctx
->tsdl
, "\\v");
75 g_string_append_printf(ctx
->tsdl
, "\\x%02x", (unsigned int) uch
);
78 } else if (*ch
== '"' || *ch
== '\\') {
79 g_string_append_c(ctx
->tsdl
, '\\');
80 g_string_append_c(ctx
->tsdl
, *ch
);
82 g_string_append_c(ctx
->tsdl
, *ch
);
87 static void append_quoted_string(ctf::sink::CtfIrToTsdlCtx
*ctx
, const char *str
)
89 g_string_append_c(ctx
->tsdl
, '"');
90 append_quoted_string_content(ctx
, str
);
91 g_string_append_c(ctx
->tsdl
, '"');
94 static void append_integer_field_class_from_props(
95 ctf::sink::CtfIrToTsdlCtx
*ctx
, unsigned int size
, unsigned int alignment
, bool is_signed
,
96 bt_field_class_integer_preferred_display_base disp_base
, const char *mapped_clock_class_name
,
97 const char *field_name
, bool end
)
99 g_string_append_printf(ctx
->tsdl
, "integer { size = %u; align = %u;", size
, alignment
);
102 g_string_append(ctx
->tsdl
, " signed = true;");
105 if (disp_base
!= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
) {
106 g_string_append(ctx
->tsdl
, " base = ");
109 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
110 g_string_append(ctx
->tsdl
, "b");
112 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
113 g_string_append(ctx
->tsdl
, "o");
115 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
116 g_string_append(ctx
->tsdl
, "x");
122 g_string_append_c(ctx
->tsdl
, ';');
125 if (mapped_clock_class_name
) {
126 g_string_append_printf(ctx
->tsdl
, " map = clock.%s.value;", mapped_clock_class_name
);
129 g_string_append(ctx
->tsdl
, " }");
132 g_string_append_printf(ctx
->tsdl
, " %s", field_name
);
136 g_string_append(ctx
->tsdl
, ";\n");
140 static void append_end_block(ctf::sink::CtfIrToTsdlCtx
*ctx
)
144 g_string_append(ctx
->tsdl
, "}");
147 static void append_end_block_semi_nl(ctf::sink::CtfIrToTsdlCtx
*ctx
)
151 g_string_append(ctx
->tsdl
, "};\n");
154 static void append_end_block_semi_nl_nl(ctf::sink::CtfIrToTsdlCtx
*ctx
)
156 append_end_block_semi_nl(ctx
);
157 g_string_append_c(ctx
->tsdl
, '\n');
160 static void append_bool_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
,
161 __attribute__((unused
)) struct fs_sink_ctf_field_class_bool
*fc
)
164 * CTF 1.8 has no boolean field class type, so this component
165 * translates it to an 8-bit unsigned integer field class.
167 append_integer_field_class_from_props(ctx
, fc
->base
.size
, fc
->base
.base
.alignment
, false,
168 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
172 static void append_bit_array_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
,
173 struct fs_sink_ctf_field_class_bit_array
*fc
)
176 * CTF 1.8 has no bit array field class type, so this component
177 * translates it to an unsigned integer field class with an
180 append_integer_field_class_from_props(ctx
, fc
->size
, fc
->base
.alignment
, false,
181 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
185 static void append_integer_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
,
186 struct fs_sink_ctf_field_class_int
*fc
)
188 const bt_field_class
*ir_fc
= fc
->base
.base
.ir_fc
;
189 bt_field_class_type type
= bt_field_class_get_type(ir_fc
);
190 bool is_signed
= bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
);
192 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
193 g_string_append(ctx
->tsdl
, "enum : ");
196 append_integer_field_class_from_props(ctx
, fc
->base
.size
, fc
->base
.base
.alignment
, is_signed
,
197 bt_field_class_integer_get_preferred_display_base(ir_fc
),
200 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
203 g_string_append(ctx
->tsdl
, " {\n");
206 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_fc
); i
++) {
208 const bt_field_class_enumeration_mapping
*mapping
;
209 const bt_field_class_enumeration_unsigned_mapping
*u_mapping
;
210 const bt_field_class_enumeration_signed_mapping
*s_mapping
;
211 const bt_integer_range_set
*ranges
;
212 const bt_integer_range_set_unsigned
*u_ranges
;
213 const bt_integer_range_set_signed
*s_ranges
;
214 uint64_t range_count
;
219 bt_field_class_enumeration_signed_borrow_mapping_by_index_const(ir_fc
, i
);
220 mapping
= bt_field_class_enumeration_signed_mapping_as_mapping_const(s_mapping
);
221 s_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(s_mapping
);
222 ranges
= bt_integer_range_set_signed_as_range_set_const(s_ranges
);
225 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(ir_fc
, i
);
226 mapping
= bt_field_class_enumeration_unsigned_mapping_as_mapping_const(u_mapping
);
228 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(u_mapping
);
229 ranges
= bt_integer_range_set_unsigned_as_range_set_const(u_ranges
);
232 label
= bt_field_class_enumeration_mapping_get_label(mapping
);
233 range_count
= bt_integer_range_set_get_range_count(ranges
);
235 for (range_i
= 0; range_i
< range_count
; range_i
++) {
237 g_string_append(ctx
->tsdl
, "\"");
238 append_quoted_string_content(ctx
, label
);
239 g_string_append(ctx
->tsdl
, "\" = ");
242 const bt_integer_range_signed
*range
;
243 int64_t lower
, upper
;
246 bt_integer_range_set_signed_borrow_range_by_index_const(s_ranges
, range_i
);
247 lower
= bt_integer_range_signed_get_lower(range
);
248 upper
= bt_integer_range_signed_get_upper(range
);
250 if (lower
== upper
) {
251 g_string_append_printf(ctx
->tsdl
, "%" PRId64
, lower
);
253 g_string_append_printf(ctx
->tsdl
, "%" PRId64
" ... %" PRId64
, lower
, upper
);
256 const bt_integer_range_unsigned
*range
;
257 uint64_t lower
, upper
;
259 range
= bt_integer_range_set_unsigned_borrow_range_by_index_const(u_ranges
,
261 lower
= bt_integer_range_unsigned_get_lower(range
);
262 upper
= bt_integer_range_unsigned_get_upper(range
);
264 if (lower
== upper
) {
265 g_string_append_printf(ctx
->tsdl
, "%" PRIu64
, lower
);
267 g_string_append_printf(ctx
->tsdl
, "%" PRIu64
" ... %" PRIu64
, lower
, upper
);
271 g_string_append(ctx
->tsdl
, ",\n");
275 append_end_block(ctx
);
279 static void append_float_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
,
280 struct fs_sink_ctf_field_class_float
*fc
)
282 unsigned int mant_dig
, exp_dig
;
284 if (bt_field_class_get_type(fc
->base
.base
.ir_fc
) == BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
) {
292 g_string_append_printf(ctx
->tsdl
, "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
293 mant_dig
, exp_dig
, fc
->base
.base
.alignment
);
296 static void append_string_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
)
298 g_string_append(ctx
->tsdl
, "string { encoding = UTF8; }");
301 static void append_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
, struct fs_sink_ctf_field_class
*fc
);
303 static void append_member(ctf::sink::CtfIrToTsdlCtx
*ctx
, const char *name
,
304 struct fs_sink_ctf_field_class
*fc
)
306 GString
*lengths
= NULL
;
307 const char *lengths_str
= "";
311 while (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
||
312 fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
314 lengths
= g_string_new(NULL
);
318 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
) {
319 struct fs_sink_ctf_field_class_array
*array_fc
= fs_sink_ctf_field_class_as_array(fc
);
321 g_string_append_printf(lengths
, "[%" PRIu64
"]", array_fc
->length
);
322 fc
= array_fc
->base
.elem_fc
;
324 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
325 fs_sink_ctf_field_class_as_sequence(fc
);
327 g_string_append_printf(lengths
, "[%s]", seq_fc
->length_ref
->str
);
328 fc
= seq_fc
->base
.elem_fc
;
332 append_field_class(ctx
, fc
);
335 lengths_str
= lengths
->str
;
338 g_string_append_printf(ctx
->tsdl
, " %s%s;\n", name
, lengths_str
);
341 g_string_free(lengths
, TRUE
);
345 static void append_struct_field_class_members(ctf::sink::CtfIrToTsdlCtx
*ctx
,
346 struct fs_sink_ctf_field_class_struct
*struct_fc
)
350 for (i
= 0; i
< struct_fc
->members
->len
; i
++) {
351 struct fs_sink_ctf_named_field_class
*named_fc
=
352 fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
353 struct fs_sink_ctf_field_class
*fc
= named_fc
->fc
;
356 * For sequence, option, and variant field classes, if
357 * the length/tag field class is generated before, write
358 * it now before the dependent field class.
360 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
361 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
362 fs_sink_ctf_field_class_as_sequence(fc
);
364 if (seq_fc
->length_is_before
) {
366 append_integer_field_class_from_props(
367 ctx
, 32, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
,
368 seq_fc
->length_ref
->str
, true);
370 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
) {
371 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
374 * CTF 1.8 does not support the option field
375 * class type. To write something anyway, this
376 * component translates this type to a variant
377 * field class where the options are:
379 * * An empty structure field class.
380 * * The optional field class itself.
382 * The "tag" is always generated/before in that
383 * case (an 8-bit unsigned enumeration field
387 g_string_append(ctx
->tsdl
, "/* The enumeration and variant field classes "
388 "below were a trace IR option field class. */\n");
390 g_string_append(ctx
->tsdl
, "enum : ");
391 append_integer_field_class_from_props(
392 ctx
, 8, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
, NULL
,
394 g_string_append(ctx
->tsdl
, " {\n");
397 g_string_append(ctx
->tsdl
, "none = 0,\n");
399 g_string_append(ctx
->tsdl
, "content = 1,\n");
400 append_end_block(ctx
);
401 g_string_append_printf(ctx
->tsdl
, " %s;\n", opt_fc
->tag_ref
->str
);
402 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
) {
403 struct fs_sink_ctf_field_class_variant
*var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
405 if (var_fc
->tag_is_before
) {
407 g_string_append(ctx
->tsdl
, "enum : ");
408 append_integer_field_class_from_props(
409 ctx
, 16, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
,
411 g_string_append(ctx
->tsdl
, " {\n");
414 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
415 struct fs_sink_ctf_named_field_class
*option_named_fc
=
416 fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
419 g_string_append_printf(ctx
->tsdl
, "\"%s\" = %" PRIu64
",\n",
420 option_named_fc
->name
->str
, i
);
423 append_end_block(ctx
);
424 g_string_append_printf(ctx
->tsdl
, " %s;\n", var_fc
->tag_ref
->str
);
426 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
) {
430 "/* The integer field class below was a trace IR boolean field class. */\n");
431 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
) {
435 "/* The integer field class below was a trace IR bit array field class. */\n");
439 append_member(ctx
, named_fc
->name
->str
, fc
);
443 static void append_struct_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
,
444 struct fs_sink_ctf_field_class_struct
*fc
)
446 g_string_append(ctx
->tsdl
, "struct {\n");
448 append_struct_field_class_members(ctx
, fc
);
449 append_end_block(ctx
);
450 g_string_append_printf(ctx
->tsdl
, " align(%u)", fc
->base
.alignment
);
453 static void append_option_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
,
454 struct fs_sink_ctf_field_class_option
*opt_fc
)
456 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n", opt_fc
->tag_ref
->str
);
459 g_string_append(ctx
->tsdl
, "struct { } none;\n");
461 append_member(ctx
, "content", opt_fc
->content_fc
);
462 append_end_block(ctx
);
465 static void append_variant_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
,
466 struct fs_sink_ctf_field_class_variant
*var_fc
)
470 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n", var_fc
->tag_ref
->str
);
473 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
474 struct fs_sink_ctf_named_field_class
*named_fc
=
475 fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
478 append_member(ctx
, named_fc
->name
->str
, named_fc
->fc
);
481 append_end_block(ctx
);
484 static void append_field_class(ctf::sink::CtfIrToTsdlCtx
*ctx
, struct fs_sink_ctf_field_class
*fc
)
487 case FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
:
488 append_bool_field_class(ctx
, fs_sink_ctf_field_class_as_bool(fc
));
490 case FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
:
491 append_bit_array_field_class(ctx
, fs_sink_ctf_field_class_as_bit_array(fc
));
493 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT
:
494 append_integer_field_class(ctx
, fs_sink_ctf_field_class_as_int(fc
));
496 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT
:
497 append_float_field_class(ctx
, fs_sink_ctf_field_class_as_float(fc
));
499 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING
:
500 append_string_field_class(ctx
);
502 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
503 append_struct_field_class(ctx
, fs_sink_ctf_field_class_as_struct(fc
));
505 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
506 append_option_field_class(ctx
, fs_sink_ctf_field_class_as_option(fc
));
508 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
509 append_variant_field_class(ctx
, fs_sink_ctf_field_class_as_variant(fc
));
516 static void append_event_class(ctf::sink::CtfIrToTsdlCtx
*ctx
, struct fs_sink_ctf_event_class
*ec
)
519 bt_event_class_log_level log_level
;
523 g_string_append(ctx
->tsdl
, "event {\n");
526 /* Event class properties */
528 g_string_append(ctx
->tsdl
, "name = ");
529 str
= bt_event_class_get_name(ec
->ir_ec
);
534 append_quoted_string(ctx
, str
);
535 g_string_append(ctx
->tsdl
, ";\n");
537 g_string_append_printf(ctx
->tsdl
, "stream_id = %" PRIu64
";\n",
538 bt_stream_class_get_id(ec
->sc
->ir_sc
));
540 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n", bt_event_class_get_id(ec
->ir_ec
));
542 str
= bt_event_class_get_emf_uri(ec
->ir_ec
);
545 g_string_append(ctx
->tsdl
, "model.emf.uri = ");
546 append_quoted_string(ctx
, str
);
547 g_string_append(ctx
->tsdl
, ";\n");
550 if (bt_event_class_get_log_level(ec
->ir_ec
, &log_level
) == BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
554 g_string_append(ctx
->tsdl
, "loglevel = ");
557 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
560 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
563 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
566 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
569 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
572 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
575 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
578 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
581 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
584 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
587 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
590 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
593 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
596 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
599 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
606 g_string_append_printf(ctx
->tsdl
, "%u;\n", level
);
609 /* Event specific context field class */
610 if (ec
->spec_context_fc
) {
612 g_string_append(ctx
->tsdl
, "context := ");
613 append_field_class(ctx
, ec
->spec_context_fc
);
614 g_string_append(ctx
->tsdl
, ";\n");
617 /* Event payload field class */
618 if (ec
->payload_fc
) {
620 g_string_append(ctx
->tsdl
, "fields := ");
621 append_field_class(ctx
, ec
->payload_fc
);
622 g_string_append(ctx
->tsdl
, ";\n");
625 append_end_block_semi_nl_nl(ctx
);
628 static void append_stream_class(ctf::sink::CtfIrToTsdlCtx
*ctx
, struct fs_sink_ctf_stream_class
*sc
)
632 /* Default clock class */
633 if (sc
->default_clock_class
) {
635 int64_t offset_seconds
;
636 uint64_t offset_cycles
;
640 g_string_append(ctx
->tsdl
, "clock {\n");
642 BT_ASSERT(sc
->default_clock_class_name
->len
> 0);
644 g_string_append_printf(ctx
->tsdl
, "name = %s;\n", sc
->default_clock_class_name
->str
);
645 descr
= bt_clock_class_get_description(sc
->default_clock_class
);
648 g_string_append(ctx
->tsdl
, "description = ");
649 append_quoted_string(ctx
, descr
);
650 g_string_append(ctx
->tsdl
, ";\n");
654 g_string_append_printf(ctx
->tsdl
, "freq = %" PRIu64
";\n",
655 bt_clock_class_get_frequency(sc
->default_clock_class
));
657 g_string_append_printf(ctx
->tsdl
, "precision = %" PRIu64
";\n",
658 bt_clock_class_get_precision(sc
->default_clock_class
));
659 bt_clock_class_get_offset(sc
->default_clock_class
, &offset_seconds
, &offset_cycles
);
661 g_string_append_printf(ctx
->tsdl
, "offset_s = %" PRId64
";\n", offset_seconds
);
663 g_string_append_printf(ctx
->tsdl
, "offset = %" PRIu64
";\n", offset_cycles
);
665 g_string_append(ctx
->tsdl
, "absolute = ");
667 if (bt_clock_class_origin_is_unix_epoch(sc
->default_clock_class
)) {
668 g_string_append(ctx
->tsdl
, "true");
670 g_string_append(ctx
->tsdl
, "false");
673 g_string_append(ctx
->tsdl
, ";\n");
674 uuid
= bt_clock_class_get_uuid(sc
->default_clock_class
);
677 g_string_append(ctx
->tsdl
, "uuid = ");
678 append_uuid(ctx
, uuid
);
679 g_string_append(ctx
->tsdl
, ";\n");
682 /* End clock class */
683 append_end_block_semi_nl_nl(ctx
);
688 g_string_append(ctx
->tsdl
, "stream {\n");
691 /* Stream class properties */
693 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n", bt_stream_class_get_id(sc
->ir_sc
));
695 /* Packet context field class */
697 g_string_append(ctx
->tsdl
, "packet.context := struct {\n");
700 append_integer_field_class_from_props(ctx
, 64, 8, false,
701 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
702 NULL
, "packet_size", true);
704 append_integer_field_class_from_props(ctx
, 64, 8, false,
705 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
706 NULL
, "content_size", true);
708 if (sc
->packets_have_ts_begin
) {
710 append_integer_field_class_from_props(
711 ctx
, 64, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
712 sc
->default_clock_class_name
->str
, "timestamp_begin", true);
715 if (sc
->packets_have_ts_end
) {
717 append_integer_field_class_from_props(
718 ctx
, 64, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
719 sc
->default_clock_class_name
->str
, "timestamp_end", true);
722 if (sc
->has_discarded_events
) {
724 append_integer_field_class_from_props(ctx
, 64, 8, false,
725 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
726 NULL
, "events_discarded", true);
730 * Unconditionally write the packet sequence number as, even if
731 * there's no possible discarded packets message, it's still
732 * useful information to have.
735 append_integer_field_class_from_props(ctx
, 64, 8, false,
736 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
737 NULL
, "packet_seq_num", true);
739 if (sc
->packet_context_fc
) {
740 append_struct_field_class_members(ctx
,
741 fs_sink_ctf_field_class_as_struct(sc
->packet_context_fc
));
742 fs_sink_ctf_field_class_struct_align_at_least(
743 fs_sink_ctf_field_class_as_struct(sc
->packet_context_fc
), 8);
746 /* End packet context field class */
747 append_end_block(ctx
);
748 g_string_append_printf(ctx
->tsdl
, " align(%u);\n\n",
749 sc
->packet_context_fc
? sc
->packet_context_fc
->alignment
: 8);
751 /* Event header field class */
753 g_string_append(ctx
->tsdl
, "event.header := struct {\n");
756 append_integer_field_class_from_props(
757 ctx
, 64, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
, "id", true);
759 if (sc
->default_clock_class
) {
761 append_integer_field_class_from_props(ctx
, 64, 8, false,
762 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
763 sc
->default_clock_class_name
->str
, "timestamp", true);
766 /* End event header field class */
767 append_end_block(ctx
);
768 g_string_append(ctx
->tsdl
, " align(8);\n");
770 /* Event common context field class */
771 if (sc
->event_common_context_fc
) {
773 g_string_append(ctx
->tsdl
, "event.context := ");
774 append_field_class(ctx
, sc
->event_common_context_fc
);
775 g_string_append(ctx
->tsdl
, ";\n");
778 /* End stream class */
779 append_end_block_semi_nl_nl(ctx
);
782 for (i
= 0; i
< sc
->event_classes
->len
; i
++) {
783 append_event_class(ctx
, (fs_sink_ctf_event_class
*) sc
->event_classes
->pdata
[i
]);
787 void translate_trace_ctf_ir_to_tsdl(struct fs_sink_ctf_trace
*trace
, GString
*tsdl
)
789 ctf::sink::CtfIrToTsdlCtx ctx
= {
796 g_string_assign(tsdl
, "/* CTF 1.8 */\n\n");
797 g_string_append(tsdl
, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
801 g_string_append(tsdl
, "trace {\n");
804 /* Trace class properties */
806 g_string_append(tsdl
, "major = 1;\n");
808 g_string_append(tsdl
, "minor = 8;\n");
810 g_string_append(tsdl
, "uuid = ");
811 append_uuid(&ctx
, trace
->uuid
);
812 g_string_append(tsdl
, ";\n");
814 g_string_append(tsdl
, "byte_order = ");
816 if (BYTE_ORDER
== LITTLE_ENDIAN
) {
817 g_string_append(tsdl
, "le");
819 g_string_append(tsdl
, "be");
822 g_string_append(tsdl
, ";\n");
824 /* Packet header field class */
826 g_string_append(tsdl
, "packet.header := struct {\n");
829 append_integer_field_class_from_props(&ctx
, 32, 8, false,
830 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
831 NULL
, "magic", true);
833 append_integer_field_class_from_props(&ctx
, 8, 8, false,
834 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
835 NULL
, "uuid[16]", true);
837 append_integer_field_class_from_props(&ctx
, 64, 8, false,
838 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
839 NULL
, "stream_id", true);
841 append_integer_field_class_from_props(&ctx
, 64, 8, false,
842 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
843 NULL
, "stream_instance_id", true);
845 /* End packet header field class */
846 append_end_block(&ctx
);
847 g_string_append(ctx
.tsdl
, " align(8);\n");
849 /* End trace class */
850 append_end_block_semi_nl_nl(&ctx
);
852 /* Trace environment */
853 count
= bt_trace_get_environment_entry_count(trace
->ir_trace
);
856 g_string_append(tsdl
, "env {\n");
859 for (i
= 0; i
< count
; i
++) {
863 bt_trace_borrow_environment_entry_by_index_const(trace
->ir_trace
, i
, &name
, &val
);
865 g_string_append_printf(tsdl
, "%s = ", name
);
867 switch (bt_value_get_type(val
)) {
868 case BT_VALUE_TYPE_SIGNED_INTEGER
:
869 g_string_append_printf(tsdl
, "%" PRId64
, bt_value_integer_signed_get(val
));
871 case BT_VALUE_TYPE_STRING
:
872 append_quoted_string(&ctx
, bt_value_string_get(val
));
877 * translate_trace_trace_ir_to_ctf_ir().
882 g_string_append(tsdl
, ";\n");
885 /* End trace class environment */
886 append_end_block_semi_nl_nl(&ctx
);
889 /* Stream classes and their event classes */
890 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
891 append_stream_class(&ctx
, (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
]);