2 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #define BT_LOG_TAG "PLUGIN-CTF-FS-SINK-TRANSLATE-CTF-IR-TO-TSDL"
26 #include <babeltrace2/babeltrace.h>
27 #include "common/babeltrace.h"
32 #include "common/assert.h"
33 #include "compat/endian.h"
35 #include "fs-sink-ctf-meta.h"
38 unsigned int indent_level
;
43 void append_indent(struct ctx
*ctx
)
47 for (i
= 0; i
< ctx
->indent_level
; i
++) {
48 g_string_append_c(ctx
->tsdl
, '\t');
53 void append_uuid(struct ctx
*ctx
, bt_uuid uuid
)
55 g_string_append_printf(ctx
->tsdl
,
56 "\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
57 (unsigned int) uuid
[0],
58 (unsigned int) uuid
[1],
59 (unsigned int) uuid
[2],
60 (unsigned int) uuid
[3],
61 (unsigned int) uuid
[4],
62 (unsigned int) uuid
[5],
63 (unsigned int) uuid
[6],
64 (unsigned int) uuid
[7],
65 (unsigned int) uuid
[8],
66 (unsigned int) uuid
[9],
67 (unsigned int) uuid
[10],
68 (unsigned int) uuid
[11],
69 (unsigned int) uuid
[12],
70 (unsigned int) uuid
[13],
71 (unsigned int) uuid
[14],
72 (unsigned int) uuid
[15]);
76 void append_quoted_string_content(struct ctx
*ctx
, const char *str
)
80 for (ch
= str
; *ch
!= '\0'; ch
++) {
81 unsigned char uch
= (unsigned char) *ch
;
83 if (uch
< 32 || uch
>= 127) {
86 g_string_append(ctx
->tsdl
, "\\a");
89 g_string_append(ctx
->tsdl
, "\\b");
92 g_string_append(ctx
->tsdl
, "\\f");
95 g_string_append(ctx
->tsdl
, "\\n");
98 g_string_append(ctx
->tsdl
, "\\r");
101 g_string_append(ctx
->tsdl
, "\\t");
104 g_string_append(ctx
->tsdl
, "\\v");
107 g_string_append_printf(ctx
->tsdl
, "\\x%02x",
111 } else if (*ch
== '"' || *ch
== '\\') {
112 g_string_append_c(ctx
->tsdl
, '\\');
113 g_string_append_c(ctx
->tsdl
, *ch
);
115 g_string_append_c(ctx
->tsdl
, *ch
);
121 void append_quoted_string(struct ctx
*ctx
, const char *str
)
123 g_string_append_c(ctx
->tsdl
, '"');
124 append_quoted_string_content(ctx
, str
);
125 g_string_append_c(ctx
->tsdl
, '"');
129 void append_integer_field_class_from_props(struct ctx
*ctx
, unsigned int size
,
130 unsigned int alignment
, bool is_signed
,
131 bt_field_class_integer_preferred_display_base disp_base
,
132 const char *mapped_clock_class_name
, const char *field_name
,
135 g_string_append_printf(ctx
->tsdl
,
136 "integer { size = %u; align = %u;",
140 g_string_append(ctx
->tsdl
, " signed = true;");
143 if (disp_base
!= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
) {
144 g_string_append(ctx
->tsdl
, " base = ");
147 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
148 g_string_append(ctx
->tsdl
, "b");
150 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
151 g_string_append(ctx
->tsdl
, "o");
153 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
154 g_string_append(ctx
->tsdl
, "x");
160 g_string_append_c(ctx
->tsdl
, ';');
163 if (mapped_clock_class_name
) {
164 g_string_append_printf(ctx
->tsdl
, " map = clock.%s.value;",
165 mapped_clock_class_name
);
168 g_string_append(ctx
->tsdl
, " }");
171 g_string_append_printf(ctx
->tsdl
, " %s", field_name
);
175 g_string_append(ctx
->tsdl
, ";\n");
180 void append_end_block(struct ctx
*ctx
)
184 g_string_append(ctx
->tsdl
, "}");
188 void append_end_block_semi_nl(struct ctx
*ctx
)
192 g_string_append(ctx
->tsdl
, "};\n");
196 void append_end_block_semi_nl_nl(struct ctx
*ctx
)
198 append_end_block_semi_nl(ctx
);
199 g_string_append_c(ctx
->tsdl
, '\n');
203 void append_integer_field_class(struct ctx
*ctx
,
204 struct fs_sink_ctf_field_class_int
*fc
)
206 const bt_field_class
*ir_fc
= fc
->base
.base
.ir_fc
;
207 bt_field_class_type type
= bt_field_class_get_type(ir_fc
);
208 bool is_signed
= type
== BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
||
209 type
== BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
;
211 if (type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
||
212 type
== BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
) {
213 g_string_append(ctx
->tsdl
, "enum : ");
216 append_integer_field_class_from_props(ctx
, fc
->base
.size
,
217 fc
->base
.base
.alignment
, is_signed
,
218 bt_field_class_integer_get_preferred_display_base(ir_fc
),
221 if (type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
||
222 type
== BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
) {
225 g_string_append(ctx
->tsdl
, " {\n");
228 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_fc
); i
++) {
230 const bt_field_class_enumeration_mapping
*mapping
;
231 const bt_field_class_unsigned_enumeration_mapping
*u_mapping
;
232 const bt_field_class_signed_enumeration_mapping
*i_mapping
;
233 uint64_t range_count
;
237 i_mapping
= bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
239 mapping
= bt_field_class_signed_enumeration_mapping_as_mapping_const(
242 u_mapping
= bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
244 mapping
= bt_field_class_unsigned_enumeration_mapping_as_mapping_const(
248 label
= bt_field_class_enumeration_mapping_get_label(
251 bt_field_class_enumeration_mapping_get_range_count(
254 for (range_i
= 0; range_i
< range_count
; range_i
++) {
258 * Systematically prepend `_` to the
259 * mapping's label as this could be used
260 * as the tag of a subsequent variant
261 * field class and variant FC option
262 * names are systematically protected
263 * with a leading `_`.
265 * FIXME: This is temporary as the
266 * library's API should change to
267 * decouple variant FC option names from
268 * selector FC labels. The current
269 * drawback is that an original label
270 * `HELLO` becomes `_HELLO` in the
271 * generated metadata, therefore tools
272 * expecting `HELLO` could fail.
274 g_string_append(ctx
->tsdl
, "\"_");
275 append_quoted_string_content(ctx
, label
);
276 g_string_append(ctx
->tsdl
, "\" = ");
279 int64_t lower
, upper
;
281 bt_field_class_signed_enumeration_mapping_get_range_by_index(
285 if (lower
== upper
) {
286 g_string_append_printf(
287 ctx
->tsdl
, "%" PRId64
,
290 g_string_append_printf(
291 ctx
->tsdl
, "%" PRId64
" ... %" PRId64
,
295 uint64_t lower
, upper
;
297 bt_field_class_unsigned_enumeration_mapping_get_range_by_index(
301 if (lower
== upper
) {
302 g_string_append_printf(
303 ctx
->tsdl
, "%" PRIu64
,
306 g_string_append_printf(
307 ctx
->tsdl
, "%" PRIu64
" ... %" PRIu64
,
312 g_string_append(ctx
->tsdl
, ",\n");
316 append_end_block(ctx
);
321 void append_float_field_class(struct ctx
*ctx
,
322 struct fs_sink_ctf_field_class_float
*fc
)
324 unsigned int mant_dig
, exp_dig
;
326 if (bt_field_class_real_is_single_precision(fc
->base
.base
.ir_fc
)) {
334 g_string_append_printf(ctx
->tsdl
,
335 "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
336 mant_dig
, exp_dig
, fc
->base
.base
.alignment
);
340 void append_string_field_class(struct ctx
*ctx
,
341 struct fs_sink_ctf_field_class_float
*fc
)
343 g_string_append(ctx
->tsdl
, "string { encoding = UTF8; }");
347 void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
);
350 void append_member(struct ctx
*ctx
, const char *name
,
351 struct fs_sink_ctf_field_class
*fc
)
353 GString
*lengths
= NULL
;
354 const char *lengths_str
= "";
356 while (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
||
357 fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
359 lengths
= g_string_new(NULL
);
363 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
) {
364 struct fs_sink_ctf_field_class_array
*array_fc
=
367 g_string_append_printf(lengths
, "[%" PRIu64
"]",
369 fc
= array_fc
->base
.elem_fc
;
371 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
374 g_string_append_printf(lengths
, "[%s]",
375 seq_fc
->length_ref
->str
);
376 fc
= seq_fc
->base
.elem_fc
;
380 append_field_class(ctx
, fc
);
383 lengths_str
= lengths
->str
;
386 g_string_append_printf(ctx
->tsdl
, " %s%s;\n", name
, lengths_str
);
389 g_string_free(lengths
, TRUE
);
394 void append_struct_field_class_members(struct ctx
*ctx
,
395 struct fs_sink_ctf_field_class_struct
*struct_fc
)
399 for (i
= 0; i
< struct_fc
->members
->len
; i
++) {
400 struct fs_sink_ctf_named_field_class
*named_fc
=
401 fs_sink_ctf_field_class_struct_borrow_member_by_index(
403 struct fs_sink_ctf_field_class
*fc
= named_fc
->fc
;
405 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
406 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
409 if (seq_fc
->length_is_before
) {
411 append_integer_field_class_from_props(ctx
,
413 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
414 NULL
, seq_fc
->length_ref
->str
, true);
416 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
) {
417 struct fs_sink_ctf_field_class_variant
*var_fc
=
420 if (var_fc
->tag_is_before
) {
422 g_string_append(ctx
->tsdl
, "enum : ");
423 append_integer_field_class_from_props(ctx
,
425 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
427 g_string_append(ctx
->tsdl
, " {\n");
430 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
431 struct fs_sink_ctf_named_field_class
*named_fc
=
432 fs_sink_ctf_field_class_variant_borrow_option_by_index(
436 g_string_append_printf(ctx
->tsdl
,
437 "\"%s\" = %" PRIu64
",\n",
438 named_fc
->name
->str
, i
);
441 append_end_block(ctx
);
442 g_string_append_printf(ctx
->tsdl
, " %s;\n",
443 var_fc
->tag_ref
->str
);
448 append_member(ctx
, named_fc
->name
->str
, fc
);
453 void append_struct_field_class(struct ctx
*ctx
,
454 struct fs_sink_ctf_field_class_struct
*fc
)
456 g_string_append(ctx
->tsdl
, "struct {\n");
458 append_struct_field_class_members(ctx
, fc
);
459 append_end_block(ctx
);
460 g_string_append_printf(ctx
->tsdl
, " align(%u)",
465 void append_variant_field_class(struct ctx
*ctx
,
466 struct fs_sink_ctf_field_class_variant
*var_fc
)
470 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n",
471 var_fc
->tag_ref
->str
);
474 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
475 struct fs_sink_ctf_named_field_class
*named_fc
=
476 fs_sink_ctf_field_class_variant_borrow_option_by_index(
480 append_member(ctx
, named_fc
->name
->str
, named_fc
->fc
);
483 append_end_block(ctx
);
487 void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
)
490 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT
:
491 append_integer_field_class(ctx
, (void *) fc
);
493 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT
:
494 append_float_field_class(ctx
, (void *) fc
);
496 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING
:
497 append_string_field_class(ctx
, (void *) fc
);
499 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
500 append_struct_field_class(ctx
, (void *) fc
);
502 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
503 append_variant_field_class(ctx
, (void *) fc
);
511 void append_event_class(struct ctx
*ctx
, struct fs_sink_ctf_event_class
*ec
)
514 bt_event_class_log_level log_level
;
518 g_string_append(ctx
->tsdl
, "event {\n");
521 /* Event class properties */
523 g_string_append(ctx
->tsdl
, "name = ");
524 str
= bt_event_class_get_name(ec
->ir_ec
);
529 append_quoted_string(ctx
, str
);
530 g_string_append(ctx
->tsdl
, ";\n");
532 g_string_append_printf(ctx
->tsdl
, "stream_id = %" PRIu64
";\n",
533 bt_stream_class_get_id(ec
->sc
->ir_sc
));
535 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n",
536 bt_event_class_get_id(ec
->ir_ec
));
538 str
= bt_event_class_get_emf_uri(ec
->ir_ec
);
541 g_string_append(ctx
->tsdl
, "model.emf.uri = ");
542 append_quoted_string(ctx
, str
);
543 g_string_append(ctx
->tsdl
, ";\n");
546 if (bt_event_class_get_log_level(ec
->ir_ec
, &log_level
) ==
547 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
551 g_string_append(ctx
->tsdl
, "loglevel = ");
554 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
557 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
560 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
563 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
566 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
569 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
572 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
575 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
578 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
581 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
584 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
587 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
590 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
593 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
596 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
603 g_string_append_printf(ctx
->tsdl
, "%u;\n", level
);
606 /* Event specific context field class */
607 if (ec
->spec_context_fc
) {
609 g_string_append(ctx
->tsdl
, "context := ");
610 append_field_class(ctx
, ec
->spec_context_fc
);
611 g_string_append(ctx
->tsdl
, ";\n");
614 /* Event payload field class */
615 if (ec
->payload_fc
) {
617 g_string_append(ctx
->tsdl
, "fields := ");
618 append_field_class(ctx
, ec
->payload_fc
);
619 g_string_append(ctx
->tsdl
, ";\n");
622 append_end_block_semi_nl_nl(ctx
);
626 void append_stream_class(struct ctx
*ctx
,
627 struct fs_sink_ctf_stream_class
*sc
)
631 /* Default clock class */
632 if (sc
->default_clock_class
) {
634 int64_t offset_seconds
;
635 uint64_t offset_cycles
;
639 g_string_append(ctx
->tsdl
, "clock {\n");
641 BT_ASSERT(sc
->default_clock_class_name
->len
> 0);
643 g_string_append_printf(ctx
->tsdl
, "name = %s;\n",
644 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
,
660 &offset_seconds
, &offset_cycles
);
662 g_string_append_printf(ctx
->tsdl
, "offset_s = %" PRId64
";\n",
665 g_string_append_printf(ctx
->tsdl
, "offset = %" PRIu64
";\n",
668 g_string_append(ctx
->tsdl
, "absolute = ");
670 if (bt_clock_class_origin_is_unix_epoch(
671 sc
->default_clock_class
)) {
672 g_string_append(ctx
->tsdl
, "true");
674 g_string_append(ctx
->tsdl
, "false");
677 g_string_append(ctx
->tsdl
, ";\n");
678 uuid
= bt_clock_class_get_uuid(sc
->default_clock_class
);
681 g_string_append(ctx
->tsdl
, "uuid = ");
682 append_uuid(ctx
, uuid
);
683 g_string_append(ctx
->tsdl
, ";\n");
686 /* End clock class */
687 append_end_block_semi_nl_nl(ctx
);
692 g_string_append(ctx
->tsdl
, "stream {\n");
695 /* Stream class properties */
697 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n",
698 bt_stream_class_get_id(sc
->ir_sc
));
700 /* Packet context field class */
702 g_string_append(ctx
->tsdl
, "packet.context := struct {\n");
705 append_integer_field_class_from_props(ctx
, 64, 8, false,
706 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
707 NULL
, "packet_size", true);
709 append_integer_field_class_from_props(ctx
, 64, 8, false,
710 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
711 NULL
, "content_size", true);
713 if (sc
->packets_have_ts_begin
) {
715 append_integer_field_class_from_props(ctx
, 64, 8, false,
716 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
717 sc
->default_clock_class_name
->str
,
718 "timestamp_begin", true);
721 if (sc
->packets_have_ts_end
) {
723 append_integer_field_class_from_props(ctx
, 64, 8, false,
724 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
725 sc
->default_clock_class_name
->str
,
726 "timestamp_end", true);
729 if (sc
->has_discarded_events
) {
731 append_integer_field_class_from_props(ctx
, 64, 8, false,
732 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
733 NULL
, "events_discarded", true);
737 * Unconditionnally write the packet sequence number as, even if
738 * there's no possible discarded packets message, it's still
739 * useful information to have.
742 append_integer_field_class_from_props(ctx
, 64, 8, false,
743 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
744 NULL
, "packet_seq_num", true);
746 if (sc
->packet_context_fc
) {
747 append_struct_field_class_members(ctx
,
748 (void *) sc
->packet_context_fc
);
749 fs_sink_ctf_field_class_struct_align_at_least(
750 (void *) sc
->packet_context_fc
, 8);
753 /* End packet context field class */
754 append_end_block(ctx
);
755 g_string_append_printf(ctx
->tsdl
, " align(%u);\n\n",
756 sc
->packet_context_fc
? sc
->packet_context_fc
->alignment
: 8);
758 /* Event header field class */
760 g_string_append(ctx
->tsdl
, "event.header := struct {\n");
763 append_integer_field_class_from_props(ctx
, 64, 8, false,
764 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
767 if (sc
->default_clock_class
) {
769 append_integer_field_class_from_props(ctx
, 64, 8, false,
770 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
771 sc
->default_clock_class_name
->str
,
775 /* End event header field class */
776 append_end_block(ctx
);
777 g_string_append(ctx
->tsdl
, " align(8);\n");
779 /* Event common context field class */
780 if (sc
->event_common_context_fc
) {
782 g_string_append(ctx
->tsdl
, "event.context := ");
783 append_field_class(ctx
,
784 (void *) sc
->event_common_context_fc
);
785 g_string_append(ctx
->tsdl
, ";\n");
788 /* End stream class */
789 append_end_block_semi_nl_nl(ctx
);
792 for (i
= 0; i
< sc
->event_classes
->len
; i
++) {
793 append_event_class(ctx
, sc
->event_classes
->pdata
[i
]);
798 void translate_trace_class_ctf_ir_to_tsdl(struct fs_sink_ctf_trace_class
*tc
,
808 g_string_assign(tsdl
, "/* CTF 1.8 */\n\n");
809 g_string_append(tsdl
, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
813 g_string_append(tsdl
, "trace {\n");
816 /* Trace class properties */
818 g_string_append(tsdl
, "major = 1;\n");
820 g_string_append(tsdl
, "minor = 8;\n");
822 g_string_append(tsdl
, "uuid = ");
823 append_uuid(&ctx
, tc
->uuid
);
824 g_string_append(tsdl
, ";\n");
826 g_string_append(tsdl
, "byte_order = ");
828 if (BYTE_ORDER
== LITTLE_ENDIAN
) {
829 g_string_append(tsdl
, "le");
831 g_string_append(tsdl
, "be");
834 g_string_append(tsdl
, ";\n");
836 /* Packet header field class */
838 g_string_append(tsdl
, "packet.header := struct {\n");
841 append_integer_field_class_from_props(&ctx
, 32, 8, false,
842 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
843 NULL
, "magic", true);
845 append_integer_field_class_from_props(&ctx
, 8, 8, false,
846 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
847 NULL
, "uuid[16]", true);
849 append_integer_field_class_from_props(&ctx
, 64, 8, false,
850 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
851 NULL
, "stream_id", true);
853 append_integer_field_class_from_props(&ctx
, 64, 8, false,
854 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
855 NULL
, "stream_instance_id", true);
857 /* End packet header field class */
858 append_end_block(&ctx
);
859 g_string_append(ctx
.tsdl
, " align(8);\n");
861 /* End trace class */
862 append_end_block_semi_nl_nl(&ctx
);
864 /* Trace class environment */
865 count
= bt_trace_class_get_environment_entry_count(tc
->ir_tc
);
868 g_string_append(tsdl
, "env {\n");
871 for (i
= 0; i
< count
; i
++) {
875 bt_trace_class_borrow_environment_entry_by_index_const(
876 tc
->ir_tc
, i
, &name
, &val
);
878 g_string_append_printf(tsdl
, "%s = ", name
);
880 switch (bt_value_get_type(val
)) {
881 case BT_VALUE_TYPE_SIGNED_INTEGER
:
882 g_string_append_printf(tsdl
, "%" PRId64
,
883 bt_value_signed_integer_get(val
));
885 case BT_VALUE_TYPE_STRING
:
886 append_quoted_string(&ctx
, bt_value_string_get(val
));
891 * translate_trace_class_trace_ir_to_ctf_ir().
896 g_string_append(tsdl
, ";\n");
899 /* End trace class environment */
900 append_end_block_semi_nl_nl(&ctx
);
903 /* Stream classes and their event classes */
904 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
905 append_stream_class(&ctx
, tc
->stream_classes
->pdata
[i
]);