2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
7 #include "translate-ctf-ir-to-tsdl.hpp"
9 #include <babeltrace2/babeltrace.h>
10 #include "common/macros.h"
15 #include "common/assert.h"
16 #include "compat/endian.h"
18 #include "fs-sink-ctf-meta.hpp"
21 unsigned int indent_level
;
26 void append_indent(struct ctx
*ctx
)
30 for (i
= 0; i
< ctx
->indent_level
; i
++) {
31 g_string_append_c(ctx
->tsdl
, '\t');
36 void append_uuid(struct ctx
*ctx
, bt_uuid uuid
)
38 g_string_append_printf(ctx
->tsdl
,
39 "\"" BT_UUID_FMT
"\"",
40 BT_UUID_FMT_VALUES(uuid
));
44 void append_quoted_string_content(struct ctx
*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",
79 } else if (*ch
== '"' || *ch
== '\\') {
80 g_string_append_c(ctx
->tsdl
, '\\');
81 g_string_append_c(ctx
->tsdl
, *ch
);
83 g_string_append_c(ctx
->tsdl
, *ch
);
89 void append_quoted_string(struct ctx
*ctx
, const char *str
)
91 g_string_append_c(ctx
->tsdl
, '"');
92 append_quoted_string_content(ctx
, str
);
93 g_string_append_c(ctx
->tsdl
, '"');
97 void append_integer_field_class_from_props(struct ctx
*ctx
, unsigned int size
,
98 unsigned int alignment
, bool is_signed
,
99 bt_field_class_integer_preferred_display_base disp_base
,
100 const char *mapped_clock_class_name
, const char *field_name
,
103 g_string_append_printf(ctx
->tsdl
,
104 "integer { size = %u; align = %u;",
108 g_string_append(ctx
->tsdl
, " signed = true;");
111 if (disp_base
!= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
) {
112 g_string_append(ctx
->tsdl
, " base = ");
115 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
116 g_string_append(ctx
->tsdl
, "b");
118 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
119 g_string_append(ctx
->tsdl
, "o");
121 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
122 g_string_append(ctx
->tsdl
, "x");
128 g_string_append_c(ctx
->tsdl
, ';');
131 if (mapped_clock_class_name
) {
132 g_string_append_printf(ctx
->tsdl
, " map = clock.%s.value;",
133 mapped_clock_class_name
);
136 g_string_append(ctx
->tsdl
, " }");
139 g_string_append_printf(ctx
->tsdl
, " %s", field_name
);
143 g_string_append(ctx
->tsdl
, ";\n");
148 void append_end_block(struct ctx
*ctx
)
152 g_string_append(ctx
->tsdl
, "}");
156 void append_end_block_semi_nl(struct ctx
*ctx
)
160 g_string_append(ctx
->tsdl
, "};\n");
164 void append_end_block_semi_nl_nl(struct ctx
*ctx
)
166 append_end_block_semi_nl(ctx
);
167 g_string_append_c(ctx
->tsdl
, '\n');
171 void append_bool_field_class(struct ctx
*ctx
,
172 __attribute__((unused
)) struct fs_sink_ctf_field_class_bool
*fc
)
175 * CTF 1.8 has no boolean field class type, so this component
176 * translates it to an 8-bit unsigned integer field class.
178 append_integer_field_class_from_props(ctx
, fc
->base
.size
,
179 fc
->base
.base
.alignment
, false,
180 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
185 void append_bit_array_field_class(struct ctx
*ctx
,
186 struct fs_sink_ctf_field_class_bit_array
*fc
)
189 * CTF 1.8 has no bit array field class type, so this component
190 * translates it to an unsigned integer field class with an
193 append_integer_field_class_from_props(ctx
, fc
->size
,
194 fc
->base
.alignment
, false,
195 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
200 void append_integer_field_class(struct ctx
*ctx
,
201 struct fs_sink_ctf_field_class_int
*fc
)
203 const bt_field_class
*ir_fc
= fc
->base
.base
.ir_fc
;
204 bt_field_class_type type
= bt_field_class_get_type(ir_fc
);
205 bool is_signed
= bt_field_class_type_is(type
,
206 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
);
208 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
209 g_string_append(ctx
->tsdl
, "enum : ");
212 append_integer_field_class_from_props(ctx
, fc
->base
.size
,
213 fc
->base
.base
.alignment
, is_signed
,
214 bt_field_class_integer_get_preferred_display_base(ir_fc
),
217 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
220 g_string_append(ctx
->tsdl
, " {\n");
223 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_fc
); i
++) {
225 const bt_field_class_enumeration_mapping
*mapping
;
226 const bt_field_class_enumeration_unsigned_mapping
*u_mapping
;
227 const bt_field_class_enumeration_signed_mapping
*s_mapping
;
228 const bt_integer_range_set
*ranges
;
229 const bt_integer_range_set_unsigned
*u_ranges
;
230 const bt_integer_range_set_signed
*s_ranges
;
231 uint64_t range_count
;
235 s_mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
237 mapping
= bt_field_class_enumeration_signed_mapping_as_mapping_const(
239 s_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
241 ranges
= bt_integer_range_set_signed_as_range_set_const(
244 u_mapping
= bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
246 mapping
= bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
248 u_ranges
= bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
250 ranges
= bt_integer_range_set_unsigned_as_range_set_const(
254 label
= bt_field_class_enumeration_mapping_get_label(
256 range_count
= bt_integer_range_set_get_range_count(
259 for (range_i
= 0; range_i
< range_count
; range_i
++) {
261 g_string_append(ctx
->tsdl
, "\"");
262 append_quoted_string_content(ctx
, label
);
263 g_string_append(ctx
->tsdl
, "\" = ");
266 const bt_integer_range_signed
*range
;
267 int64_t lower
, upper
;
269 range
= bt_integer_range_set_signed_borrow_range_by_index_const(
271 lower
= bt_integer_range_signed_get_lower(
273 upper
= bt_integer_range_signed_get_upper(
276 if (lower
== upper
) {
277 g_string_append_printf(
278 ctx
->tsdl
, "%" PRId64
,
281 g_string_append_printf(
282 ctx
->tsdl
, "%" PRId64
" ... %" PRId64
,
286 const bt_integer_range_unsigned
*range
;
287 uint64_t lower
, upper
;
289 range
= bt_integer_range_set_unsigned_borrow_range_by_index_const(
291 lower
= bt_integer_range_unsigned_get_lower(
293 upper
= bt_integer_range_unsigned_get_upper(
296 if (lower
== upper
) {
297 g_string_append_printf(
298 ctx
->tsdl
, "%" PRIu64
,
301 g_string_append_printf(
302 ctx
->tsdl
, "%" PRIu64
" ... %" PRIu64
,
307 g_string_append(ctx
->tsdl
, ",\n");
311 append_end_block(ctx
);
316 void append_float_field_class(struct ctx
*ctx
,
317 struct fs_sink_ctf_field_class_float
*fc
)
319 unsigned int mant_dig
, exp_dig
;
321 if (bt_field_class_get_type(fc
->base
.base
.ir_fc
) ==
322 BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
) {
330 g_string_append_printf(ctx
->tsdl
,
331 "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
332 mant_dig
, exp_dig
, fc
->base
.base
.alignment
);
336 void append_string_field_class(struct ctx
*ctx
,
337 struct fs_sink_ctf_field_class_string
*fc
)
339 g_string_append(ctx
->tsdl
, "string { encoding = UTF8; }");
343 void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
);
346 void append_member(struct ctx
*ctx
, const char *name
,
347 struct fs_sink_ctf_field_class
*fc
)
349 GString
*lengths
= NULL
;
350 const char *lengths_str
= "";
354 while (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
||
355 fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
357 lengths
= g_string_new(NULL
);
361 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
) {
362 struct fs_sink_ctf_field_class_array
*array_fc
=
363 fs_sink_ctf_field_class_as_array(fc
);
365 g_string_append_printf(lengths
, "[%" PRIu64
"]",
367 fc
= array_fc
->base
.elem_fc
;
369 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
370 fs_sink_ctf_field_class_as_sequence(fc
);
372 g_string_append_printf(lengths
, "[%s]",
373 seq_fc
->length_ref
->str
);
374 fc
= seq_fc
->base
.elem_fc
;
378 append_field_class(ctx
, fc
);
381 lengths_str
= lengths
->str
;
384 g_string_append_printf(ctx
->tsdl
, " %s%s;\n", name
, lengths_str
);
387 g_string_free(lengths
, TRUE
);
392 void append_struct_field_class_members(struct ctx
*ctx
,
393 struct fs_sink_ctf_field_class_struct
*struct_fc
)
397 for (i
= 0; i
< struct_fc
->members
->len
; i
++) {
398 struct fs_sink_ctf_named_field_class
*named_fc
=
399 fs_sink_ctf_field_class_struct_borrow_member_by_index(
401 struct fs_sink_ctf_field_class
*fc
= named_fc
->fc
;
404 * For sequence, option, and variant field classes, if
405 * the length/tag field class is generated before, write
406 * it now before the dependent field class.
408 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
409 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
410 fs_sink_ctf_field_class_as_sequence(fc
);
412 if (seq_fc
->length_is_before
) {
414 append_integer_field_class_from_props(ctx
,
416 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
417 NULL
, seq_fc
->length_ref
->str
, true);
419 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
) {
420 struct fs_sink_ctf_field_class_option
*opt_fc
=
421 fs_sink_ctf_field_class_as_option(fc
);
424 * CTF 1.8 does not support the option field
425 * class type. To write something anyway, this
426 * component translates this type to a variant
427 * field class where the options are:
429 * * An empty structure field class.
430 * * The optional field class itself.
432 * The "tag" is always generated/before in that
433 * case (an 8-bit unsigned enumeration field
437 g_string_append(ctx
->tsdl
,
438 "/* The enumeration and variant field classes "
439 "below were a trace IR option field class. */\n");
441 g_string_append(ctx
->tsdl
, "enum : ");
442 append_integer_field_class_from_props(ctx
,
444 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
446 g_string_append(ctx
->tsdl
, " {\n");
449 g_string_append(ctx
->tsdl
, "none = 0,\n");
451 g_string_append(ctx
->tsdl
, "content = 1,\n");
452 append_end_block(ctx
);
453 g_string_append_printf(ctx
->tsdl
, " %s;\n",
454 opt_fc
->tag_ref
->str
);
455 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
) {
456 struct fs_sink_ctf_field_class_variant
*var_fc
=
457 fs_sink_ctf_field_class_as_variant(fc
);
459 if (var_fc
->tag_is_before
) {
461 g_string_append(ctx
->tsdl
, "enum : ");
462 append_integer_field_class_from_props(ctx
,
464 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
466 g_string_append(ctx
->tsdl
, " {\n");
469 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
470 struct fs_sink_ctf_named_field_class
*option_named_fc
=
471 fs_sink_ctf_field_class_variant_borrow_option_by_index(
475 g_string_append_printf(ctx
->tsdl
,
476 "\"%s\" = %" PRIu64
",\n",
477 option_named_fc
->name
->str
, i
);
480 append_end_block(ctx
);
481 g_string_append_printf(ctx
->tsdl
, " %s;\n",
482 var_fc
->tag_ref
->str
);
484 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
) {
486 g_string_append(ctx
->tsdl
,
487 "/* The integer field class below was a trace IR boolean field class. */\n");
488 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
) {
490 g_string_append(ctx
->tsdl
,
491 "/* The integer field class below was a trace IR bit array field class. */\n");
495 append_member(ctx
, named_fc
->name
->str
, fc
);
500 void append_struct_field_class(struct ctx
*ctx
,
501 struct fs_sink_ctf_field_class_struct
*fc
)
503 g_string_append(ctx
->tsdl
, "struct {\n");
505 append_struct_field_class_members(ctx
, fc
);
506 append_end_block(ctx
);
507 g_string_append_printf(ctx
->tsdl
, " align(%u)",
512 void append_option_field_class(struct ctx
*ctx
,
513 struct fs_sink_ctf_field_class_option
*opt_fc
)
515 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n",
516 opt_fc
->tag_ref
->str
);
519 g_string_append(ctx
->tsdl
, "struct { } none;\n");
521 append_member(ctx
, "content", opt_fc
->content_fc
);
522 append_end_block(ctx
);
526 void append_variant_field_class(struct ctx
*ctx
,
527 struct fs_sink_ctf_field_class_variant
*var_fc
)
531 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n",
532 var_fc
->tag_ref
->str
);
535 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
536 struct fs_sink_ctf_named_field_class
*named_fc
=
537 fs_sink_ctf_field_class_variant_borrow_option_by_index(
541 append_member(ctx
, named_fc
->name
->str
, named_fc
->fc
);
544 append_end_block(ctx
);
548 void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
)
551 case FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
:
552 append_bool_field_class(ctx
, fs_sink_ctf_field_class_as_bool(fc
));
554 case FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
:
555 append_bit_array_field_class(ctx
, fs_sink_ctf_field_class_as_bit_array(fc
));
557 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT
:
558 append_integer_field_class(ctx
, fs_sink_ctf_field_class_as_int(fc
));
560 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT
:
561 append_float_field_class(ctx
, fs_sink_ctf_field_class_as_float(fc
));
563 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING
:
564 append_string_field_class(ctx
, fs_sink_ctf_field_class_as_string(fc
));
566 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
567 append_struct_field_class(ctx
, fs_sink_ctf_field_class_as_struct(fc
));
569 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
570 append_option_field_class(ctx
, fs_sink_ctf_field_class_as_option(fc
));
572 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
573 append_variant_field_class(ctx
, fs_sink_ctf_field_class_as_variant(fc
));
581 void append_event_class(struct ctx
*ctx
, struct fs_sink_ctf_event_class
*ec
)
584 bt_event_class_log_level log_level
;
588 g_string_append(ctx
->tsdl
, "event {\n");
591 /* Event class properties */
593 g_string_append(ctx
->tsdl
, "name = ");
594 str
= bt_event_class_get_name(ec
->ir_ec
);
599 append_quoted_string(ctx
, str
);
600 g_string_append(ctx
->tsdl
, ";\n");
602 g_string_append_printf(ctx
->tsdl
, "stream_id = %" PRIu64
";\n",
603 bt_stream_class_get_id(ec
->sc
->ir_sc
));
605 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n",
606 bt_event_class_get_id(ec
->ir_ec
));
608 str
= bt_event_class_get_emf_uri(ec
->ir_ec
);
611 g_string_append(ctx
->tsdl
, "model.emf.uri = ");
612 append_quoted_string(ctx
, str
);
613 g_string_append(ctx
->tsdl
, ";\n");
616 if (bt_event_class_get_log_level(ec
->ir_ec
, &log_level
) ==
617 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
621 g_string_append(ctx
->tsdl
, "loglevel = ");
624 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
627 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
630 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
633 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
636 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
639 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
642 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
645 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
648 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
651 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
654 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
657 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
660 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
663 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
666 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
673 g_string_append_printf(ctx
->tsdl
, "%u;\n", level
);
676 /* Event specific context field class */
677 if (ec
->spec_context_fc
) {
679 g_string_append(ctx
->tsdl
, "context := ");
680 append_field_class(ctx
, ec
->spec_context_fc
);
681 g_string_append(ctx
->tsdl
, ";\n");
684 /* Event payload field class */
685 if (ec
->payload_fc
) {
687 g_string_append(ctx
->tsdl
, "fields := ");
688 append_field_class(ctx
, ec
->payload_fc
);
689 g_string_append(ctx
->tsdl
, ";\n");
692 append_end_block_semi_nl_nl(ctx
);
696 void append_stream_class(struct ctx
*ctx
,
697 struct fs_sink_ctf_stream_class
*sc
)
701 /* Default clock class */
702 if (sc
->default_clock_class
) {
704 int64_t offset_seconds
;
705 uint64_t offset_cycles
;
709 g_string_append(ctx
->tsdl
, "clock {\n");
711 BT_ASSERT(sc
->default_clock_class_name
->len
> 0);
713 g_string_append_printf(ctx
->tsdl
, "name = %s;\n",
714 sc
->default_clock_class_name
->str
);
715 descr
= bt_clock_class_get_description(sc
->default_clock_class
);
718 g_string_append(ctx
->tsdl
, "description = ");
719 append_quoted_string(ctx
, descr
);
720 g_string_append(ctx
->tsdl
, ";\n");
724 g_string_append_printf(ctx
->tsdl
, "freq = %" PRIu64
";\n",
725 bt_clock_class_get_frequency(sc
->default_clock_class
));
727 g_string_append_printf(ctx
->tsdl
, "precision = %" PRIu64
";\n",
728 bt_clock_class_get_precision(sc
->default_clock_class
));
729 bt_clock_class_get_offset(sc
->default_clock_class
,
730 &offset_seconds
, &offset_cycles
);
732 g_string_append_printf(ctx
->tsdl
, "offset_s = %" PRId64
";\n",
735 g_string_append_printf(ctx
->tsdl
, "offset = %" PRIu64
";\n",
738 g_string_append(ctx
->tsdl
, "absolute = ");
740 if (bt_clock_class_origin_is_unix_epoch(
741 sc
->default_clock_class
)) {
742 g_string_append(ctx
->tsdl
, "true");
744 g_string_append(ctx
->tsdl
, "false");
747 g_string_append(ctx
->tsdl
, ";\n");
748 uuid
= bt_clock_class_get_uuid(sc
->default_clock_class
);
751 g_string_append(ctx
->tsdl
, "uuid = ");
752 append_uuid(ctx
, uuid
);
753 g_string_append(ctx
->tsdl
, ";\n");
756 /* End clock class */
757 append_end_block_semi_nl_nl(ctx
);
762 g_string_append(ctx
->tsdl
, "stream {\n");
765 /* Stream class properties */
767 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n",
768 bt_stream_class_get_id(sc
->ir_sc
));
770 /* Packet context field class */
772 g_string_append(ctx
->tsdl
, "packet.context := struct {\n");
775 append_integer_field_class_from_props(ctx
, 64, 8, false,
776 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
777 NULL
, "packet_size", true);
779 append_integer_field_class_from_props(ctx
, 64, 8, false,
780 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
781 NULL
, "content_size", true);
783 if (sc
->packets_have_ts_begin
) {
785 append_integer_field_class_from_props(ctx
, 64, 8, false,
786 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
787 sc
->default_clock_class_name
->str
,
788 "timestamp_begin", true);
791 if (sc
->packets_have_ts_end
) {
793 append_integer_field_class_from_props(ctx
, 64, 8, false,
794 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
795 sc
->default_clock_class_name
->str
,
796 "timestamp_end", true);
799 if (sc
->has_discarded_events
) {
801 append_integer_field_class_from_props(ctx
, 64, 8, false,
802 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
803 NULL
, "events_discarded", true);
807 * Unconditionnally write the packet sequence number as, even if
808 * there's no possible discarded packets message, it's still
809 * useful information to have.
812 append_integer_field_class_from_props(ctx
, 64, 8, false,
813 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
814 NULL
, "packet_seq_num", true);
816 if (sc
->packet_context_fc
) {
817 append_struct_field_class_members(ctx
,
818 fs_sink_ctf_field_class_as_struct(sc
->packet_context_fc
));
819 fs_sink_ctf_field_class_struct_align_at_least(
820 fs_sink_ctf_field_class_as_struct(sc
->packet_context_fc
), 8);
823 /* End packet context field class */
824 append_end_block(ctx
);
825 g_string_append_printf(ctx
->tsdl
, " align(%u);\n\n",
826 sc
->packet_context_fc
? sc
->packet_context_fc
->alignment
: 8);
828 /* Event header field class */
830 g_string_append(ctx
->tsdl
, "event.header := struct {\n");
833 append_integer_field_class_from_props(ctx
, 64, 8, false,
834 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
837 if (sc
->default_clock_class
) {
839 append_integer_field_class_from_props(ctx
, 64, 8, false,
840 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
841 sc
->default_clock_class_name
->str
,
845 /* End event header field class */
846 append_end_block(ctx
);
847 g_string_append(ctx
->tsdl
, " align(8);\n");
849 /* Event common context field class */
850 if (sc
->event_common_context_fc
) {
852 g_string_append(ctx
->tsdl
, "event.context := ");
853 append_field_class(ctx
, sc
->event_common_context_fc
);
854 g_string_append(ctx
->tsdl
, ";\n");
857 /* End stream class */
858 append_end_block_semi_nl_nl(ctx
);
861 for (i
= 0; i
< sc
->event_classes
->len
; i
++) {
862 append_event_class(ctx
,
863 (fs_sink_ctf_event_class
*) sc
->event_classes
->pdata
[i
]);
868 void translate_trace_ctf_ir_to_tsdl(struct fs_sink_ctf_trace
*trace
,
878 g_string_assign(tsdl
, "/* CTF 1.8 */\n\n");
879 g_string_append(tsdl
, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
883 g_string_append(tsdl
, "trace {\n");
886 /* Trace class properties */
888 g_string_append(tsdl
, "major = 1;\n");
890 g_string_append(tsdl
, "minor = 8;\n");
892 g_string_append(tsdl
, "uuid = ");
893 append_uuid(&ctx
, trace
->uuid
);
894 g_string_append(tsdl
, ";\n");
896 g_string_append(tsdl
, "byte_order = ");
898 if (BYTE_ORDER
== LITTLE_ENDIAN
) {
899 g_string_append(tsdl
, "le");
901 g_string_append(tsdl
, "be");
904 g_string_append(tsdl
, ";\n");
906 /* Packet header field class */
908 g_string_append(tsdl
, "packet.header := struct {\n");
911 append_integer_field_class_from_props(&ctx
, 32, 8, false,
912 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
913 NULL
, "magic", true);
915 append_integer_field_class_from_props(&ctx
, 8, 8, false,
916 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
917 NULL
, "uuid[16]", true);
919 append_integer_field_class_from_props(&ctx
, 64, 8, false,
920 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
921 NULL
, "stream_id", true);
923 append_integer_field_class_from_props(&ctx
, 64, 8, false,
924 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
925 NULL
, "stream_instance_id", true);
927 /* End packet header field class */
928 append_end_block(&ctx
);
929 g_string_append(ctx
.tsdl
, " align(8);\n");
931 /* End trace class */
932 append_end_block_semi_nl_nl(&ctx
);
934 /* Trace environment */
935 count
= bt_trace_get_environment_entry_count(trace
->ir_trace
);
938 g_string_append(tsdl
, "env {\n");
941 for (i
= 0; i
< count
; i
++) {
945 bt_trace_borrow_environment_entry_by_index_const(
946 trace
->ir_trace
, i
, &name
, &val
);
948 g_string_append_printf(tsdl
, "%s = ", name
);
950 switch (bt_value_get_type(val
)) {
951 case BT_VALUE_TYPE_SIGNED_INTEGER
:
952 g_string_append_printf(tsdl
, "%" PRId64
,
953 bt_value_integer_signed_get(val
));
955 case BT_VALUE_TYPE_STRING
:
956 append_quoted_string(&ctx
, bt_value_string_get(val
));
961 * translate_trace_trace_ir_to_ctf_ir().
966 g_string_append(tsdl
, ";\n");
969 /* End trace class environment */
970 append_end_block_semi_nl_nl(&ctx
);
973 /* Stream classes and their event classes */
974 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
975 append_stream_class(&ctx
,
976 (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
]);