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_COMP_LOG_SELF_COMP (ctx->self_comp)
24 #define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
25 #define BT_LOG_TAG "PLUGIN/SINK.CTF.FS/TRANSLATE-TRACE-IR-TO-CTF-IR"
26 #include "plugins/comp-logging.h"
28 #include <babeltrace2/babeltrace.h>
29 #include "common/macros.h"
30 #include "common/common.h"
31 #include "common/assert.h"
38 #include "fs-sink-ctf-meta.h"
40 struct field_path_elem
{
41 uint64_t index_in_parent
;
45 const bt_field_class
*ir_fc
;
48 struct fs_sink_ctf_field_class
*parent_fc
;
52 bt_logging_level log_level
;
53 bt_self_component
*self_comp
;
56 struct fs_sink_ctf_stream_class
*cur_sc
;
59 struct fs_sink_ctf_event_class
*cur_ec
;
64 * Array of `struct field_path_elem` */
69 struct field_path_elem
*cur_path_stack_at(struct ctx
*ctx
, uint64_t i
)
71 BT_ASSERT(i
< ctx
->cur_path
->len
);
72 return &g_array_index(ctx
->cur_path
, struct field_path_elem
, i
);
76 struct field_path_elem
*cur_path_stack_top(struct ctx
*ctx
)
78 BT_ASSERT(ctx
->cur_path
->len
> 0);
79 return cur_path_stack_at(ctx
, ctx
->cur_path
->len
- 1);
83 bool is_reserved_member_name(const char *name
, const char *reserved_name
)
85 bool is_reserved
= false;
87 if (strcmp(name
, reserved_name
) == 0) {
92 if (name
[0] == '_' && strcmp(&name
[1], reserved_name
) == 0) {
101 static const char *reserved_tsdl_keywords
[] = {
133 bool ist_valid_identifier(const char *name
)
137 bool ist_valid
= true;
139 /* Make sure the name is not a reserved keyword */
140 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
);
142 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
148 /* Make sure the name is not an empty string */
149 if (strlen(name
) == 0) {
154 /* Make sure the name starts with a letter or `_` */
155 if (!isalpha(name
[0]) && name
[0] != '_') {
160 /* Make sure the name only contains letters, digits, and `_` */
161 for (at
= name
; *at
!= '\0'; at
++) {
162 if (!isalnum(*at
) && *at
!= '_') {
173 bool must_protect_identifier(const char *name
)
176 bool must_protect
= false;
178 /* Protect a reserved keyword */
179 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
);
181 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
187 /* Protect an identifier which already starts with `_` */
188 if (name
[0] == '_') {
198 int cur_path_stack_push(struct ctx
*ctx
,
199 uint64_t index_in_parent
, const char *name
,
200 bool force_protect_name
, const bt_field_class
*ir_fc
,
201 struct fs_sink_ctf_field_class
*parent_fc
)
204 struct field_path_elem
*field_path_elem
;
206 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
+ 1);
207 field_path_elem
= cur_path_stack_top(ctx
);
208 field_path_elem
->index_in_parent
= index_in_parent
;
209 field_path_elem
->name
= g_string_new(NULL
);
212 if (force_protect_name
) {
213 g_string_assign(field_path_elem
->name
, "_");
216 g_string_append(field_path_elem
->name
, name
);
218 if (ctx
->cur_scope
== BT_SCOPE_PACKET_CONTEXT
) {
219 if (is_reserved_member_name(name
, "packet_size") ||
220 is_reserved_member_name(name
, "content_size") ||
221 is_reserved_member_name(name
, "timestamp_begin") ||
222 is_reserved_member_name(name
, "timestamp_end") ||
223 is_reserved_member_name(name
, "events_discarded") ||
224 is_reserved_member_name(name
, "packet_seq_num")) {
225 BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
226 "or variant field class option name: name=\"%s\"",
233 if (!ist_valid_identifier(field_path_elem
->name
->str
)) {
235 BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
236 "or variant field class option name: name=\"%s\"",
237 field_path_elem
->name
->str
);
242 field_path_elem
->ir_fc
= ir_fc
;
243 field_path_elem
->parent_fc
= parent_fc
;
250 void cur_path_stack_pop(struct ctx
*ctx
)
252 struct field_path_elem
*field_path_elem
;
254 BT_ASSERT(ctx
->cur_path
->len
> 0);
255 field_path_elem
= cur_path_stack_top(ctx
);
257 if (field_path_elem
->name
) {
258 g_string_free(field_path_elem
->name
, TRUE
);
259 field_path_elem
->name
= NULL
;
262 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
- 1);
266 * Creates a relative field ref (a single name) from IR field path
267 * `tgt_ir_field_path`.
269 * This function tries to locate the target field class recursively from
270 * the top to the bottom of the context's current path using only the
271 * target field class's own name. This is because many CTF reading tools
272 * do not support a relative field ref with more than one element, for
273 * example `prev_struct.len`.
275 * Returns a negative value if this resolving operation failed.
278 int create_relative_field_ref(struct ctx
*ctx
,
279 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
,
280 struct fs_sink_ctf_field_class
**user_tgt_fc
)
283 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
286 const char *tgt_fc_name
= NULL
;
287 struct field_path_elem
*field_path_elem
;
289 /* Get target field class's name */
290 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
291 case BT_SCOPE_PACKET_CONTEXT
:
292 BT_ASSERT(ctx
->cur_sc
);
293 tgt_fc
= ctx
->cur_sc
->packet_context_fc
;
295 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
296 BT_ASSERT(ctx
->cur_sc
);
297 tgt_fc
= ctx
->cur_sc
->event_common_context_fc
;
299 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
300 BT_ASSERT(ctx
->cur_ec
);
301 tgt_fc
= ctx
->cur_ec
->spec_context_fc
;
303 case BT_SCOPE_EVENT_PAYLOAD
:
304 BT_ASSERT(ctx
->cur_ec
);
305 tgt_fc
= ctx
->cur_ec
->payload_fc
;
313 while (i
< bt_field_path_get_item_count(tgt_ir_field_path
)) {
314 const bt_field_path_item
*fp_item
=
315 bt_field_path_borrow_item_by_index_const(
316 tgt_ir_field_path
, i
);
317 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
322 switch (tgt_fc
->type
) {
323 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
324 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
325 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
326 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
328 bt_field_path_item_index_get_index(fp_item
));
330 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
331 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
332 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
333 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
335 bt_field_path_item_index_get_index(fp_item
));
337 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
338 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
340 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
343 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
344 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
);
345 tgt_fc
= array_base_fc
->elem_fc
;
353 tgt_fc
= named_fc
->fc
;
354 tgt_fc_name
= named_fc
->name
->str
;
360 BT_ASSERT(tgt_fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_INT
);
361 BT_ASSERT(tgt_fc_name
);
363 /* Find target field class having this name in current context */
364 for (si
= ctx
->cur_path
->len
- 1; si
>= 0; si
--) {
365 struct fs_sink_ctf_field_class
*fc
;
366 struct fs_sink_ctf_field_class_struct
*struct_fc
;
367 struct fs_sink_ctf_field_class_variant
*var_fc
;
368 struct fs_sink_ctf_named_field_class
*named_fc
;
371 field_path_elem
= cur_path_stack_at(ctx
, (uint64_t) si
);
372 fc
= field_path_elem
->parent_fc
;
374 /* Reached stack's bottom */
380 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
381 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
383 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
384 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
387 /* Not supported by TSDL 1.8 */
392 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
393 struct_fc
= (void *) fc
;
394 len
= struct_fc
->members
->len
;
396 var_fc
= (void *) fc
;
397 len
= var_fc
->options
->len
;
400 for (i
= 0; i
< len
; i
++) {
401 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
402 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
405 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
409 if (strcmp(named_fc
->name
->str
, tgt_fc_name
) == 0) {
410 if (named_fc
->fc
== tgt_fc
) {
411 g_string_assign(tgt_field_ref
,
415 *user_tgt_fc
= tgt_fc
;
419 * Using only the target field
420 * class's name, we're not
421 * reaching the target field
422 * class. This is not supported
438 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
440 * Returns a negative value if this resolving operation failed.
443 int create_absolute_field_ref(struct ctx
*ctx
,
444 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
,
445 struct fs_sink_ctf_field_class
**user_tgt_fc
)
448 struct fs_sink_ctf_field_class
*fc
= NULL
;
451 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
452 case BT_SCOPE_PACKET_CONTEXT
:
453 BT_ASSERT(ctx
->cur_sc
);
454 fc
= ctx
->cur_sc
->packet_context_fc
;
455 g_string_assign(tgt_field_ref
, "stream.packet.context");
457 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
458 BT_ASSERT(ctx
->cur_sc
);
459 fc
= ctx
->cur_sc
->event_common_context_fc
;
460 g_string_assign(tgt_field_ref
, "stream.event.context");
462 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
463 BT_ASSERT(ctx
->cur_ec
);
464 fc
= ctx
->cur_ec
->spec_context_fc
;
465 g_string_assign(tgt_field_ref
, "event.context");
467 case BT_SCOPE_EVENT_PAYLOAD
:
468 BT_ASSERT(ctx
->cur_ec
);
469 fc
= ctx
->cur_ec
->payload_fc
;
470 g_string_assign(tgt_field_ref
, "event.fields");
478 for (i
= 0; i
< bt_field_path_get_item_count(tgt_ir_field_path
); i
++) {
479 const bt_field_path_item
*fp_item
=
480 bt_field_path_borrow_item_by_index_const(
481 tgt_ir_field_path
, i
);
482 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
484 if (bt_field_path_item_get_type(fp_item
) !=
485 BT_FIELD_PATH_ITEM_TYPE_INDEX
) {
486 /* Not supported by TSDL 1.8 */
492 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
493 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
494 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
495 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
497 bt_field_path_item_index_get_index(fp_item
));
499 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
500 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
501 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
502 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
504 bt_field_path_item_index_get_index(fp_item
));
511 g_string_append_c(tgt_field_ref
, '.');
512 g_string_append(tgt_field_ref
, named_fc
->name
->str
);
525 * Resolves a target field class located at `tgt_ir_field_path`, writing
526 * the resolved field ref to `tgt_field_ref` and setting
527 * `*create_before` according to whether or not the target field must be
528 * created immediately before (in which case `tgt_field_ref` is
532 void resolve_field_class(struct ctx
*ctx
,
533 const bt_field_path
*tgt_ir_field_path
,
534 GString
*tgt_field_ref
, bool *create_before
,
535 struct fs_sink_ctf_field_class
**user_tgt_fc
)
540 *create_before
= false;
542 if (!tgt_ir_field_path
) {
543 *create_before
= true;
547 tgt_scope
= bt_field_path_get_root_scope(tgt_ir_field_path
);
549 if (tgt_scope
== ctx
->cur_scope
) {
551 * Try, in this order:
553 * 1. Use a relative path, using only the target field
554 * class's name. This is what is the most commonly
555 * supported by popular CTF reading tools.
557 * 2. Use an absolute path. This could fail if there's
558 * an array field class from the current root's field
559 * class to the target field class.
561 * 3. Create the target field class before the
562 * requesting field class (fallback).
564 ret
= create_relative_field_ref(ctx
, tgt_ir_field_path
,
565 tgt_field_ref
, user_tgt_fc
);
567 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
,
568 tgt_field_ref
, user_tgt_fc
);
570 *create_before
= true;
576 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
,
577 tgt_field_ref
, user_tgt_fc
);
579 /* It must always work in previous scopes */
588 int translate_field_class(struct ctx
*ctx
);
591 void append_to_parent_field_class(struct ctx
*ctx
,
592 struct fs_sink_ctf_field_class
*fc
)
594 struct fs_sink_ctf_field_class
*parent_fc
=
595 cur_path_stack_top(ctx
)->parent_fc
;
597 switch (parent_fc
->type
) {
598 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
599 fs_sink_ctf_field_class_struct_append_member((void *) parent_fc
,
600 cur_path_stack_top(ctx
)->name
->str
, fc
);
602 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
603 fs_sink_ctf_field_class_variant_append_option((void *) parent_fc
,
604 cur_path_stack_top(ctx
)->name
->str
, fc
);
606 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
607 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
609 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
612 BT_ASSERT(!array_base_fc
->elem_fc
);
613 array_base_fc
->elem_fc
= fc
;
614 array_base_fc
->base
.alignment
= fc
->alignment
;
623 void update_parent_field_class_alignment(struct ctx
*ctx
,
624 unsigned int alignment
)
626 struct fs_sink_ctf_field_class
*parent_fc
=
627 cur_path_stack_top(ctx
)->parent_fc
;
629 switch (parent_fc
->type
) {
630 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
631 fs_sink_ctf_field_class_struct_align_at_least(
632 (void *) parent_fc
, alignment
);
634 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
635 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
637 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
640 array_base_fc
->base
.alignment
= alignment
;
649 int translate_structure_field_class_members(struct ctx
*ctx
,
650 struct fs_sink_ctf_field_class_struct
*struct_fc
,
651 const bt_field_class
*ir_fc
)
656 for (i
= 0; i
< bt_field_class_structure_get_member_count(ir_fc
); i
++) {
657 const bt_field_class_structure_member
*member
;
659 const bt_field_class
*memb_ir_fc
;
662 bt_field_class_structure_borrow_member_by_index_const(
664 name
= bt_field_class_structure_member_get_name(member
);
665 memb_ir_fc
= bt_field_class_structure_member_borrow_field_class_const(
667 ret
= cur_path_stack_push(ctx
, i
, name
, true, memb_ir_fc
,
670 BT_COMP_LOGE("Cannot translate structure field class member: "
671 "name=\"%s\"", name
);
675 ret
= translate_field_class(ctx
);
677 BT_COMP_LOGE("Cannot translate structure field class member: "
678 "name=\"%s\"", name
);
682 cur_path_stack_pop(ctx
);
690 int translate_structure_field_class(struct ctx
*ctx
)
693 struct fs_sink_ctf_field_class_struct
*fc
=
694 fs_sink_ctf_field_class_struct_create_empty(
695 cur_path_stack_top(ctx
)->ir_fc
,
696 cur_path_stack_top(ctx
)->index_in_parent
);
699 append_to_parent_field_class(ctx
, (void *) fc
);
700 ret
= translate_structure_field_class_members(ctx
, fc
, fc
->base
.ir_fc
);
705 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
712 * This function returns whether or not a given field class `tag_fc`
713 * is valid as the tag field class of the variant field class `fc`.
715 * CTF 1.8 requires that the tag field class be an enumeration field
716 * class and that, for each variant field class option's range set, the
717 * tag field class contains a mapping which has the option's name and an
721 bool _is_variant_field_class_tag_valid(
722 struct fs_sink_ctf_field_class_variant
*fc
,
723 struct fs_sink_ctf_field_class
*tag_fc
)
725 bool is_valid
= true;
726 bt_field_class_type ir_tag_fc_type
= bt_field_class_get_type(
729 GString
*escaped_opt_name
= g_string_new(NULL
);
731 BT_ASSERT(escaped_opt_name
);
733 if (ir_tag_fc_type
!= BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
&&
734 ir_tag_fc_type
!= BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
) {
739 for (i
= 0; i
< bt_field_class_variant_get_option_count(
740 fc
->base
.ir_fc
); i
++) {
741 const bt_field_class_variant_option
*var_opt_base
=
742 bt_field_class_variant_borrow_option_by_index_const(
744 const char *opt_name
= bt_field_class_variant_option_get_name(
748 * If the option is named `name` in trace IR, then it
749 * was _possibly_ named `_name` originally if it comes
750 * from `src.ctf.fs`. This means the corresponding
751 * enumeration field class mapping was also named
752 * `_name`, but this one didn't change, as enumeration
753 * FC mapping names are not escaped; they are literal
756 * The `sink.ctf.fs` component escapes all the variant
757 * FC option names with `_`. Therefore the
758 * _escaped name_ must match the original enumeration
761 g_string_assign(escaped_opt_name
, "_");
762 g_string_append(escaped_opt_name
, opt_name
);
764 if (ir_tag_fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
765 const bt_field_class_variant_with_unsigned_selector_option
*var_opt
=
766 bt_field_class_variant_with_unsigned_selector_borrow_option_by_index_const(
768 const bt_field_class_unsigned_enumeration_mapping
*mapping
;
769 const bt_integer_range_set_unsigned
*opt_ranges
;
770 const bt_integer_range_set_unsigned
*mapping_ranges
;
772 mapping
= bt_field_class_unsigned_enumeration_borrow_mapping_by_label_const(
773 tag_fc
->ir_fc
, escaped_opt_name
->str
);
779 opt_ranges
= bt_field_class_variant_with_unsigned_selector_option_borrow_ranges_const(
781 mapping_ranges
= bt_field_class_unsigned_enumeration_mapping_borrow_ranges_const(
783 if (!bt_integer_range_set_unsigned_compare(opt_ranges
,
789 const bt_field_class_variant_with_signed_selector_option
*var_opt
=
790 bt_field_class_variant_with_signed_selector_borrow_option_by_index_const(
792 const bt_field_class_signed_enumeration_mapping
*mapping
;
793 const bt_integer_range_set_signed
*opt_ranges
;
794 const bt_integer_range_set_signed
*mapping_ranges
;
796 mapping
= bt_field_class_signed_enumeration_borrow_mapping_by_label_const(
797 tag_fc
->ir_fc
, escaped_opt_name
->str
);
803 opt_ranges
= bt_field_class_variant_with_signed_selector_option_borrow_ranges_const(
805 mapping_ranges
= bt_field_class_signed_enumeration_mapping_borrow_ranges_const(
807 if (!bt_integer_range_set_signed_compare(opt_ranges
,
820 * This function indicates whether or not a given variant FC option name
821 * must be protected (with the `_` prefix).
823 * One of the goals of `sink.ctf.fs` is to write a CTF trace which is as
824 * close as possible to an original CTF trace as decoded by
827 * This scenario is valid in CTF 1.8:
839 * Once in trace IR, the enumeration FC mapping names and variant FC
840 * option names are kept as is. For this reason, we don't want to
841 * protect the variant FC option names here (by prepending `_`): this
842 * would make the variant FC option name and the enumeration FC mapping
845 * This scenario is also valid in CTF 1.8:
857 * Once in trace IR, the enumeration FC mapping names are kept as is,
858 * but the `_HELLO` variant FC option name becomes `HELLO` (unprotected
859 * for presentation, as recommended by CTF 1.8). When going back to
860 * TSDL, we need to protect `HELLO` so that it becomes `_HELLO` to match
861 * the corresponding enumeration FC mapping name.
863 * This scenario is also valid in CTF 1.8:
875 * Once in trace IR, the enumeration FC mapping names are kept as is,
876 * but the `__HELLO` variant FC option name becomes `_HELLO`
877 * (unprotected). When going back to TSDL, we need to protect `_HELLO`
878 * so that it becomes `__HELLO` to match the corresponding enumeration
881 * `src.ctf.fs` always uses the _same_ integer range sets for a selector
882 * FC mapping and a corresponding variant FC option. We can use that
883 * fact to find the original variant FC option names by matching variant
884 * FC options and enumeration FC mappings by range set.
887 int must_protect_variant_option_name(const bt_field_class
*ir_var_fc
,
888 const bt_field_class
*ir_tag_fc
, uint64_t opt_i
,
889 GString
*name_buf
, bool *must_protect
)
893 bt_field_class_type ir_var_fc_type
;
894 const void *opt_ranges
= NULL
;
895 const char *mapping_label
= NULL
;
896 const char *ir_opt_name
;
897 const bt_field_class_variant_option
*base_var_opt
;
898 bool force_protect
= false;
900 *must_protect
= false;
901 ir_var_fc_type
= bt_field_class_get_type(ir_var_fc
);
902 base_var_opt
= bt_field_class_variant_borrow_option_by_index_const(
904 BT_ASSERT(base_var_opt
);
905 ir_opt_name
= bt_field_class_variant_option_get_name(base_var_opt
);
906 BT_ASSERT(ir_opt_name
);
909 * Check if the variant FC option name is required to be
910 * protected (reserved TSDL keyword or starts with `_`). In that
911 * case, the name of the selector FC mapping we find must match
912 * exactly the protected name.
914 force_protect
= must_protect_identifier(ir_opt_name
);
916 *must_protect
= true;
917 g_string_assign(name_buf
, "_");
918 g_string_append(name_buf
, ir_opt_name
);
920 g_string_assign(name_buf
, ir_opt_name
);
923 /* Borrow option's ranges */
924 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR
) {
925 /* No ranges: we're done */
927 } if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
) {
928 const bt_field_class_variant_with_unsigned_selector_option
*var_opt
=
929 bt_field_class_variant_with_unsigned_selector_borrow_option_by_index_const(
932 bt_field_class_variant_with_unsigned_selector_option_borrow_ranges_const(
935 const bt_field_class_variant_with_signed_selector_option
*var_opt
=
936 bt_field_class_variant_with_signed_selector_borrow_option_by_index_const(
939 bt_field_class_variant_with_signed_selector_option_borrow_ranges_const(
943 /* Find corresponding mapping by range set in selector FC */
944 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_tag_fc
);
946 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
) {
947 const bt_field_class_enumeration_mapping
*mapping_base
;
948 const bt_field_class_unsigned_enumeration_mapping
*mapping
;
949 const bt_integer_range_set_unsigned
*mapping_ranges
;
951 mapping
= bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
953 mapping_ranges
= bt_field_class_unsigned_enumeration_mapping_borrow_ranges_const(
956 if (bt_integer_range_set_unsigned_compare(opt_ranges
,
958 /* We have a winner */
960 bt_field_class_unsigned_enumeration_mapping_as_mapping_const(
963 bt_field_class_enumeration_mapping_get_label(
968 const bt_field_class_enumeration_mapping
*mapping_base
;
969 const bt_field_class_signed_enumeration_mapping
*mapping
;
970 const bt_integer_range_set_signed
*mapping_ranges
;
972 mapping
= bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
974 mapping_ranges
= bt_field_class_signed_enumeration_mapping_borrow_ranges_const(
977 if (bt_integer_range_set_signed_compare(opt_ranges
,
979 /* We have a winner */
981 bt_field_class_signed_enumeration_mapping_as_mapping_const(
984 bt_field_class_enumeration_mapping_get_label(
991 if (!mapping_label
) {
992 /* Range set not found: invalid selector for CTF 1.8 */
998 * If the enumeration FC mapping name is not the same as the
999 * variant FC option name and we didn't protect already, try
1000 * protecting the option name and check again.
1002 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
1003 if (force_protect
) {
1008 if (mapping_label
[0] == '\0') {
1013 g_string_assign(name_buf
, "_");
1014 g_string_append(name_buf
, ir_opt_name
);
1016 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
1022 * If this comes from a `src.ctf.fs` source, it looks
1023 * like the variant FC option name was initially
1024 * protected: protect it again when going back to TSDL.
1026 *must_protect
= true;
1034 int translate_variant_field_class(struct ctx
*ctx
)
1038 struct fs_sink_ctf_field_class_variant
*fc
=
1039 fs_sink_ctf_field_class_variant_create_empty(
1040 cur_path_stack_top(ctx
)->ir_fc
,
1041 cur_path_stack_top(ctx
)->index_in_parent
);
1042 bt_field_class_type ir_fc_type
;
1043 const bt_field_path
*ir_selector_field_path
= NULL
;
1044 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
1045 GString
*name_buf
= g_string_new(NULL
);
1046 bt_value
*prot_opt_names
= bt_value_array_create();
1050 BT_ASSERT(name_buf
);
1051 BT_ASSERT(prot_opt_names
);
1052 ir_fc_type
= bt_field_class_get_type(fc
->base
.ir_fc
);
1053 opt_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
1055 if (ir_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
||
1056 ir_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR
) {
1057 ir_selector_field_path
= bt_field_class_variant_with_selector_borrow_selector_field_path_const(
1059 BT_ASSERT(ir_selector_field_path
);
1062 /* Resolve tag field class before appending to parent */
1063 resolve_field_class(ctx
, ir_selector_field_path
, fc
->tag_ref
,
1064 &fc
->tag_is_before
, &tgt_fc
);
1066 if (ir_selector_field_path
&& tgt_fc
) {
1067 uint64_t mapping_count
;
1068 uint64_t option_count
;
1070 /* CTF 1.8: selector FC must be an enumeration FC */
1071 bt_field_class_type type
= bt_field_class_get_type(
1074 if (type
!= BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
&&
1075 type
!= BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
) {
1076 fc
->tag_is_before
= true;
1081 * Call must_protect_variant_option_name() for each
1082 * option below. In that case we also want selector FC
1083 * to contain as many mappings as the variant FC has
1086 mapping_count
= bt_field_class_enumeration_get_mapping_count(
1088 option_count
= bt_field_class_variant_get_option_count(
1091 if (mapping_count
!= option_count
) {
1092 fc
->tag_is_before
= true;
1097 * No compatible selector field class for CTF 1.8:
1098 * create the appropriate selector field class.
1100 fc
->tag_is_before
= true;
1105 * First pass: detect any option name clash with option name
1106 * protection. In that case, we don't fail: just create the
1107 * selector field class before the variant field class.
1109 * After this, `prot_opt_names` contains the final option names,
1110 * potentially protected if needed. They can still be invalid
1111 * TSDL identifiers however; this will be checked by
1112 * cur_path_stack_push().
1114 for (i
= 0; i
< opt_count
; i
++) {
1115 bool must_protect
= false;
1117 ret
= must_protect_variant_option_name(fc
->base
.ir_fc
,
1118 tgt_fc
->ir_fc
, i
, name_buf
, &must_protect
);
1120 fc
->tag_is_before
= true;
1123 ret
= bt_value_array_append_string_element(prot_opt_names
,
1130 for (i
= 0; i
< opt_count
; i
++) {
1132 const bt_value
*opt_name_a
=
1133 bt_value_array_borrow_element_by_index_const(
1136 for (j
= 0; j
< opt_count
; j
++) {
1137 const bt_value
*opt_name_b
;
1144 bt_value_array_borrow_element_by_index_const(
1146 if (bt_value_compare(opt_name_a
, opt_name_b
)) {
1148 * Variant FC option names are not
1149 * unique when protected.
1151 fc
->tag_is_before
= true;
1152 goto append_to_parent
;
1158 append_to_parent_field_class(ctx
, (void *) fc
);
1160 for (i
= 0; i
< opt_count
; i
++) {
1161 const bt_field_class_variant_option
*opt
;
1162 const bt_field_class
*opt_ir_fc
;
1163 const bt_value
*prot_opt_name_val
=
1164 bt_value_array_borrow_element_by_index_const(
1166 const char *prot_opt_name
= bt_value_string_get(
1169 BT_ASSERT(prot_opt_name
);
1170 opt
= bt_field_class_variant_borrow_option_by_index_const(
1172 opt_ir_fc
= bt_field_class_variant_option_borrow_field_class_const(
1176 * We don't ask cur_path_stack_push() to protect the
1177 * option name because it's already protected at this
1180 ret
= cur_path_stack_push(ctx
, i
, prot_opt_name
, false,
1181 opt_ir_fc
, (void *) fc
);
1183 BT_COMP_LOGE("Cannot translate variant field class option: "
1184 "name=\"%s\"", prot_opt_name
);
1188 ret
= translate_field_class(ctx
);
1190 BT_COMP_LOGE("Cannot translate variant field class option: "
1191 "name=\"%s\"", prot_opt_name
);
1195 cur_path_stack_pop(ctx
);
1200 g_string_free(name_buf
, TRUE
);
1203 bt_value_put_ref(prot_opt_names
);
1208 int translate_static_array_field_class(struct ctx
*ctx
)
1210 struct fs_sink_ctf_field_class_array
*fc
=
1211 fs_sink_ctf_field_class_array_create_empty(
1212 cur_path_stack_top(ctx
)->ir_fc
,
1213 cur_path_stack_top(ctx
)->index_in_parent
);
1214 const bt_field_class
*elem_ir_fc
=
1215 bt_field_class_array_borrow_element_field_class_const(
1216 fc
->base
.base
.ir_fc
);
1220 append_to_parent_field_class(ctx
, (void *) fc
);
1221 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
,
1224 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1228 ret
= translate_field_class(ctx
);
1230 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1234 cur_path_stack_pop(ctx
);
1235 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1242 int translate_dynamic_array_field_class(struct ctx
*ctx
)
1244 struct fs_sink_ctf_field_class_sequence
*fc
=
1245 fs_sink_ctf_field_class_sequence_create_empty(
1246 cur_path_stack_top(ctx
)->ir_fc
,
1247 cur_path_stack_top(ctx
)->index_in_parent
);
1248 const bt_field_class
*elem_ir_fc
=
1249 bt_field_class_array_borrow_element_field_class_const(
1250 fc
->base
.base
.ir_fc
);
1255 /* Resolve length field class before appending to parent */
1256 resolve_field_class(ctx
,
1257 bt_field_class_dynamic_array_borrow_length_field_path_const(
1258 fc
->base
.base
.ir_fc
),
1259 fc
->length_ref
, &fc
->length_is_before
, NULL
);
1261 append_to_parent_field_class(ctx
, (void *) fc
);
1262 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
,
1265 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1269 ret
= translate_field_class(ctx
);
1271 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1275 cur_path_stack_pop(ctx
);
1276 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1283 int translate_integer_field_class(struct ctx
*ctx
)
1285 struct fs_sink_ctf_field_class_int
*fc
=
1286 fs_sink_ctf_field_class_int_create(
1287 cur_path_stack_top(ctx
)->ir_fc
,
1288 cur_path_stack_top(ctx
)->index_in_parent
);
1291 append_to_parent_field_class(ctx
, (void *) fc
);
1296 int translate_real_field_class(struct ctx
*ctx
)
1298 struct fs_sink_ctf_field_class_float
*fc
=
1299 fs_sink_ctf_field_class_float_create(
1300 cur_path_stack_top(ctx
)->ir_fc
,
1301 cur_path_stack_top(ctx
)->index_in_parent
);
1304 append_to_parent_field_class(ctx
, (void *) fc
);
1309 int translate_string_field_class(struct ctx
*ctx
)
1311 struct fs_sink_ctf_field_class_string
*fc
=
1312 fs_sink_ctf_field_class_string_create(
1313 cur_path_stack_top(ctx
)->ir_fc
,
1314 cur_path_stack_top(ctx
)->index_in_parent
);
1317 append_to_parent_field_class(ctx
, (void *) fc
);
1322 * Translates a field class, recursively.
1324 * The field class's IR field class, parent field class, and index
1325 * within its parent are in the context's current path's top element
1326 * (cur_path_stack_top()).
1329 int translate_field_class(struct ctx
*ctx
)
1333 switch (bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
)) {
1334 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
1335 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
1336 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
1337 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
1338 ret
= translate_integer_field_class(ctx
);
1340 case BT_FIELD_CLASS_TYPE_REAL
:
1341 ret
= translate_real_field_class(ctx
);
1343 case BT_FIELD_CLASS_TYPE_STRING
:
1344 ret
= translate_string_field_class(ctx
);
1346 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1347 ret
= translate_structure_field_class(ctx
);
1349 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1350 ret
= translate_static_array_field_class(ctx
);
1352 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1353 ret
= translate_dynamic_array_field_class(ctx
);
1355 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR
:
1356 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
:
1357 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR
:
1358 ret
= translate_variant_field_class(ctx
);
1368 int set_field_ref(struct fs_sink_ctf_field_class
*fc
, const char *fc_name
,
1369 struct fs_sink_ctf_field_class
*parent_fc
)
1372 GString
*field_ref
= NULL
;
1374 const char *tgt_type
;
1375 struct fs_sink_ctf_field_class_struct
*parent_struct_fc
=
1378 unsigned int suffix
= 0;
1380 if (!fc_name
|| !parent_fc
||
1381 parent_fc
->type
!= FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1388 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1390 struct fs_sink_ctf_field_class_sequence
*seq_fc
= (void *) fc
;
1392 field_ref
= seq_fc
->length_ref
;
1393 is_before
= seq_fc
->length_is_before
;
1397 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1399 struct fs_sink_ctf_field_class_variant
*var_fc
= (void *) fc
;
1401 field_ref
= var_fc
->tag_ref
;
1402 is_before
= var_fc
->tag_is_before
;
1410 BT_ASSERT(field_ref
);
1416 /* Initial field ref */
1417 g_string_printf(field_ref
, "__%s_%s", fc_name
, tgt_type
);
1420 * Make sure field ref does not clash with an existing field
1421 * class name within the same parent structure field class.
1424 bool name_ok
= true;
1426 for (i
= 0; i
< parent_struct_fc
->members
->len
; i
++) {
1427 struct fs_sink_ctf_named_field_class
*named_fc
=
1428 fs_sink_ctf_field_class_struct_borrow_member_by_index(
1429 parent_struct_fc
, i
);
1431 if (strcmp(field_ref
->str
, named_fc
->name
->str
) == 0) {
1439 /* No clash: we're done */
1443 /* Append suffix and try again */
1444 g_string_printf(field_ref
, "__%s_%s_%u", fc_name
, tgt_type
,
1454 * This function recursively sets field refs of sequence and variant
1455 * field classes when they are immediately before, avoiding name clashes
1456 * with existing field class names.
1458 * It can fail at this point if, for example, a sequence field class of
1459 * which to set the length's field ref has something else than a
1460 * structure field class as its parent: in this case, there's no
1461 * location to place the length field class immediately before the
1462 * sequence field class.
1465 int set_field_refs(struct fs_sink_ctf_field_class
* const fc
,
1466 const char *fc_name
, struct fs_sink_ctf_field_class
*parent_fc
)
1469 enum fs_sink_ctf_field_class_type fc_type
;
1475 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
1476 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1480 struct fs_sink_ctf_field_class_struct
*struct_fc
;
1481 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
1482 struct fs_sink_ctf_named_field_class
*named_fc
;
1484 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1485 struct_fc
= (void *) fc
;
1486 len
= struct_fc
->members
->len
;
1488 var_fc
= (void *) fc
;
1489 len
= var_fc
->options
->len
;
1490 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1496 for (i
= 0; i
< len
; i
++) {
1497 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1498 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
1501 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
1505 ret
= set_field_refs(named_fc
->fc
, named_fc
->name
->str
,
1514 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
1515 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1517 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
1520 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
1521 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1527 ret
= set_field_refs(array_base_fc
->elem_fc
, NULL
, fc
);
1543 * This function translates a root scope trace IR field class to
1544 * a CTF IR field class.
1546 * The resulting CTF IR field class is written to `*fc` so that it
1547 * exists as the parent object's (stream class or event class) true root
1548 * field class during the recursive translation for resolving purposes.
1549 * This is also why this function creates the empty structure field
1550 * class and then calls translate_structure_field_class_members() to
1554 int translate_scope_field_class(struct ctx
*ctx
, bt_scope scope
,
1555 struct fs_sink_ctf_field_class
**fc
,
1556 const bt_field_class
*ir_fc
)
1564 BT_ASSERT(bt_field_class_get_type(ir_fc
) ==
1565 BT_FIELD_CLASS_TYPE_STRUCTURE
);
1567 *fc
= (void *) fs_sink_ctf_field_class_struct_create_empty(
1568 ir_fc
, UINT64_C(-1));
1570 ctx
->cur_scope
= scope
;
1571 BT_ASSERT(ctx
->cur_path
->len
== 0);
1572 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, ir_fc
, NULL
);
1574 BT_COMP_LOGE("Cannot translate scope structure field class: "
1579 ret
= translate_structure_field_class_members(ctx
, (void *) *fc
, ir_fc
);
1581 BT_COMP_LOGE("Cannot translate scope structure field class: "
1586 cur_path_stack_pop(ctx
);
1588 /* Set field refs for preceding targets */
1589 ret
= set_field_refs(*fc
, NULL
, NULL
);
1596 void ctx_init(struct ctx
*ctx
, struct fs_sink_comp
*fs_sink
)
1598 memset(ctx
, 0, sizeof(struct ctx
));
1599 ctx
->cur_path
= g_array_new(FALSE
, TRUE
,
1600 sizeof(struct field_path_elem
));
1601 BT_ASSERT(ctx
->cur_path
);
1602 ctx
->log_level
= fs_sink
->log_level
;
1603 ctx
->self_comp
= fs_sink
->self_comp
;
1607 void ctx_fini(struct ctx
*ctx
)
1609 if (ctx
->cur_path
) {
1610 g_array_free(ctx
->cur_path
, TRUE
);
1611 ctx
->cur_path
= NULL
;
1616 int translate_event_class(struct fs_sink_comp
*fs_sink
,
1617 struct fs_sink_ctf_stream_class
*sc
,
1618 const bt_event_class
*ir_ec
,
1619 struct fs_sink_ctf_event_class
**out_ec
)
1623 struct fs_sink_ctf_event_class
*ec
;
1628 ctx_init(&ctx
, fs_sink
);
1629 ec
= fs_sink_ctf_event_class_create(sc
, ir_ec
);
1633 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_EVENT_SPECIFIC_CONTEXT
,
1634 &ec
->spec_context_fc
,
1635 bt_event_class_borrow_specific_context_field_class_const(
1641 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_EVENT_PAYLOAD
,
1643 bt_event_class_borrow_payload_field_class_const(ir_ec
));
1655 int try_translate_event_class_trace_ir_to_ctf_ir(
1656 struct fs_sink_comp
*fs_sink
,
1657 struct fs_sink_ctf_stream_class
*sc
,
1658 const bt_event_class
*ir_ec
,
1659 struct fs_sink_ctf_event_class
**out_ec
)
1666 /* Check in hash table first */
1667 *out_ec
= g_hash_table_lookup(sc
->event_classes_from_ir
, ir_ec
);
1668 if (G_LIKELY(*out_ec
)) {
1672 ret
= translate_event_class(fs_sink
, sc
, ir_ec
, out_ec
);
1678 bool default_clock_class_name_exists(struct fs_sink_ctf_trace
*trace
,
1681 bool exists
= false;
1684 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1685 struct fs_sink_ctf_stream_class
*sc
=
1686 trace
->stream_classes
->pdata
[i
];
1688 if (sc
->default_clock_class_name
->len
== 0) {
1689 /* No default clock class */
1693 if (strcmp(sc
->default_clock_class_name
->str
, name
) == 0) {
1704 void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class
*sc
)
1706 unsigned int suffix
= 0;
1709 g_string_assign(sc
->default_clock_class_name
, "");
1710 sprintf(buf
, "default");
1712 while (default_clock_class_name_exists(sc
->trace
, buf
)) {
1713 sprintf(buf
, "default%u", suffix
);
1717 g_string_assign(sc
->default_clock_class_name
, buf
);
1721 int translate_stream_class(struct fs_sink_comp
*fs_sink
,
1722 struct fs_sink_ctf_trace
*trace
,
1723 const bt_stream_class
*ir_sc
,
1724 struct fs_sink_ctf_stream_class
**out_sc
)
1731 ctx_init(&ctx
, fs_sink
);
1732 *out_sc
= fs_sink_ctf_stream_class_create(trace
, ir_sc
);
1735 /* Set default clock class's protected name, if any */
1736 if ((*out_sc
)->default_clock_class
) {
1737 const char *name
= bt_clock_class_get_name(
1738 (*out_sc
)->default_clock_class
);
1741 /* Try original name, protected */
1742 g_string_assign((*out_sc
)->default_clock_class_name
,
1745 if (must_protect_identifier(name
)) {
1747 (*out_sc
)->default_clock_class_name
,
1751 g_string_assign((*out_sc
)->default_clock_class_name
,
1753 if (!ist_valid_identifier(
1754 (*out_sc
)->default_clock_class_name
->str
)) {
1755 /* Invalid: create a new name */
1756 make_unique_default_clock_class_name(*out_sc
);
1760 /* No name: create a name */
1761 make_unique_default_clock_class_name(*out_sc
);
1765 ctx
.cur_sc
= *out_sc
;
1766 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_PACKET_CONTEXT
,
1767 &(*out_sc
)->packet_context_fc
,
1768 bt_stream_class_borrow_packet_context_field_class_const(ir_sc
));
1773 if ((*out_sc
)->packet_context_fc
) {
1775 * Make sure the structure field class's alignment is
1776 * enough: 8 is what we use for our own special members
1777 * in the packet context.
1779 fs_sink_ctf_field_class_struct_align_at_least(
1780 (void *) (*out_sc
)->packet_context_fc
, 8);
1783 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_EVENT_COMMON_CONTEXT
,
1784 &(*out_sc
)->event_common_context_fc
,
1785 bt_stream_class_borrow_event_common_context_field_class_const(
1794 fs_sink_ctf_stream_class_destroy(*out_sc
);
1803 int try_translate_stream_class_trace_ir_to_ctf_ir(
1804 struct fs_sink_comp
*fs_sink
,
1805 struct fs_sink_ctf_trace
*trace
,
1806 const bt_stream_class
*ir_sc
,
1807 struct fs_sink_ctf_stream_class
**out_sc
)
1815 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1816 *out_sc
= trace
->stream_classes
->pdata
[i
];
1818 if ((*out_sc
)->ir_sc
== ir_sc
) {
1823 ret
= translate_stream_class(fs_sink
, trace
, ir_sc
, out_sc
);
1830 struct fs_sink_ctf_trace
*translate_trace_trace_ir_to_ctf_ir(
1831 struct fs_sink_comp
*fs_sink
, const bt_trace
*ir_trace
)
1835 struct fs_sink_ctf_trace
*trace
= NULL
;
1837 /* Check that trace's environment is TSDL-compatible */
1838 count
= bt_trace_get_environment_entry_count(ir_trace
);
1839 for (i
= 0; i
< count
; i
++) {
1841 const bt_value
*val
;
1843 bt_trace_borrow_environment_entry_by_index_const(
1844 ir_trace
, i
, &name
, &val
);
1846 if (!ist_valid_identifier(name
)) {
1847 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
,
1849 "Unsupported trace class's environment entry name: "
1850 "name=\"%s\"", name
);
1854 switch (bt_value_get_type(val
)) {
1855 case BT_VALUE_TYPE_SIGNED_INTEGER
:
1856 case BT_VALUE_TYPE_STRING
:
1859 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
,
1861 "Unsupported trace class's environment entry value type: "
1863 bt_common_value_type_string(
1864 bt_value_get_type(val
)));
1869 trace
= fs_sink_ctf_trace_create(ir_trace
);