2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
12 #include <babeltrace2/babeltrace.h>
14 #include "common/assert.h"
15 #include "common/macros.h"
16 #include "compat/endian.h"
18 #include "fs-sink-ctf-meta.hpp"
19 #include "translate-ctf-ir-to-tsdl.hpp"
23 unsigned int indent_level
;
27 static inline void append_indent(struct ctx
*ctx
)
31 for (i
= 0; i
< ctx
->indent_level
; i
++) {
32 g_string_append_c(ctx
->tsdl
, '\t');
36 static void append_uuid(struct ctx
*ctx
, bt_uuid uuid
)
38 g_string_append_printf(ctx
->tsdl
, "\"" BT_UUID_FMT
"\"", BT_UUID_FMT_VALUES(uuid
));
41 static void append_quoted_string_content(struct ctx
*ctx
, const char *str
)
45 for (ch
= str
; *ch
!= '\0'; ch
++) {
46 unsigned char uch
= (unsigned char) *ch
;
48 if (uch
< 32 || uch
>= 127) {
51 g_string_append(ctx
->tsdl
, "\\a");
54 g_string_append(ctx
->tsdl
, "\\b");
57 g_string_append(ctx
->tsdl
, "\\f");
60 g_string_append(ctx
->tsdl
, "\\n");
63 g_string_append(ctx
->tsdl
, "\\r");
66 g_string_append(ctx
->tsdl
, "\\t");
69 g_string_append(ctx
->tsdl
, "\\v");
72 g_string_append_printf(ctx
->tsdl
, "\\x%02x", (unsigned int) uch
);
75 } else if (*ch
== '"' || *ch
== '\\') {
76 g_string_append_c(ctx
->tsdl
, '\\');
77 g_string_append_c(ctx
->tsdl
, *ch
);
79 g_string_append_c(ctx
->tsdl
, *ch
);
84 static void append_quoted_string(struct ctx
*ctx
, const char *str
)
86 g_string_append_c(ctx
->tsdl
, '"');
87 append_quoted_string_content(ctx
, str
);
88 g_string_append_c(ctx
->tsdl
, '"');
91 static void append_integer_field_class_from_props(
92 struct ctx
*ctx
, unsigned int size
, unsigned int alignment
, bool is_signed
,
93 bt_field_class_integer_preferred_display_base disp_base
, const char *mapped_clock_class_name
,
94 const char *field_name
, bool end
)
96 g_string_append_printf(ctx
->tsdl
, "integer { size = %u; align = %u;", size
, alignment
);
99 g_string_append(ctx
->tsdl
, " signed = true;");
102 if (disp_base
!= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
) {
103 g_string_append(ctx
->tsdl
, " base = ");
106 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
107 g_string_append(ctx
->tsdl
, "b");
109 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
110 g_string_append(ctx
->tsdl
, "o");
112 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
113 g_string_append(ctx
->tsdl
, "x");
119 g_string_append_c(ctx
->tsdl
, ';');
122 if (mapped_clock_class_name
) {
123 g_string_append_printf(ctx
->tsdl
, " map = clock.%s.value;", mapped_clock_class_name
);
126 g_string_append(ctx
->tsdl
, " }");
129 g_string_append_printf(ctx
->tsdl
, " %s", field_name
);
133 g_string_append(ctx
->tsdl
, ";\n");
137 static void append_end_block(struct ctx
*ctx
)
141 g_string_append(ctx
->tsdl
, "}");
144 static void append_end_block_semi_nl(struct ctx
*ctx
)
148 g_string_append(ctx
->tsdl
, "};\n");
151 static void append_end_block_semi_nl_nl(struct ctx
*ctx
)
153 append_end_block_semi_nl(ctx
);
154 g_string_append_c(ctx
->tsdl
, '\n');
157 static void append_bool_field_class(struct ctx
*ctx
,
158 __attribute__((unused
)) struct fs_sink_ctf_field_class_bool
*fc
)
161 * CTF 1.8 has no boolean field class type, so this component
162 * translates it to an 8-bit unsigned integer field class.
164 append_integer_field_class_from_props(ctx
, fc
->base
.size
, fc
->base
.base
.alignment
, false,
165 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
169 static void append_bit_array_field_class(struct ctx
*ctx
,
170 struct fs_sink_ctf_field_class_bit_array
*fc
)
173 * CTF 1.8 has no bit array field class type, so this component
174 * translates it to an unsigned integer field class with an
177 append_integer_field_class_from_props(ctx
, fc
->size
, fc
->base
.alignment
, false,
178 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
182 static void append_integer_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class_int
*fc
)
184 const bt_field_class
*ir_fc
= fc
->base
.base
.ir_fc
;
185 bt_field_class_type type
= bt_field_class_get_type(ir_fc
);
186 bool is_signed
= bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
);
188 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
189 g_string_append(ctx
->tsdl
, "enum : ");
192 append_integer_field_class_from_props(ctx
, fc
->base
.size
, fc
->base
.base
.alignment
, is_signed
,
193 bt_field_class_integer_get_preferred_display_base(ir_fc
),
196 if (bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
199 g_string_append(ctx
->tsdl
, " {\n");
202 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_fc
); i
++) {
204 const bt_field_class_enumeration_mapping
*mapping
;
205 const bt_field_class_enumeration_unsigned_mapping
*u_mapping
;
206 const bt_field_class_enumeration_signed_mapping
*s_mapping
;
207 const bt_integer_range_set
*ranges
;
208 const bt_integer_range_set_unsigned
*u_ranges
;
209 const bt_integer_range_set_signed
*s_ranges
;
210 uint64_t range_count
;
215 bt_field_class_enumeration_signed_borrow_mapping_by_index_const(ir_fc
, i
);
216 mapping
= bt_field_class_enumeration_signed_mapping_as_mapping_const(s_mapping
);
217 s_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(s_mapping
);
218 ranges
= bt_integer_range_set_signed_as_range_set_const(s_ranges
);
221 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(ir_fc
, i
);
222 mapping
= bt_field_class_enumeration_unsigned_mapping_as_mapping_const(u_mapping
);
224 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(u_mapping
);
225 ranges
= bt_integer_range_set_unsigned_as_range_set_const(u_ranges
);
228 label
= bt_field_class_enumeration_mapping_get_label(mapping
);
229 range_count
= bt_integer_range_set_get_range_count(ranges
);
231 for (range_i
= 0; range_i
< range_count
; range_i
++) {
233 g_string_append(ctx
->tsdl
, "\"");
234 append_quoted_string_content(ctx
, label
);
235 g_string_append(ctx
->tsdl
, "\" = ");
238 const bt_integer_range_signed
*range
;
239 int64_t lower
, upper
;
242 bt_integer_range_set_signed_borrow_range_by_index_const(s_ranges
, range_i
);
243 lower
= bt_integer_range_signed_get_lower(range
);
244 upper
= bt_integer_range_signed_get_upper(range
);
246 if (lower
== upper
) {
247 g_string_append_printf(ctx
->tsdl
, "%" PRId64
, lower
);
249 g_string_append_printf(ctx
->tsdl
, "%" PRId64
" ... %" PRId64
, lower
, upper
);
252 const bt_integer_range_unsigned
*range
;
253 uint64_t lower
, upper
;
255 range
= bt_integer_range_set_unsigned_borrow_range_by_index_const(u_ranges
,
257 lower
= bt_integer_range_unsigned_get_lower(range
);
258 upper
= bt_integer_range_unsigned_get_upper(range
);
260 if (lower
== upper
) {
261 g_string_append_printf(ctx
->tsdl
, "%" PRIu64
, lower
);
263 g_string_append_printf(ctx
->tsdl
, "%" PRIu64
" ... %" PRIu64
, lower
, upper
);
267 g_string_append(ctx
->tsdl
, ",\n");
271 append_end_block(ctx
);
275 static void append_float_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class_float
*fc
)
277 unsigned int mant_dig
, exp_dig
;
279 if (bt_field_class_get_type(fc
->base
.base
.ir_fc
) == BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
) {
287 g_string_append_printf(ctx
->tsdl
, "floating_point { mant_dig = %u; exp_dig = %u; align = %u; }",
288 mant_dig
, exp_dig
, fc
->base
.base
.alignment
);
291 static void append_string_field_class(struct ctx
*ctx
)
293 g_string_append(ctx
->tsdl
, "string { encoding = UTF8; }");
296 static void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
);
298 static void append_member(struct ctx
*ctx
, const char *name
, struct fs_sink_ctf_field_class
*fc
)
300 GString
*lengths
= NULL
;
301 const char *lengths_str
= "";
305 while (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
||
306 fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
308 lengths
= g_string_new(NULL
);
312 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
) {
313 struct fs_sink_ctf_field_class_array
*array_fc
= fs_sink_ctf_field_class_as_array(fc
);
315 g_string_append_printf(lengths
, "[%" PRIu64
"]", array_fc
->length
);
316 fc
= array_fc
->base
.elem_fc
;
318 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
319 fs_sink_ctf_field_class_as_sequence(fc
);
321 g_string_append_printf(lengths
, "[%s]", seq_fc
->length_ref
->str
);
322 fc
= seq_fc
->base
.elem_fc
;
326 append_field_class(ctx
, fc
);
329 lengths_str
= lengths
->str
;
332 g_string_append_printf(ctx
->tsdl
, " %s%s;\n", name
, lengths_str
);
335 g_string_free(lengths
, TRUE
);
339 static void append_struct_field_class_members(struct ctx
*ctx
,
340 struct fs_sink_ctf_field_class_struct
*struct_fc
)
344 for (i
= 0; i
< struct_fc
->members
->len
; i
++) {
345 struct fs_sink_ctf_named_field_class
*named_fc
=
346 fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
347 struct fs_sink_ctf_field_class
*fc
= named_fc
->fc
;
350 * For sequence, option, and variant field classes, if
351 * the length/tag field class is generated before, write
352 * it now before the dependent field class.
354 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
355 struct fs_sink_ctf_field_class_sequence
*seq_fc
=
356 fs_sink_ctf_field_class_as_sequence(fc
);
358 if (seq_fc
->length_is_before
) {
360 append_integer_field_class_from_props(
361 ctx
, 32, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
,
362 seq_fc
->length_ref
->str
, true);
364 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
) {
365 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
368 * CTF 1.8 does not support the option field
369 * class type. To write something anyway, this
370 * component translates this type to a variant
371 * field class where the options are:
373 * * An empty structure field class.
374 * * The optional field class itself.
376 * The "tag" is always generated/before in that
377 * case (an 8-bit unsigned enumeration field
381 g_string_append(ctx
->tsdl
, "/* The enumeration and variant field classes "
382 "below were a trace IR option field class. */\n");
384 g_string_append(ctx
->tsdl
, "enum : ");
385 append_integer_field_class_from_props(
386 ctx
, 8, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
, NULL
,
388 g_string_append(ctx
->tsdl
, " {\n");
391 g_string_append(ctx
->tsdl
, "none = 0,\n");
393 g_string_append(ctx
->tsdl
, "content = 1,\n");
394 append_end_block(ctx
);
395 g_string_append_printf(ctx
->tsdl
, " %s;\n", opt_fc
->tag_ref
->str
);
396 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
) {
397 struct fs_sink_ctf_field_class_variant
*var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
399 if (var_fc
->tag_is_before
) {
401 g_string_append(ctx
->tsdl
, "enum : ");
402 append_integer_field_class_from_props(
403 ctx
, 16, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
,
405 g_string_append(ctx
->tsdl
, " {\n");
408 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
409 struct fs_sink_ctf_named_field_class
*option_named_fc
=
410 fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
413 g_string_append_printf(ctx
->tsdl
, "\"%s\" = %" PRIu64
",\n",
414 option_named_fc
->name
->str
, i
);
417 append_end_block(ctx
);
418 g_string_append_printf(ctx
->tsdl
, " %s;\n", var_fc
->tag_ref
->str
);
420 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
) {
424 "/* The integer field class below was a trace IR boolean field class. */\n");
425 } else if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
) {
429 "/* The integer field class below was a trace IR bit array field class. */\n");
433 append_member(ctx
, named_fc
->name
->str
, fc
);
437 static void append_struct_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class_struct
*fc
)
439 g_string_append(ctx
->tsdl
, "struct {\n");
441 append_struct_field_class_members(ctx
, fc
);
442 append_end_block(ctx
);
443 g_string_append_printf(ctx
->tsdl
, " align(%u)", fc
->base
.alignment
);
446 static void append_option_field_class(struct ctx
*ctx
,
447 struct fs_sink_ctf_field_class_option
*opt_fc
)
449 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n", opt_fc
->tag_ref
->str
);
452 g_string_append(ctx
->tsdl
, "struct { } none;\n");
454 append_member(ctx
, "content", opt_fc
->content_fc
);
455 append_end_block(ctx
);
458 static void append_variant_field_class(struct ctx
*ctx
,
459 struct fs_sink_ctf_field_class_variant
*var_fc
)
463 g_string_append_printf(ctx
->tsdl
, "variant <%s> {\n", var_fc
->tag_ref
->str
);
466 for (i
= 0; i
< var_fc
->options
->len
; i
++) {
467 struct fs_sink_ctf_named_field_class
*named_fc
=
468 fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
471 append_member(ctx
, named_fc
->name
->str
, named_fc
->fc
);
474 append_end_block(ctx
);
477 static void append_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
)
480 case FS_SINK_CTF_FIELD_CLASS_TYPE_BOOL
:
481 append_bool_field_class(ctx
, fs_sink_ctf_field_class_as_bool(fc
));
483 case FS_SINK_CTF_FIELD_CLASS_TYPE_BIT_ARRAY
:
484 append_bit_array_field_class(ctx
, fs_sink_ctf_field_class_as_bit_array(fc
));
486 case FS_SINK_CTF_FIELD_CLASS_TYPE_INT
:
487 append_integer_field_class(ctx
, fs_sink_ctf_field_class_as_int(fc
));
489 case FS_SINK_CTF_FIELD_CLASS_TYPE_FLOAT
:
490 append_float_field_class(ctx
, fs_sink_ctf_field_class_as_float(fc
));
492 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRING
:
493 append_string_field_class(ctx
);
495 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
496 append_struct_field_class(ctx
, fs_sink_ctf_field_class_as_struct(fc
));
498 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
499 append_option_field_class(ctx
, fs_sink_ctf_field_class_as_option(fc
));
501 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
502 append_variant_field_class(ctx
, fs_sink_ctf_field_class_as_variant(fc
));
509 static void append_event_class(struct ctx
*ctx
, struct fs_sink_ctf_event_class
*ec
)
512 bt_event_class_log_level log_level
;
516 g_string_append(ctx
->tsdl
, "event {\n");
519 /* Event class properties */
521 g_string_append(ctx
->tsdl
, "name = ");
522 str
= bt_event_class_get_name(ec
->ir_ec
);
527 append_quoted_string(ctx
, str
);
528 g_string_append(ctx
->tsdl
, ";\n");
530 g_string_append_printf(ctx
->tsdl
, "stream_id = %" PRIu64
";\n",
531 bt_stream_class_get_id(ec
->sc
->ir_sc
));
533 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n", bt_event_class_get_id(ec
->ir_ec
));
535 str
= bt_event_class_get_emf_uri(ec
->ir_ec
);
538 g_string_append(ctx
->tsdl
, "model.emf.uri = ");
539 append_quoted_string(ctx
, str
);
540 g_string_append(ctx
->tsdl
, ";\n");
543 if (bt_event_class_get_log_level(ec
->ir_ec
, &log_level
) == BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
547 g_string_append(ctx
->tsdl
, "loglevel = ");
550 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
553 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
556 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
559 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
562 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
565 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
568 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
571 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
574 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
577 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
580 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
583 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
586 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
589 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
592 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
599 g_string_append_printf(ctx
->tsdl
, "%u;\n", level
);
602 /* Event specific context field class */
603 if (ec
->spec_context_fc
) {
605 g_string_append(ctx
->tsdl
, "context := ");
606 append_field_class(ctx
, ec
->spec_context_fc
);
607 g_string_append(ctx
->tsdl
, ";\n");
610 /* Event payload field class */
611 if (ec
->payload_fc
) {
613 g_string_append(ctx
->tsdl
, "fields := ");
614 append_field_class(ctx
, ec
->payload_fc
);
615 g_string_append(ctx
->tsdl
, ";\n");
618 append_end_block_semi_nl_nl(ctx
);
621 static void append_stream_class(struct ctx
*ctx
, struct fs_sink_ctf_stream_class
*sc
)
625 /* Default clock class */
626 if (sc
->default_clock_class
) {
628 int64_t offset_seconds
;
629 uint64_t offset_cycles
;
633 g_string_append(ctx
->tsdl
, "clock {\n");
635 BT_ASSERT(sc
->default_clock_class_name
->len
> 0);
637 g_string_append_printf(ctx
->tsdl
, "name = %s;\n", sc
->default_clock_class_name
->str
);
638 descr
= bt_clock_class_get_description(sc
->default_clock_class
);
641 g_string_append(ctx
->tsdl
, "description = ");
642 append_quoted_string(ctx
, descr
);
643 g_string_append(ctx
->tsdl
, ";\n");
647 g_string_append_printf(ctx
->tsdl
, "freq = %" PRIu64
";\n",
648 bt_clock_class_get_frequency(sc
->default_clock_class
));
650 g_string_append_printf(ctx
->tsdl
, "precision = %" PRIu64
";\n",
651 bt_clock_class_get_precision(sc
->default_clock_class
));
652 bt_clock_class_get_offset(sc
->default_clock_class
, &offset_seconds
, &offset_cycles
);
654 g_string_append_printf(ctx
->tsdl
, "offset_s = %" PRId64
";\n", offset_seconds
);
656 g_string_append_printf(ctx
->tsdl
, "offset = %" PRIu64
";\n", offset_cycles
);
658 g_string_append(ctx
->tsdl
, "absolute = ");
660 if (bt_clock_class_origin_is_unix_epoch(sc
->default_clock_class
)) {
661 g_string_append(ctx
->tsdl
, "true");
663 g_string_append(ctx
->tsdl
, "false");
666 g_string_append(ctx
->tsdl
, ";\n");
667 uuid
= bt_clock_class_get_uuid(sc
->default_clock_class
);
670 g_string_append(ctx
->tsdl
, "uuid = ");
671 append_uuid(ctx
, uuid
);
672 g_string_append(ctx
->tsdl
, ";\n");
675 /* End clock class */
676 append_end_block_semi_nl_nl(ctx
);
681 g_string_append(ctx
->tsdl
, "stream {\n");
684 /* Stream class properties */
686 g_string_append_printf(ctx
->tsdl
, "id = %" PRIu64
";\n", bt_stream_class_get_id(sc
->ir_sc
));
688 /* Packet context field class */
690 g_string_append(ctx
->tsdl
, "packet.context := struct {\n");
693 append_integer_field_class_from_props(ctx
, 64, 8, false,
694 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
695 NULL
, "packet_size", true);
697 append_integer_field_class_from_props(ctx
, 64, 8, false,
698 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
699 NULL
, "content_size", true);
701 if (sc
->packets_have_ts_begin
) {
703 append_integer_field_class_from_props(
704 ctx
, 64, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
705 sc
->default_clock_class_name
->str
, "timestamp_begin", true);
708 if (sc
->packets_have_ts_end
) {
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_end", true);
715 if (sc
->has_discarded_events
) {
717 append_integer_field_class_from_props(ctx
, 64, 8, false,
718 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
719 NULL
, "events_discarded", true);
723 * Unconditionnally write the packet sequence number as, even if
724 * there's no possible discarded packets message, it's still
725 * useful information to have.
728 append_integer_field_class_from_props(ctx
, 64, 8, false,
729 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
730 NULL
, "packet_seq_num", true);
732 if (sc
->packet_context_fc
) {
733 append_struct_field_class_members(ctx
,
734 fs_sink_ctf_field_class_as_struct(sc
->packet_context_fc
));
735 fs_sink_ctf_field_class_struct_align_at_least(
736 fs_sink_ctf_field_class_as_struct(sc
->packet_context_fc
), 8);
739 /* End packet context field class */
740 append_end_block(ctx
);
741 g_string_append_printf(ctx
->tsdl
, " align(%u);\n\n",
742 sc
->packet_context_fc
? sc
->packet_context_fc
->alignment
: 8);
744 /* Event header field class */
746 g_string_append(ctx
->tsdl
, "event.header := struct {\n");
749 append_integer_field_class_from_props(
750 ctx
, 64, 8, false, BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
, NULL
, "id", true);
752 if (sc
->default_clock_class
) {
754 append_integer_field_class_from_props(ctx
, 64, 8, false,
755 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
756 sc
->default_clock_class_name
->str
, "timestamp", true);
759 /* End event header field class */
760 append_end_block(ctx
);
761 g_string_append(ctx
->tsdl
, " align(8);\n");
763 /* Event common context field class */
764 if (sc
->event_common_context_fc
) {
766 g_string_append(ctx
->tsdl
, "event.context := ");
767 append_field_class(ctx
, sc
->event_common_context_fc
);
768 g_string_append(ctx
->tsdl
, ";\n");
771 /* End stream class */
772 append_end_block_semi_nl_nl(ctx
);
775 for (i
= 0; i
< sc
->event_classes
->len
; i
++) {
776 append_event_class(ctx
, (fs_sink_ctf_event_class
*) sc
->event_classes
->pdata
[i
]);
780 void translate_trace_ctf_ir_to_tsdl(struct fs_sink_ctf_trace
*trace
, GString
*tsdl
)
789 g_string_assign(tsdl
, "/* CTF 1.8 */\n\n");
790 g_string_append(tsdl
, "/* This was generated by a Babeltrace `sink.ctf.fs` component. */\n\n");
794 g_string_append(tsdl
, "trace {\n");
797 /* Trace class properties */
799 g_string_append(tsdl
, "major = 1;\n");
801 g_string_append(tsdl
, "minor = 8;\n");
803 g_string_append(tsdl
, "uuid = ");
804 append_uuid(&ctx
, trace
->uuid
);
805 g_string_append(tsdl
, ";\n");
807 g_string_append(tsdl
, "byte_order = ");
809 if (BYTE_ORDER
== LITTLE_ENDIAN
) {
810 g_string_append(tsdl
, "le");
812 g_string_append(tsdl
, "be");
815 g_string_append(tsdl
, ";\n");
817 /* Packet header field class */
819 g_string_append(tsdl
, "packet.header := struct {\n");
822 append_integer_field_class_from_props(&ctx
, 32, 8, false,
823 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
,
824 NULL
, "magic", true);
826 append_integer_field_class_from_props(&ctx
, 8, 8, false,
827 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
828 NULL
, "uuid[16]", true);
830 append_integer_field_class_from_props(&ctx
, 64, 8, false,
831 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
832 NULL
, "stream_id", true);
834 append_integer_field_class_from_props(&ctx
, 64, 8, false,
835 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
,
836 NULL
, "stream_instance_id", true);
838 /* End packet header field class */
839 append_end_block(&ctx
);
840 g_string_append(ctx
.tsdl
, " align(8);\n");
842 /* End trace class */
843 append_end_block_semi_nl_nl(&ctx
);
845 /* Trace environment */
846 count
= bt_trace_get_environment_entry_count(trace
->ir_trace
);
849 g_string_append(tsdl
, "env {\n");
852 for (i
= 0; i
< count
; i
++) {
856 bt_trace_borrow_environment_entry_by_index_const(trace
->ir_trace
, i
, &name
, &val
);
858 g_string_append_printf(tsdl
, "%s = ", name
);
860 switch (bt_value_get_type(val
)) {
861 case BT_VALUE_TYPE_SIGNED_INTEGER
:
862 g_string_append_printf(tsdl
, "%" PRId64
, bt_value_integer_signed_get(val
));
864 case BT_VALUE_TYPE_STRING
:
865 append_quoted_string(&ctx
, bt_value_string_get(val
));
870 * translate_trace_trace_ir_to_ctf_ir().
875 g_string_append(tsdl
, ";\n");
878 /* End trace class environment */
879 append_end_block_semi_nl_nl(&ctx
);
882 /* Stream classes and their event classes */
883 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
884 append_stream_class(&ctx
, (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
]);