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"
22 unsigned int indent_level
;
26 static inline void append_indent(struct ctx
*ctx
)
30 for (i
= 0; i
< ctx
->indent_level
; i
++) {
31 g_string_append_c(ctx
->tsdl
, '\t');
35 static void append_uuid(struct ctx
*ctx
, bt_uuid uuid
)
37 g_string_append_printf(ctx
->tsdl
, "\"" BT_UUID_FMT
"\"", BT_UUID_FMT_VALUES(uuid
));
40 static void append_quoted_string_content(struct ctx
*ctx
, const char *str
)
44 for (ch
= str
; *ch
!= '\0'; ch
++) {
45 unsigned char uch
= (unsigned char) *ch
;
47 if (uch
< 32 || uch
>= 127) {
50 g_string_append(ctx
->tsdl
, "\\a");
53 g_string_append(ctx
->tsdl
, "\\b");
56 g_string_append(ctx
->tsdl
, "\\f");
59 g_string_append(ctx
->tsdl
, "\\n");
62 g_string_append(ctx
->tsdl
, "\\r");
65 g_string_append(ctx
->tsdl
, "\\t");
68 g_string_append(ctx
->tsdl
, "\\v");
71 g_string_append_printf(ctx
->tsdl
, "\\x%02x", (unsigned int) uch
);
74 } else if (*ch
== '"' || *ch
== '\\') {
75 g_string_append_c(ctx
->tsdl
, '\\');
76 g_string_append_c(ctx
->tsdl
, *ch
);
78 g_string_append_c(ctx
->tsdl
, *ch
);
83 static void append_quoted_string(struct ctx
*ctx
, const char *str
)
85 g_string_append_c(ctx
->tsdl
, '"');
86 append_quoted_string_content(ctx
, str
);
87 g_string_append_c(ctx
->tsdl
, '"');
90 static void append_integer_field_class_from_props(
91 struct ctx
*ctx
, unsigned int size
, unsigned int alignment
, bool is_signed
,
92 bt_field_class_integer_preferred_display_base disp_base
, const char *mapped_clock_class_name
,
93 const char *field_name
, bool end
)
95 g_string_append_printf(ctx
->tsdl
, "integer { size = %u; align = %u;", size
, alignment
);
98 g_string_append(ctx
->tsdl
, " signed = true;");
101 if (disp_base
!= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
) {
102 g_string_append(ctx
->tsdl
, " base = ");
105 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
106 g_string_append(ctx
->tsdl
, "b");
108 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
109 g_string_append(ctx
->tsdl
, "o");
111 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
112 g_string_append(ctx
->tsdl
, "x");
118 g_string_append_c(ctx
->tsdl
, ';');
121 if (mapped_clock_class_name
) {
122 g_string_append_printf(ctx
->tsdl
, " map = clock.%s.value;", mapped_clock_class_name
);
125 g_string_append(ctx
->tsdl
, " }");
128 g_string_append_printf(ctx
->tsdl
, " %s", field_name
);
132 g_string_append(ctx
->tsdl
, ";\n");
136 static void append_end_block(struct ctx
*ctx
)
140 g_string_append(ctx
->tsdl
, "}");
143 static void append_end_block_semi_nl(struct ctx
*ctx
)
147 g_string_append(ctx
->tsdl
, "};\n");
150 static void append_end_block_semi_nl_nl(struct ctx
*ctx
)
152 append_end_block_semi_nl(ctx
);
153 g_string_append_c(ctx
->tsdl
, '\n');
156 static void append_bool_field_class(struct ctx
*ctx
,
157 __attribute__((unused
)) struct fs_sink_ctf_field_class_bool
*fc
)
160 * CTF 1.8 has no boolean field class type, so this component
161 * translates it to an 8-bit unsigned integer field class.
163 append_integer_field_class_from_props(ctx
, fc
->base
.size
, fc
->base
.base
.alignment
, false,
164 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
168 static void append_bit_array_field_class(struct ctx
*ctx
,
169 struct fs_sink_ctf_field_class_bit_array
*fc
)
172 * CTF 1.8 has no bit array field class type, so this component
173 * translates it to an unsigned integer field class with an
176 append_integer_field_class_from_props(ctx
, fc
->size
, fc
->base
.alignment
, false,
177 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
181 static void append_integer_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class_int
*fc
)
183 const bt_field_class
*ir_fc
= fc
->base
.base
.ir_fc
;
184 bt_field_class_type type
= bt_field_class_get_type(ir_fc
);
185 bool is_signed
= bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
);
187 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
188 g_string_append(ctx
->tsdl
, "enum : ");
191 append_integer_field_class_from_props(ctx
, fc
->base
.size
, fc
->base
.base
.alignment
, is_signed
,
192 bt_field_class_integer_get_preferred_display_base(ir_fc
),
195 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
198 g_string_append(ctx
->tsdl
, " {\n");
201 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_fc
); i
++) {
203 const bt_field_class_enumeration_mapping
*mapping
;
204 const bt_field_class_enumeration_unsigned_mapping
*u_mapping
;
205 const bt_field_class_enumeration_signed_mapping
*s_mapping
;
206 const bt_integer_range_set
*ranges
;
207 const bt_integer_range_set_unsigned
*u_ranges
;
208 const bt_integer_range_set_signed
*s_ranges
;
209 uint64_t range_count
;
214 bt_field_class_enumeration_signed_borrow_mapping_by_index_const(ir_fc
, i
);
215 mapping
= bt_field_class_enumeration_signed_mapping_as_mapping_const(s_mapping
);
216 s_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(s_mapping
);
217 ranges
= bt_integer_range_set_signed_as_range_set_const(s_ranges
);
220 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(ir_fc
, i
);
221 mapping
= bt_field_class_enumeration_unsigned_mapping_as_mapping_const(u_mapping
);
223 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(u_mapping
);
224 ranges
= bt_integer_range_set_unsigned_as_range_set_const(u_ranges
);
227 label
= bt_field_class_enumeration_mapping_get_label(mapping
);
228 range_count
= bt_integer_range_set_get_range_count(ranges
);
230 for (range_i
= 0; range_i
< range_count
; range_i
++) {
232 g_string_append(ctx
->tsdl
, "\"");
233 append_quoted_string_content(ctx
, label
);
234 g_string_append(ctx
->tsdl
, "\" = ");
237 const bt_integer_range_signed
*range
;
238 int64_t lower
, upper
;
241 bt_integer_range_set_signed_borrow_range_by_index_const(s_ranges
, range_i
);
242 lower
= bt_integer_range_signed_get_lower(range
);
243 upper
= bt_integer_range_signed_get_upper(range
);
245 if (lower
== upper
) {
246 g_string_append_printf(ctx
->tsdl
, "%" PRId64
, lower
);
248 g_string_append_printf(ctx
->tsdl
, "%" PRId64
" ... %" PRId64
, lower
, upper
);
251 const bt_integer_range_unsigned
*range
;
252 uint64_t lower
, upper
;
254 range
= bt_integer_range_set_unsigned_borrow_range_by_index_const(u_ranges
,
256 lower
= bt_integer_range_unsigned_get_lower(range
);
257 upper
= bt_integer_range_unsigned_get_upper(range
);
259 if (lower
== upper
) {
260 g_string_append_printf(ctx
->tsdl
, "%" PRIu64
, lower
);
262 g_string_append_printf(ctx
->tsdl
, "%" PRIu64
" ... %" PRIu64
, lower
, upper
);
266 g_string_append(ctx
->tsdl
, ",\n");
270 append_end_block(ctx
);
274 static void append_float_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class_float
*fc
)
276 unsigned int mant_dig
, exp_dig
;
278 if (bt_field_class_get_type(fc
->base
.base
.ir_fc
) == BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
) {
286 g_string_append_printf(ctx
->tsdl
, "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
287 mant_dig
, exp_dig
, fc
->base
.base
.alignment
);
290 static void append_string_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class_string
*)
292 g_string_append(ctx
->tsdl
, "string { encoding = UTF8; }");
295 static void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
);
297 static void append_member(struct ctx
*ctx
, const char *name
, struct fs_sink_ctf_field_class
*fc
)
299 GString
*lengths
= NULL
;
300 const char *lengths_str
= "";
304 while (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
||
305 fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
307 lengths
= g_string_new(NULL
);
311 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
) {
312 struct fs_sink_ctf_field_class_array
*array_fc
= fs_sink_ctf_field_class_as_array(fc
);
314 g_string_append_printf(lengths
, "[%" PRIu64
"]", array_fc
->length
);
315 fc
= array_fc
->base
.elem_fc
;
317 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
318 fs_sink_ctf_field_class_as_sequence(fc
);
320 g_string_append_printf(lengths
, "[%s]", seq_fc
->length_ref
->str
);
321 fc
= seq_fc
->base
.elem_fc
;
325 append_field_class(ctx
, fc
);
328 lengths_str
= lengths
->str
;
331 g_string_append_printf(ctx
->tsdl
, " %s%s;\n", name
, lengths_str
);
334 g_string_free(lengths
, TRUE
);
338 static void append_struct_field_class_members(struct ctx
*ctx
,
339 struct fs_sink_ctf_field_class_struct
*struct_fc
)
343 for (i
= 0; i
< struct_fc
->members
->len
; i
++) {
344 struct fs_sink_ctf_named_field_class
*named_fc
=
345 fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
346 struct fs_sink_ctf_field_class
*fc
= named_fc
->fc
;
349 * For sequence, option, and variant field classes, if
350 * the length/tag field class is generated before, write
351 * it now before the dependent field class.
353 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
354 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
355 fs_sink_ctf_field_class_as_sequence(fc
);
357 if (seq_fc
->length_is_before
) {
359 append_integer_field_class_from_props(
360 ctx
, 32, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
,
361 seq_fc
->length_ref
->str
, true);
363 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
) {
364 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
367 * CTF 1.8 does not support the option field
368 * class type. To write something anyway, this
369 * component translates this type to a variant
370 * field class where the options are:
372 * * An empty structure field class.
373 * * The optional field class itself.
375 * The "tag" is always generated/before in that
376 * case (an 8-bit unsigned enumeration field
380 g_string_append(ctx
->tsdl
, "/* The enumeration and variant field classes "
381 "below were a trace IR option field class. */\n");
383 g_string_append(ctx
->tsdl
, "enum : ");
384 append_integer_field_class_from_props(
385 ctx
, 8, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
, NULL
,
387 g_string_append(ctx
->tsdl
, " {\n");
390 g_string_append(ctx
->tsdl
, "none = 0,\n");
392 g_string_append(ctx
->tsdl
, "content = 1,\n");
393 append_end_block(ctx
);
394 g_string_append_printf(ctx
->tsdl
, " %s;\n", opt_fc
->tag_ref
->str
);
395 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
) {
396 struct fs_sink_ctf_field_class_variant
*var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
398 if (var_fc
->tag_is_before
) {
400 g_string_append(ctx
->tsdl
, "enum : ");
401 append_integer_field_class_from_props(
402 ctx
, 16, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
,
404 g_string_append(ctx
->tsdl
, " {\n");
407 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
408 struct fs_sink_ctf_named_field_class
*option_named_fc
=
409 fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
412 g_string_append_printf(ctx
->tsdl
, "\"%s\" = %" PRIu64
",\n",
413 option_named_fc
->name
->str
, i
);
416 append_end_block(ctx
);
417 g_string_append_printf(ctx
->tsdl
, " %s;\n", var_fc
->tag_ref
->str
);
419 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
) {
423 "/* The integer field class below was a trace IR boolean field class. */\n");
424 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
) {
428 "/* The integer field class below was a trace IR bit array field class. */\n");
432 append_member(ctx
, named_fc
->name
->str
, fc
);
436 static void append_struct_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class_struct
*fc
)
438 g_string_append(ctx
->tsdl
, "struct {\n");
440 append_struct_field_class_members(ctx
, fc
);
441 append_end_block(ctx
);
442 g_string_append_printf(ctx
->tsdl
, " align(%u)", fc
->base
.alignment
);
445 static void append_option_field_class(struct ctx
*ctx
,
446 struct fs_sink_ctf_field_class_option
*opt_fc
)
448 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n", opt_fc
->tag_ref
->str
);
451 g_string_append(ctx
->tsdl
, "struct { } none;\n");
453 append_member(ctx
, "content", opt_fc
->content_fc
);
454 append_end_block(ctx
);
457 static void append_variant_field_class(struct ctx
*ctx
,
458 struct fs_sink_ctf_field_class_variant
*var_fc
)
462 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n", var_fc
->tag_ref
->str
);
465 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
466 struct fs_sink_ctf_named_field_class
*named_fc
=
467 fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
470 append_member(ctx
, named_fc
->name
->str
, named_fc
->fc
);
473 append_end_block(ctx
);
476 static void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
)
479 case FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
:
480 append_bool_field_class(ctx
, fs_sink_ctf_field_class_as_bool(fc
));
482 case FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
:
483 append_bit_array_field_class(ctx
, fs_sink_ctf_field_class_as_bit_array(fc
));
485 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT
:
486 append_integer_field_class(ctx
, fs_sink_ctf_field_class_as_int(fc
));
488 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT
:
489 append_float_field_class(ctx
, fs_sink_ctf_field_class_as_float(fc
));
491 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING
:
492 append_string_field_class(ctx
, fs_sink_ctf_field_class_as_string(fc
));
494 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
495 append_struct_field_class(ctx
, fs_sink_ctf_field_class_as_struct(fc
));
497 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
498 append_option_field_class(ctx
, fs_sink_ctf_field_class_as_option(fc
));
500 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
501 append_variant_field_class(ctx
, fs_sink_ctf_field_class_as_variant(fc
));
508 static void append_event_class(struct ctx
*ctx
, struct fs_sink_ctf_event_class
*ec
)
511 bt_event_class_log_level log_level
;
515 g_string_append(ctx
->tsdl
, "event {\n");
518 /* Event class properties */
520 g_string_append(ctx
->tsdl
, "name = ");
521 str
= bt_event_class_get_name(ec
->ir_ec
);
526 append_quoted_string(ctx
, str
);
527 g_string_append(ctx
->tsdl
, ";\n");
529 g_string_append_printf(ctx
->tsdl
, "stream_id = %" PRIu64
";\n",
530 bt_stream_class_get_id(ec
->sc
->ir_sc
));
532 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n", bt_event_class_get_id(ec
->ir_ec
));
534 str
= bt_event_class_get_emf_uri(ec
->ir_ec
);
537 g_string_append(ctx
->tsdl
, "model.emf.uri = ");
538 append_quoted_string(ctx
, str
);
539 g_string_append(ctx
->tsdl
, ";\n");
542 if (bt_event_class_get_log_level(ec
->ir_ec
, &log_level
) == BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
546 g_string_append(ctx
->tsdl
, "loglevel = ");
549 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
552 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
555 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
558 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
561 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
564 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
567 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
570 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
573 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
576 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
579 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
582 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
585 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
588 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
591 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
598 g_string_append_printf(ctx
->tsdl
, "%u;\n", level
);
601 /* Event specific context field class */
602 if (ec
->spec_context_fc
) {
604 g_string_append(ctx
->tsdl
, "context := ");
605 append_field_class(ctx
, ec
->spec_context_fc
);
606 g_string_append(ctx
->tsdl
, ";\n");
609 /* Event payload field class */
610 if (ec
->payload_fc
) {
612 g_string_append(ctx
->tsdl
, "fields := ");
613 append_field_class(ctx
, ec
->payload_fc
);
614 g_string_append(ctx
->tsdl
, ";\n");
617 append_end_block_semi_nl_nl(ctx
);
620 static void append_stream_class(struct ctx
*ctx
, struct fs_sink_ctf_stream_class
*sc
)
624 /* Default clock class */
625 if (sc
->default_clock_class
) {
627 int64_t offset_seconds
;
628 uint64_t offset_cycles
;
632 g_string_append(ctx
->tsdl
, "clock {\n");
634 BT_ASSERT(sc
->default_clock_class_name
->len
> 0);
636 g_string_append_printf(ctx
->tsdl
, "name = %s;\n", sc
->default_clock_class_name
->str
);
637 descr
= bt_clock_class_get_description(sc
->default_clock_class
);
640 g_string_append(ctx
->tsdl
, "description = ");
641 append_quoted_string(ctx
, descr
);
642 g_string_append(ctx
->tsdl
, ";\n");
646 g_string_append_printf(ctx
->tsdl
, "freq = %" PRIu64
";\n",
647 bt_clock_class_get_frequency(sc
->default_clock_class
));
649 g_string_append_printf(ctx
->tsdl
, "precision = %" PRIu64
";\n",
650 bt_clock_class_get_precision(sc
->default_clock_class
));
651 bt_clock_class_get_offset(sc
->default_clock_class
, &offset_seconds
, &offset_cycles
);
653 g_string_append_printf(ctx
->tsdl
, "offset_s = %" PRId64
";\n", offset_seconds
);
655 g_string_append_printf(ctx
->tsdl
, "offset = %" PRIu64
";\n", offset_cycles
);
657 g_string_append(ctx
->tsdl
, "absolute = ");
659 if (bt_clock_class_origin_is_unix_epoch(sc
->default_clock_class
)) {
660 g_string_append(ctx
->tsdl
, "true");
662 g_string_append(ctx
->tsdl
, "false");
665 g_string_append(ctx
->tsdl
, ";\n");
666 uuid
= bt_clock_class_get_uuid(sc
->default_clock_class
);
669 g_string_append(ctx
->tsdl
, "uuid = ");
670 append_uuid(ctx
, uuid
);
671 g_string_append(ctx
->tsdl
, ";\n");
674 /* End clock class */
675 append_end_block_semi_nl_nl(ctx
);
680 g_string_append(ctx
->tsdl
, "stream {\n");
683 /* Stream class properties */
685 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n", bt_stream_class_get_id(sc
->ir_sc
));
687 /* Packet context field class */
689 g_string_append(ctx
->tsdl
, "packet.context := struct {\n");
692 append_integer_field_class_from_props(ctx
, 64, 8, false,
693 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
694 NULL
, "packet_size", true);
696 append_integer_field_class_from_props(ctx
, 64, 8, false,
697 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
698 NULL
, "content_size", true);
700 if (sc
->packets_have_ts_begin
) {
702 append_integer_field_class_from_props(
703 ctx
, 64, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
704 sc
->default_clock_class_name
->str
, "timestamp_begin", true);
707 if (sc
->packets_have_ts_end
) {
709 append_integer_field_class_from_props(
710 ctx
, 64, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
711 sc
->default_clock_class_name
->str
, "timestamp_end", true);
714 if (sc
->has_discarded_events
) {
716 append_integer_field_class_from_props(ctx
, 64, 8, false,
717 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
718 NULL
, "events_discarded", true);
722 * Unconditionnally write the packet sequence number as, even if
723 * there's no possible discarded packets message, it's still
724 * useful information to have.
727 append_integer_field_class_from_props(ctx
, 64, 8, false,
728 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
729 NULL
, "packet_seq_num", true);
731 if (sc
->packet_context_fc
) {
732 append_struct_field_class_members(ctx
,
733 fs_sink_ctf_field_class_as_struct(sc
->packet_context_fc
));
734 fs_sink_ctf_field_class_struct_align_at_least(
735 fs_sink_ctf_field_class_as_struct(sc
->packet_context_fc
), 8);
738 /* End packet context field class */
739 append_end_block(ctx
);
740 g_string_append_printf(ctx
->tsdl
, " align(%u);\n\n",
741 sc
->packet_context_fc
? sc
->packet_context_fc
->alignment
: 8);
743 /* Event header field class */
745 g_string_append(ctx
->tsdl
, "event.header := struct {\n");
748 append_integer_field_class_from_props(
749 ctx
, 64, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
, "id", true);
751 if (sc
->default_clock_class
) {
753 append_integer_field_class_from_props(ctx
, 64, 8, false,
754 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
755 sc
->default_clock_class_name
->str
, "timestamp", true);
758 /* End event header field class */
759 append_end_block(ctx
);
760 g_string_append(ctx
->tsdl
, " align(8);\n");
762 /* Event common context field class */
763 if (sc
->event_common_context_fc
) {
765 g_string_append(ctx
->tsdl
, "event.context := ");
766 append_field_class(ctx
, sc
->event_common_context_fc
);
767 g_string_append(ctx
->tsdl
, ";\n");
770 /* End stream class */
771 append_end_block_semi_nl_nl(ctx
);
774 for (i
= 0; i
< sc
->event_classes
->len
; i
++) {
775 append_event_class(ctx
, (fs_sink_ctf_event_class
*) sc
->event_classes
->pdata
[i
]);
779 void translate_trace_ctf_ir_to_tsdl(struct fs_sink_ctf_trace
*trace
, GString
*tsdl
)
788 g_string_assign(tsdl
, "/* CTF 1.8 */\n\n");
789 g_string_append(tsdl
, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
793 g_string_append(tsdl
, "trace {\n");
796 /* Trace class properties */
798 g_string_append(tsdl
, "major = 1;\n");
800 g_string_append(tsdl
, "minor = 8;\n");
802 g_string_append(tsdl
, "uuid = ");
803 append_uuid(&ctx
, trace
->uuid
);
804 g_string_append(tsdl
, ";\n");
806 g_string_append(tsdl
, "byte_order = ");
808 if (BYTE_ORDER
== LITTLE_ENDIAN
) {
809 g_string_append(tsdl
, "le");
811 g_string_append(tsdl
, "be");
814 g_string_append(tsdl
, ";\n");
816 /* Packet header field class */
818 g_string_append(tsdl
, "packet.header := struct {\n");
821 append_integer_field_class_from_props(&ctx
, 32, 8, false,
822 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
823 NULL
, "magic", true);
825 append_integer_field_class_from_props(&ctx
, 8, 8, false,
826 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
827 NULL
, "uuid[16]", true);
829 append_integer_field_class_from_props(&ctx
, 64, 8, false,
830 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
831 NULL
, "stream_id", true);
833 append_integer_field_class_from_props(&ctx
, 64, 8, false,
834 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
835 NULL
, "stream_instance_id", true);
837 /* End packet header field class */
838 append_end_block(&ctx
);
839 g_string_append(ctx
.tsdl
, " align(8);\n");
841 /* End trace class */
842 append_end_block_semi_nl_nl(&ctx
);
844 /* Trace environment */
845 count
= bt_trace_get_environment_entry_count(trace
->ir_trace
);
848 g_string_append(tsdl
, "env {\n");
851 for (i
= 0; i
< count
; i
++) {
855 bt_trace_borrow_environment_entry_by_index_const(trace
->ir_trace
, i
, &name
, &val
);
857 g_string_append_printf(tsdl
, "%s = ", name
);
859 switch (bt_value_get_type(val
)) {
860 case BT_VALUE_TYPE_SIGNED_INTEGER
:
861 g_string_append_printf(tsdl
, "%" PRId64
, bt_value_integer_signed_get(val
));
863 case BT_VALUE_TYPE_STRING
:
864 append_quoted_string(&ctx
, bt_value_string_get(val
));
869 * translate_trace_trace_ir_to_ctf_ir().
874 g_string_append(tsdl
, ";\n");
877 /* End trace class environment */
878 append_end_block_semi_nl_nl(&ctx
);
881 /* Stream classes and their event classes */
882 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
883 append_stream_class(&ctx
, (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
]);