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 #include "translate-ctf-ir-to-tsdl.h"
25 #include <babeltrace2/babeltrace.h>
26 #include "common/macros.h"
31 #include "common/assert.h"
32 #include "compat/endian.h"
34 #include "fs-sink-ctf-meta.h"
37 unsigned int indent_level
;
42 void append_indent(struct ctx
*ctx
)
46 for (i
= 0; i
< ctx
->indent_level
; i
++) {
47 g_string_append_c(ctx
->tsdl
, '\t');
52 void append_uuid(struct ctx
*ctx
, bt_uuid uuid
)
54 g_string_append_printf(ctx
->tsdl
,
55 "\"" BT_UUID_FMT
"\"",
56 BT_UUID_FMT_VALUES(uuid
));
60 void append_quoted_string_content(struct ctx
*ctx
, const char *str
)
64 for (ch
= str
; *ch
!= '\0'; ch
++) {
65 unsigned char uch
= (unsigned char) *ch
;
67 if (uch
< 32 || uch
>= 127) {
70 g_string_append(ctx
->tsdl
, "\\a");
73 g_string_append(ctx
->tsdl
, "\\b");
76 g_string_append(ctx
->tsdl
, "\\f");
79 g_string_append(ctx
->tsdl
, "\\n");
82 g_string_append(ctx
->tsdl
, "\\r");
85 g_string_append(ctx
->tsdl
, "\\t");
88 g_string_append(ctx
->tsdl
, "\\v");
91 g_string_append_printf(ctx
->tsdl
, "\\x%02x",
95 } else if (*ch
== '"' || *ch
== '\\') {
96 g_string_append_c(ctx
->tsdl
, '\\');
97 g_string_append_c(ctx
->tsdl
, *ch
);
99 g_string_append_c(ctx
->tsdl
, *ch
);
105 void append_quoted_string(struct ctx
*ctx
, const char *str
)
107 g_string_append_c(ctx
->tsdl
, '"');
108 append_quoted_string_content(ctx
, str
);
109 g_string_append_c(ctx
->tsdl
, '"');
113 void append_integer_field_class_from_props(struct ctx
*ctx
, unsigned int size
,
114 unsigned int alignment
, bool is_signed
,
115 bt_field_class_integer_preferred_display_base disp_base
,
116 const char *mapped_clock_class_name
, const char *field_name
,
119 g_string_append_printf(ctx
->tsdl
,
120 "integer { size = %u; align = %u;",
124 g_string_append(ctx
->tsdl
, " signed = true;");
127 if (disp_base
!= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
) {
128 g_string_append(ctx
->tsdl
, " base = ");
131 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
132 g_string_append(ctx
->tsdl
, "b");
134 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
135 g_string_append(ctx
->tsdl
, "o");
137 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
138 g_string_append(ctx
->tsdl
, "x");
144 g_string_append_c(ctx
->tsdl
, ';');
147 if (mapped_clock_class_name
) {
148 g_string_append_printf(ctx
->tsdl
, " map = clock.%s.value;",
149 mapped_clock_class_name
);
152 g_string_append(ctx
->tsdl
, " }");
155 g_string_append_printf(ctx
->tsdl
, " %s", field_name
);
159 g_string_append(ctx
->tsdl
, ";\n");
164 void append_end_block(struct ctx
*ctx
)
168 g_string_append(ctx
->tsdl
, "}");
172 void append_end_block_semi_nl(struct ctx
*ctx
)
176 g_string_append(ctx
->tsdl
, "};\n");
180 void append_end_block_semi_nl_nl(struct ctx
*ctx
)
182 append_end_block_semi_nl(ctx
);
183 g_string_append_c(ctx
->tsdl
, '\n');
187 void append_bool_field_class(struct ctx
*ctx
,
188 __attribute__((unused
)) struct fs_sink_ctf_field_class_bool
*fc
)
191 * CTF 1.8 has no boolean field class type, so this component
192 * translates it to an 8-bit unsigned integer field class.
194 append_integer_field_class_from_props(ctx
, fc
->base
.size
,
195 fc
->base
.base
.alignment
, false,
196 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
201 void append_bit_array_field_class(struct ctx
*ctx
,
202 struct fs_sink_ctf_field_class_bit_array
*fc
)
205 * CTF 1.8 has no bit array field class type, so this component
206 * translates it to an unsigned integer field class with an
209 append_integer_field_class_from_props(ctx
, fc
->size
,
210 fc
->base
.alignment
, false,
211 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
216 void append_integer_field_class(struct ctx
*ctx
,
217 struct fs_sink_ctf_field_class_int
*fc
)
219 const bt_field_class
*ir_fc
= fc
->base
.base
.ir_fc
;
220 bt_field_class_type type
= bt_field_class_get_type(ir_fc
);
221 bool is_signed
= bt_field_class_type_is(type
,
222 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
);
224 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
225 g_string_append(ctx
->tsdl
, "enum : ");
228 append_integer_field_class_from_props(ctx
, fc
->base
.size
,
229 fc
->base
.base
.alignment
, is_signed
,
230 bt_field_class_integer_get_preferred_display_base(ir_fc
),
233 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
236 g_string_append(ctx
->tsdl
, " {\n");
239 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_fc
); i
++) {
241 const bt_field_class_enumeration_mapping
*mapping
;
242 const bt_field_class_enumeration_unsigned_mapping
*u_mapping
;
243 const bt_field_class_enumeration_signed_mapping
*s_mapping
;
244 const bt_integer_range_set
*ranges
;
245 const bt_integer_range_set_unsigned
*u_ranges
;
246 const bt_integer_range_set_signed
*s_ranges
;
247 uint64_t range_count
;
251 s_mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
253 mapping
= bt_field_class_enumeration_signed_mapping_as_mapping_const(
255 s_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
257 ranges
= bt_integer_range_set_signed_as_range_set_const(
260 u_mapping
= bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
262 mapping
= bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
264 u_ranges
= bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
266 ranges
= bt_integer_range_set_unsigned_as_range_set_const(
270 label
= bt_field_class_enumeration_mapping_get_label(
272 range_count
= bt_integer_range_set_get_range_count(
275 for (range_i
= 0; range_i
< range_count
; range_i
++) {
277 g_string_append(ctx
->tsdl
, "\"");
278 append_quoted_string_content(ctx
, label
);
279 g_string_append(ctx
->tsdl
, "\" = ");
282 const bt_integer_range_signed
*range
;
283 int64_t lower
, upper
;
285 range
= bt_integer_range_set_signed_borrow_range_by_index_const(
287 lower
= bt_integer_range_signed_get_lower(
289 upper
= bt_integer_range_signed_get_upper(
292 if (lower
== upper
) {
293 g_string_append_printf(
294 ctx
->tsdl
, "%" PRId64
,
297 g_string_append_printf(
298 ctx
->tsdl
, "%" PRId64
" ... %" PRId64
,
302 const bt_integer_range_unsigned
*range
;
303 uint64_t lower
, upper
;
305 range
= bt_integer_range_set_unsigned_borrow_range_by_index_const(
307 lower
= bt_integer_range_unsigned_get_lower(
309 upper
= bt_integer_range_unsigned_get_upper(
312 if (lower
== upper
) {
313 g_string_append_printf(
314 ctx
->tsdl
, "%" PRIu64
,
317 g_string_append_printf(
318 ctx
->tsdl
, "%" PRIu64
" ... %" PRIu64
,
323 g_string_append(ctx
->tsdl
, ",\n");
327 append_end_block(ctx
);
332 void append_float_field_class(struct ctx
*ctx
,
333 struct fs_sink_ctf_field_class_float
*fc
)
335 unsigned int mant_dig
, exp_dig
;
337 if (bt_field_class_get_type(fc
->base
.base
.ir_fc
) ==
338 BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
) {
346 g_string_append_printf(ctx
->tsdl
,
347 "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
348 mant_dig
, exp_dig
, fc
->base
.base
.alignment
);
352 void append_string_field_class(struct ctx
*ctx
,
353 struct fs_sink_ctf_field_class_float
*fc
)
355 g_string_append(ctx
->tsdl
, "string { encoding = UTF8; }");
359 void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
);
362 void append_member(struct ctx
*ctx
, const char *name
,
363 struct fs_sink_ctf_field_class
*fc
)
365 GString
*lengths
= NULL
;
366 const char *lengths_str
= "";
370 while (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
||
371 fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
373 lengths
= g_string_new(NULL
);
377 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
) {
378 struct fs_sink_ctf_field_class_array
*array_fc
=
381 g_string_append_printf(lengths
, "[%" PRIu64
"]",
383 fc
= array_fc
->base
.elem_fc
;
385 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
388 g_string_append_printf(lengths
, "[%s]",
389 seq_fc
->length_ref
->str
);
390 fc
= seq_fc
->base
.elem_fc
;
394 append_field_class(ctx
, fc
);
397 lengths_str
= lengths
->str
;
400 g_string_append_printf(ctx
->tsdl
, " %s%s;\n", name
, lengths_str
);
403 g_string_free(lengths
, TRUE
);
408 void append_struct_field_class_members(struct ctx
*ctx
,
409 struct fs_sink_ctf_field_class_struct
*struct_fc
)
413 for (i
= 0; i
< struct_fc
->members
->len
; i
++) {
414 struct fs_sink_ctf_named_field_class
*named_fc
=
415 fs_sink_ctf_field_class_struct_borrow_member_by_index(
417 struct fs_sink_ctf_field_class
*fc
= named_fc
->fc
;
420 * For sequence, option, and variant field classes, if
421 * the length/tag field class is generated before, write
422 * it now before the dependent field class.
424 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
425 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
428 if (seq_fc
->length_is_before
) {
430 append_integer_field_class_from_props(ctx
,
432 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
433 NULL
, seq_fc
->length_ref
->str
, true);
435 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
) {
436 struct fs_sink_ctf_field_class_option
*opt_fc
=
440 * CTF 1.8 does not support the option field
441 * class type. To write something anyway, this
442 * component translates this type to a variant
443 * field class where the options are:
445 * * An empty structure field class.
446 * * The optional field class itself.
448 * The "tag" is always generated/before in that
449 * case (an 8-bit unsigned enumeration field
453 g_string_append(ctx
->tsdl
,
454 "/* The enumeration and variant field classes "
455 "below were a trace IR option field class. */\n");
457 g_string_append(ctx
->tsdl
, "enum : ");
458 append_integer_field_class_from_props(ctx
,
460 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
462 g_string_append(ctx
->tsdl
, " {\n");
465 g_string_append(ctx
->tsdl
, "none = 0,\n");
467 g_string_append(ctx
->tsdl
, "content = 1,\n");
468 append_end_block(ctx
);
469 g_string_append_printf(ctx
->tsdl
, " %s;\n",
470 opt_fc
->tag_ref
->str
);
471 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
) {
472 struct fs_sink_ctf_field_class_variant
*var_fc
=
475 if (var_fc
->tag_is_before
) {
477 g_string_append(ctx
->tsdl
, "enum : ");
478 append_integer_field_class_from_props(ctx
,
480 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
482 g_string_append(ctx
->tsdl
, " {\n");
485 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
486 struct fs_sink_ctf_named_field_class
*option_named_fc
=
487 fs_sink_ctf_field_class_variant_borrow_option_by_index(
491 g_string_append_printf(ctx
->tsdl
,
492 "\"%s\" = %" PRIu64
",\n",
493 option_named_fc
->name
->str
, i
);
496 append_end_block(ctx
);
497 g_string_append_printf(ctx
->tsdl
, " %s;\n",
498 var_fc
->tag_ref
->str
);
500 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
) {
502 g_string_append(ctx
->tsdl
,
503 "/* The integer field class below was a trace IR boolean field class. */\n");
504 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
) {
506 g_string_append(ctx
->tsdl
,
507 "/* The integer field class below was a trace IR bit array field class. */\n");
511 append_member(ctx
, named_fc
->name
->str
, fc
);
516 void append_struct_field_class(struct ctx
*ctx
,
517 struct fs_sink_ctf_field_class_struct
*fc
)
519 g_string_append(ctx
->tsdl
, "struct {\n");
521 append_struct_field_class_members(ctx
, fc
);
522 append_end_block(ctx
);
523 g_string_append_printf(ctx
->tsdl
, " align(%u)",
528 void append_option_field_class(struct ctx
*ctx
,
529 struct fs_sink_ctf_field_class_option
*opt_fc
)
531 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n",
532 opt_fc
->tag_ref
->str
);
535 g_string_append(ctx
->tsdl
, "struct { } none;\n");
537 append_member(ctx
, "content", opt_fc
->content_fc
);
538 append_end_block(ctx
);
542 void append_variant_field_class(struct ctx
*ctx
,
543 struct fs_sink_ctf_field_class_variant
*var_fc
)
547 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n",
548 var_fc
->tag_ref
->str
);
551 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
552 struct fs_sink_ctf_named_field_class
*named_fc
=
553 fs_sink_ctf_field_class_variant_borrow_option_by_index(
557 append_member(ctx
, named_fc
->name
->str
, named_fc
->fc
);
560 append_end_block(ctx
);
564 void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
)
567 case FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
:
568 append_bool_field_class(ctx
, (void *) fc
);
570 case FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
:
571 append_bit_array_field_class(ctx
, (void *) fc
);
573 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT
:
574 append_integer_field_class(ctx
, (void *) fc
);
576 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT
:
577 append_float_field_class(ctx
, (void *) fc
);
579 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING
:
580 append_string_field_class(ctx
, (void *) fc
);
582 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
583 append_struct_field_class(ctx
, (void *) fc
);
585 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
586 append_option_field_class(ctx
, (void *) fc
);
588 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
589 append_variant_field_class(ctx
, (void *) fc
);
597 void append_event_class(struct ctx
*ctx
, struct fs_sink_ctf_event_class
*ec
)
600 bt_event_class_log_level log_level
;
604 g_string_append(ctx
->tsdl
, "event {\n");
607 /* Event class properties */
609 g_string_append(ctx
->tsdl
, "name = ");
610 str
= bt_event_class_get_name(ec
->ir_ec
);
615 append_quoted_string(ctx
, str
);
616 g_string_append(ctx
->tsdl
, ";\n");
618 g_string_append_printf(ctx
->tsdl
, "stream_id = %" PRIu64
";\n",
619 bt_stream_class_get_id(ec
->sc
->ir_sc
));
621 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n",
622 bt_event_class_get_id(ec
->ir_ec
));
624 str
= bt_event_class_get_emf_uri(ec
->ir_ec
);
627 g_string_append(ctx
->tsdl
, "model.emf.uri = ");
628 append_quoted_string(ctx
, str
);
629 g_string_append(ctx
->tsdl
, ";\n");
632 if (bt_event_class_get_log_level(ec
->ir_ec
, &log_level
) ==
633 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
637 g_string_append(ctx
->tsdl
, "loglevel = ");
640 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
643 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
646 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
649 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
652 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
655 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
658 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
661 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
664 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
667 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
670 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
673 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
676 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
679 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
682 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
689 g_string_append_printf(ctx
->tsdl
, "%u;\n", level
);
692 /* Event specific context field class */
693 if (ec
->spec_context_fc
) {
695 g_string_append(ctx
->tsdl
, "context := ");
696 append_field_class(ctx
, ec
->spec_context_fc
);
697 g_string_append(ctx
->tsdl
, ";\n");
700 /* Event payload field class */
701 if (ec
->payload_fc
) {
703 g_string_append(ctx
->tsdl
, "fields := ");
704 append_field_class(ctx
, ec
->payload_fc
);
705 g_string_append(ctx
->tsdl
, ";\n");
708 append_end_block_semi_nl_nl(ctx
);
712 void append_stream_class(struct ctx
*ctx
,
713 struct fs_sink_ctf_stream_class
*sc
)
717 /* Default clock class */
718 if (sc
->default_clock_class
) {
720 int64_t offset_seconds
;
721 uint64_t offset_cycles
;
725 g_string_append(ctx
->tsdl
, "clock {\n");
727 BT_ASSERT(sc
->default_clock_class_name
->len
> 0);
729 g_string_append_printf(ctx
->tsdl
, "name = %s;\n",
730 sc
->default_clock_class_name
->str
);
731 descr
= bt_clock_class_get_description(sc
->default_clock_class
);
734 g_string_append(ctx
->tsdl
, "description = ");
735 append_quoted_string(ctx
, descr
);
736 g_string_append(ctx
->tsdl
, ";\n");
740 g_string_append_printf(ctx
->tsdl
, "freq = %" PRIu64
";\n",
741 bt_clock_class_get_frequency(sc
->default_clock_class
));
743 g_string_append_printf(ctx
->tsdl
, "precision = %" PRIu64
";\n",
744 bt_clock_class_get_precision(sc
->default_clock_class
));
745 bt_clock_class_get_offset(sc
->default_clock_class
,
746 &offset_seconds
, &offset_cycles
);
748 g_string_append_printf(ctx
->tsdl
, "offset_s = %" PRId64
";\n",
751 g_string_append_printf(ctx
->tsdl
, "offset = %" PRIu64
";\n",
754 g_string_append(ctx
->tsdl
, "absolute = ");
756 if (bt_clock_class_origin_is_unix_epoch(
757 sc
->default_clock_class
)) {
758 g_string_append(ctx
->tsdl
, "true");
760 g_string_append(ctx
->tsdl
, "false");
763 g_string_append(ctx
->tsdl
, ";\n");
764 uuid
= bt_clock_class_get_uuid(sc
->default_clock_class
);
767 g_string_append(ctx
->tsdl
, "uuid = ");
768 append_uuid(ctx
, uuid
);
769 g_string_append(ctx
->tsdl
, ";\n");
772 /* End clock class */
773 append_end_block_semi_nl_nl(ctx
);
778 g_string_append(ctx
->tsdl
, "stream {\n");
781 /* Stream class properties */
783 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n",
784 bt_stream_class_get_id(sc
->ir_sc
));
786 /* Packet context field class */
788 g_string_append(ctx
->tsdl
, "packet.context := struct {\n");
791 append_integer_field_class_from_props(ctx
, 64, 8, false,
792 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
793 NULL
, "packet_size", true);
795 append_integer_field_class_from_props(ctx
, 64, 8, false,
796 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
797 NULL
, "content_size", true);
799 if (sc
->packets_have_ts_begin
) {
801 append_integer_field_class_from_props(ctx
, 64, 8, false,
802 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
803 sc
->default_clock_class_name
->str
,
804 "timestamp_begin", true);
807 if (sc
->packets_have_ts_end
) {
809 append_integer_field_class_from_props(ctx
, 64, 8, false,
810 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
811 sc
->default_clock_class_name
->str
,
812 "timestamp_end", true);
815 if (sc
->has_discarded_events
) {
817 append_integer_field_class_from_props(ctx
, 64, 8, false,
818 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
819 NULL
, "events_discarded", true);
823 * Unconditionnally write the packet sequence number as, even if
824 * there's no possible discarded packets message, it's still
825 * useful information to have.
828 append_integer_field_class_from_props(ctx
, 64, 8, false,
829 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
830 NULL
, "packet_seq_num", true);
832 if (sc
->packet_context_fc
) {
833 append_struct_field_class_members(ctx
,
834 (void *) sc
->packet_context_fc
);
835 fs_sink_ctf_field_class_struct_align_at_least(
836 (void *) sc
->packet_context_fc
, 8);
839 /* End packet context field class */
840 append_end_block(ctx
);
841 g_string_append_printf(ctx
->tsdl
, " align(%u);\n\n",
842 sc
->packet_context_fc
? sc
->packet_context_fc
->alignment
: 8);
844 /* Event header field class */
846 g_string_append(ctx
->tsdl
, "event.header := struct {\n");
849 append_integer_field_class_from_props(ctx
, 64, 8, false,
850 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
853 if (sc
->default_clock_class
) {
855 append_integer_field_class_from_props(ctx
, 64, 8, false,
856 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
857 sc
->default_clock_class_name
->str
,
861 /* End event header field class */
862 append_end_block(ctx
);
863 g_string_append(ctx
->tsdl
, " align(8);\n");
865 /* Event common context field class */
866 if (sc
->event_common_context_fc
) {
868 g_string_append(ctx
->tsdl
, "event.context := ");
869 append_field_class(ctx
,
870 (void *) sc
->event_common_context_fc
);
871 g_string_append(ctx
->tsdl
, ";\n");
874 /* End stream class */
875 append_end_block_semi_nl_nl(ctx
);
878 for (i
= 0; i
< sc
->event_classes
->len
; i
++) {
879 append_event_class(ctx
, sc
->event_classes
->pdata
[i
]);
884 void translate_trace_ctf_ir_to_tsdl(struct fs_sink_ctf_trace
*trace
,
894 g_string_assign(tsdl
, "/* CTF 1.8 */\n\n");
895 g_string_append(tsdl
, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
899 g_string_append(tsdl
, "trace {\n");
902 /* Trace class properties */
904 g_string_append(tsdl
, "major = 1;\n");
906 g_string_append(tsdl
, "minor = 8;\n");
908 g_string_append(tsdl
, "uuid = ");
909 append_uuid(&ctx
, trace
->uuid
);
910 g_string_append(tsdl
, ";\n");
912 g_string_append(tsdl
, "byte_order = ");
914 if (BYTE_ORDER
== LITTLE_ENDIAN
) {
915 g_string_append(tsdl
, "le");
917 g_string_append(tsdl
, "be");
920 g_string_append(tsdl
, ";\n");
922 /* Packet header field class */
924 g_string_append(tsdl
, "packet.header := struct {\n");
927 append_integer_field_class_from_props(&ctx
, 32, 8, false,
928 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
929 NULL
, "magic", true);
931 append_integer_field_class_from_props(&ctx
, 8, 8, false,
932 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
933 NULL
, "uuid[16]", true);
935 append_integer_field_class_from_props(&ctx
, 64, 8, false,
936 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
937 NULL
, "stream_id", true);
939 append_integer_field_class_from_props(&ctx
, 64, 8, false,
940 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
941 NULL
, "stream_instance_id", true);
943 /* End packet header field class */
944 append_end_block(&ctx
);
945 g_string_append(ctx
.tsdl
, " align(8);\n");
947 /* End trace class */
948 append_end_block_semi_nl_nl(&ctx
);
950 /* Trace environment */
951 count
= bt_trace_get_environment_entry_count(trace
->ir_trace
);
954 g_string_append(tsdl
, "env {\n");
957 for (i
= 0; i
< count
; i
++) {
961 bt_trace_borrow_environment_entry_by_index_const(
962 trace
->ir_trace
, i
, &name
, &val
);
964 g_string_append_printf(tsdl
, "%s = ", name
);
966 switch (bt_value_get_type(val
)) {
967 case BT_VALUE_TYPE_SIGNED_INTEGER
:
968 g_string_append_printf(tsdl
, "%" PRId64
,
969 bt_value_integer_signed_get(val
));
971 case BT_VALUE_TYPE_STRING
:
972 append_quoted_string(&ctx
, bt_value_string_get(val
));
977 * translate_trace_trace_ir_to_ctf_ir().
982 g_string_append(tsdl
, ";\n");
985 /* End trace class environment */
986 append_end_block_semi_nl_nl(&ctx
);
989 /* Stream classes and their event classes */
990 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
991 append_stream_class(&ctx
, trace
->stream_classes
->pdata
[i
]);