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 "logging/comp-logging.h"
28 #include "translate-trace-ir-to-ctf-ir.h"
30 #include <babeltrace2/babeltrace.h>
31 #include "common/macros.h"
32 #include "common/common.h"
33 #include "common/assert.h"
40 #include "fs-sink-ctf-meta.h"
42 struct field_path_elem
{
43 uint64_t index_in_parent
;
47 const bt_field_class
*ir_fc
;
50 struct fs_sink_ctf_field_class
*parent_fc
;
54 bt_logging_level log_level
;
55 bt_self_component
*self_comp
;
58 struct fs_sink_ctf_stream_class
*cur_sc
;
61 struct fs_sink_ctf_event_class
*cur_ec
;
63 bt_field_path_scope cur_scope
;
66 * Array of `struct field_path_elem` */
71 struct field_path_elem
*cur_path_stack_at(struct ctx
*ctx
, uint64_t i
)
73 BT_ASSERT(i
< ctx
->cur_path
->len
);
74 return &g_array_index(ctx
->cur_path
, struct field_path_elem
, i
);
78 struct field_path_elem
*cur_path_stack_top(struct ctx
*ctx
)
80 BT_ASSERT(ctx
->cur_path
->len
> 0);
81 return cur_path_stack_at(ctx
, ctx
->cur_path
->len
- 1);
85 bool is_reserved_member_name(const char *name
, const char *reserved_name
)
87 bool is_reserved
= false;
89 if (strcmp(name
, reserved_name
) == 0) {
94 if (name
[0] == '_' && strcmp(&name
[1], reserved_name
) == 0) {
103 static const char *reserved_tsdl_keywords
[] = {
135 bool ist_valid_identifier(const char *name
)
139 bool ist_valid
= true;
141 /* Make sure the name is not a reserved keyword */
142 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
);
144 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
150 /* Make sure the name is not an empty string */
151 if (strlen(name
) == 0) {
156 /* Make sure the name starts with a letter or `_` */
157 if (!isalpha((unsigned char) name
[0]) && name
[0] != '_') {
162 /* Make sure the name only contains letters, digits, and `_` */
163 for (at
= name
; *at
!= '\0'; at
++) {
164 if (!isalnum((unsigned char) *at
) && *at
!= '_') {
175 bool must_protect_identifier(const char *name
)
178 bool must_protect
= false;
180 /* Protect a reserved keyword */
181 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
);
183 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
189 /* Protect an identifier which already starts with `_` */
190 if (name
[0] == '_') {
200 int cur_path_stack_push(struct ctx
*ctx
,
201 uint64_t index_in_parent
, const char *name
,
202 bool force_protect_name
, const bt_field_class
*ir_fc
,
203 struct fs_sink_ctf_field_class
*parent_fc
)
206 struct field_path_elem
*field_path_elem
;
208 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
+ 1);
209 field_path_elem
= cur_path_stack_top(ctx
);
210 field_path_elem
->index_in_parent
= index_in_parent
;
211 field_path_elem
->name
= g_string_new(NULL
);
214 if (force_protect_name
) {
215 g_string_assign(field_path_elem
->name
, "_");
218 g_string_append(field_path_elem
->name
, name
);
220 if (ctx
->cur_scope
== BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
) {
221 if (is_reserved_member_name(name
, "packet_size") ||
222 is_reserved_member_name(name
, "content_size") ||
223 is_reserved_member_name(name
, "timestamp_begin") ||
224 is_reserved_member_name(name
, "timestamp_end") ||
225 is_reserved_member_name(name
, "events_discarded") ||
226 is_reserved_member_name(name
, "packet_seq_num")) {
227 BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
228 "or variant field class option name: name=\"%s\"",
235 if (!ist_valid_identifier(field_path_elem
->name
->str
)) {
237 BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
238 "or variant field class option name: name=\"%s\"",
239 field_path_elem
->name
->str
);
244 field_path_elem
->ir_fc
= ir_fc
;
245 field_path_elem
->parent_fc
= parent_fc
;
252 void cur_path_stack_pop(struct ctx
*ctx
)
254 struct field_path_elem
*field_path_elem
;
256 BT_ASSERT(ctx
->cur_path
->len
> 0);
257 field_path_elem
= cur_path_stack_top(ctx
);
259 if (field_path_elem
->name
) {
260 g_string_free(field_path_elem
->name
, TRUE
);
261 field_path_elem
->name
= NULL
;
264 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
- 1);
268 * Creates a relative field ref (a single name) from IR field path
269 * `tgt_ir_field_path`.
271 * This function tries to locate the target field class recursively from
272 * the top to the bottom of the context's current path using only the
273 * target field class's own name. This is because many CTF reading tools
274 * do not support a relative field ref with more than one element, for
275 * example `prev_struct.len`.
277 * Returns a negative value if this resolving operation failed.
280 int create_relative_field_ref(struct ctx
*ctx
,
281 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
,
282 struct fs_sink_ctf_field_class
**user_tgt_fc
)
285 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
288 const char *tgt_fc_name
= NULL
;
289 struct field_path_elem
*field_path_elem
;
291 /* Get target field class's name */
292 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
293 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
294 BT_ASSERT(ctx
->cur_sc
);
295 tgt_fc
= ctx
->cur_sc
->packet_context_fc
;
297 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
298 BT_ASSERT(ctx
->cur_sc
);
299 tgt_fc
= ctx
->cur_sc
->event_common_context_fc
;
301 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
302 BT_ASSERT(ctx
->cur_ec
);
303 tgt_fc
= ctx
->cur_ec
->spec_context_fc
;
305 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
306 BT_ASSERT(ctx
->cur_ec
);
307 tgt_fc
= ctx
->cur_ec
->payload_fc
;
315 while (i
< bt_field_path_get_item_count(tgt_ir_field_path
)) {
316 const bt_field_path_item
*fp_item
=
317 bt_field_path_borrow_item_by_index_const(
318 tgt_ir_field_path
, i
);
319 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
324 if (bt_field_path_item_get_type(fp_item
) ==
325 BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT
) {
326 /* Not supported by CTF 1.8 */
331 switch (tgt_fc
->type
) {
332 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
333 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
334 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
335 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
337 bt_field_path_item_index_get_index(fp_item
));
339 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
340 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
341 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
342 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
344 bt_field_path_item_index_get_index(fp_item
));
346 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
347 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
349 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
352 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
353 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
);
354 tgt_fc
= array_base_fc
->elem_fc
;
362 tgt_fc
= named_fc
->fc
;
363 tgt_fc_name
= named_fc
->name
->str
;
369 BT_ASSERT(tgt_fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_INT
);
370 BT_ASSERT(tgt_fc_name
);
372 /* Find target field class having this name in current context */
373 for (si
= ctx
->cur_path
->len
- 1; si
>= 0; si
--) {
374 struct fs_sink_ctf_field_class
*fc
;
375 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
376 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
377 struct fs_sink_ctf_named_field_class
*named_fc
;
380 field_path_elem
= cur_path_stack_at(ctx
, (uint64_t) si
);
381 fc
= field_path_elem
->parent_fc
;
383 /* Reached stack's bottom */
389 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
390 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
392 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
393 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
396 /* Not supported by TSDL 1.8 */
401 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
402 struct_fc
= (void *) fc
;
403 len
= struct_fc
->members
->len
;
405 var_fc
= (void *) fc
;
406 len
= var_fc
->options
->len
;
409 for (i
= 0; i
< len
; i
++) {
410 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
411 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
414 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
418 if (strcmp(named_fc
->name
->str
, tgt_fc_name
) == 0) {
419 if (named_fc
->fc
== tgt_fc
) {
420 g_string_assign(tgt_field_ref
,
424 *user_tgt_fc
= tgt_fc
;
428 * Using only the target field
429 * class's name, we're not
430 * reaching the target field
431 * class. This is not supported
447 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
449 * Returns a negative value if this resolving operation failed.
452 int create_absolute_field_ref(struct ctx
*ctx
,
453 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
,
454 struct fs_sink_ctf_field_class
**user_tgt_fc
)
457 struct fs_sink_ctf_field_class
*fc
= NULL
;
460 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
461 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
462 BT_ASSERT(ctx
->cur_sc
);
463 fc
= ctx
->cur_sc
->packet_context_fc
;
464 g_string_assign(tgt_field_ref
, "stream.packet.context");
466 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
467 BT_ASSERT(ctx
->cur_sc
);
468 fc
= ctx
->cur_sc
->event_common_context_fc
;
469 g_string_assign(tgt_field_ref
, "stream.event.context");
471 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
472 BT_ASSERT(ctx
->cur_ec
);
473 fc
= ctx
->cur_ec
->spec_context_fc
;
474 g_string_assign(tgt_field_ref
, "event.context");
476 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
477 BT_ASSERT(ctx
->cur_ec
);
478 fc
= ctx
->cur_ec
->payload_fc
;
479 g_string_assign(tgt_field_ref
, "event.fields");
487 for (i
= 0; i
< bt_field_path_get_item_count(tgt_ir_field_path
); i
++) {
488 const bt_field_path_item
*fp_item
=
489 bt_field_path_borrow_item_by_index_const(
490 tgt_ir_field_path
, i
);
491 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
493 if (bt_field_path_item_get_type(fp_item
) !=
494 BT_FIELD_PATH_ITEM_TYPE_INDEX
) {
495 /* Not supported by TSDL 1.8 */
501 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
502 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
503 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
504 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
506 bt_field_path_item_index_get_index(fp_item
));
508 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
509 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
510 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
511 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
513 bt_field_path_item_index_get_index(fp_item
));
520 g_string_append_c(tgt_field_ref
, '.');
521 g_string_append(tgt_field_ref
, named_fc
->name
->str
);
534 * Resolves a target field class located at `tgt_ir_field_path`, writing
535 * the resolved field ref to `tgt_field_ref` and setting
536 * `*create_before` according to whether or not the target field must be
537 * created immediately before (in which case `tgt_field_ref` is
541 void resolve_field_class(struct ctx
*ctx
,
542 const bt_field_path
*tgt_ir_field_path
,
543 GString
*tgt_field_ref
, bool *create_before
,
544 struct fs_sink_ctf_field_class
**user_tgt_fc
)
547 bt_field_path_scope tgt_scope
;
549 *create_before
= false;
551 if (!tgt_ir_field_path
) {
552 *create_before
= true;
556 tgt_scope
= bt_field_path_get_root_scope(tgt_ir_field_path
);
558 if (tgt_scope
== ctx
->cur_scope
) {
560 * Try, in this order:
562 * 1. Use a relative path, using only the target field
563 * class's name. This is what is the most commonly
564 * supported by popular CTF reading tools.
566 * 2. Use an absolute path. This could fail if there's
567 * an array field class from the current root's field
568 * class to the target field class.
570 * 3. Create the target field class before the
571 * requesting field class (fallback).
573 ret
= create_relative_field_ref(ctx
, tgt_ir_field_path
,
574 tgt_field_ref
, user_tgt_fc
);
576 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
,
577 tgt_field_ref
, user_tgt_fc
);
579 *create_before
= true;
584 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
,
585 tgt_field_ref
, user_tgt_fc
);
587 /* It must always work in previous scopes */
596 int translate_field_class(struct ctx
*ctx
);
599 void append_to_parent_field_class(struct ctx
*ctx
,
600 struct fs_sink_ctf_field_class
*fc
)
602 struct fs_sink_ctf_field_class
*parent_fc
=
603 cur_path_stack_top(ctx
)->parent_fc
;
605 switch (parent_fc
->type
) {
606 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
607 fs_sink_ctf_field_class_struct_append_member((void *) parent_fc
,
608 cur_path_stack_top(ctx
)->name
->str
, fc
);
610 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
612 struct fs_sink_ctf_field_class_option
*opt_fc
=
615 BT_ASSERT(!opt_fc
->content_fc
);
616 opt_fc
->content_fc
= fc
;
617 opt_fc
->base
.alignment
= fc
->alignment
;
620 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
621 fs_sink_ctf_field_class_variant_append_option((void *) parent_fc
,
622 cur_path_stack_top(ctx
)->name
->str
, fc
);
624 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
625 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
627 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
630 BT_ASSERT(!array_base_fc
->elem_fc
);
631 array_base_fc
->elem_fc
= fc
;
632 array_base_fc
->base
.alignment
= fc
->alignment
;
641 void update_parent_field_class_alignment(struct ctx
*ctx
,
642 unsigned int alignment
)
644 struct fs_sink_ctf_field_class
*parent_fc
=
645 cur_path_stack_top(ctx
)->parent_fc
;
647 switch (parent_fc
->type
) {
648 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
649 fs_sink_ctf_field_class_struct_align_at_least(
650 (void *) parent_fc
, alignment
);
652 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
653 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
655 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
658 array_base_fc
->base
.alignment
= alignment
;
667 int translate_structure_field_class_members(struct ctx
*ctx
,
668 struct fs_sink_ctf_field_class_struct
*struct_fc
,
669 const bt_field_class
*ir_fc
)
674 for (i
= 0; i
< bt_field_class_structure_get_member_count(ir_fc
); i
++) {
675 const bt_field_class_structure_member
*member
;
677 const bt_field_class
*memb_ir_fc
;
680 bt_field_class_structure_borrow_member_by_index_const(
682 name
= bt_field_class_structure_member_get_name(member
);
683 memb_ir_fc
= bt_field_class_structure_member_borrow_field_class_const(
685 ret
= cur_path_stack_push(ctx
, i
, name
, true, memb_ir_fc
,
688 BT_COMP_LOGE("Cannot translate structure field class member: "
689 "name=\"%s\"", name
);
693 ret
= translate_field_class(ctx
);
695 BT_COMP_LOGE("Cannot translate structure field class member: "
696 "name=\"%s\"", name
);
700 cur_path_stack_pop(ctx
);
708 int translate_structure_field_class(struct ctx
*ctx
)
711 struct fs_sink_ctf_field_class_struct
*fc
=
712 fs_sink_ctf_field_class_struct_create_empty(
713 cur_path_stack_top(ctx
)->ir_fc
,
714 cur_path_stack_top(ctx
)->index_in_parent
);
717 append_to_parent_field_class(ctx
, (void *) fc
);
718 ret
= translate_structure_field_class_members(ctx
, fc
, fc
->base
.ir_fc
);
723 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
730 * This function protects a given variant FC option name (with the `_`
731 * prefix) if required. On success, `name_buf->str` contains the variant
732 * FC option name to use (original option name or protected if
735 * One of the goals of `sink.ctf.fs` is to write a CTF trace which is as
736 * close as possible to an original CTF trace as decoded by
739 * This scenario is valid in CTF 1.8:
751 * Once in trace IR, the enumeration FC mapping names and variant FC
752 * option names are kept as is. For this reason, we don't want to
753 * protect the variant FC option names here (by prepending `_`): this
754 * would make the variant FC option name and the enumeration FC mapping
757 * This scenario is also valid in CTF 1.8:
769 * Once in trace IR, the enumeration FC mapping names are kept as is,
770 * but the `_HELLO` variant FC option name becomes `HELLO` (unprotected
771 * for presentation, as recommended by CTF 1.8). When going back to
772 * TSDL, we need to protect `HELLO` so that it becomes `_HELLO` to match
773 * the corresponding enumeration FC mapping name.
775 * This scenario is also valid in CTF 1.8:
787 * Once in trace IR, the enumeration FC mapping names are kept as is,
788 * but the `__HELLO` variant FC option name becomes `_HELLO`
789 * (unprotected). When going back to TSDL, we need to protect `_HELLO`
790 * so that it becomes `__HELLO` to match the corresponding enumeration
793 * `src.ctf.fs` always uses the _same_ integer range sets for a selector
794 * FC mapping and a corresponding variant FC option. We can use that
795 * fact to find the original variant FC option names by matching variant
796 * FC options and enumeration FC mappings by range set.
799 int maybe_protect_variant_option_name(const bt_field_class
*ir_var_fc
,
800 const bt_field_class
*ir_tag_fc
, uint64_t opt_i
,
805 bt_field_class_type ir_var_fc_type
;
806 const void *opt_ranges
= NULL
;
807 const char *mapping_label
= NULL
;
808 const char *ir_opt_name
;
809 const bt_field_class_variant_option
*base_var_opt
;
810 bool force_protect
= false;
812 ir_var_fc_type
= bt_field_class_get_type(ir_var_fc
);
813 base_var_opt
= bt_field_class_variant_borrow_option_by_index_const(
815 BT_ASSERT(base_var_opt
);
816 ir_opt_name
= bt_field_class_variant_option_get_name(base_var_opt
);
817 BT_ASSERT(ir_opt_name
);
820 * Check if the variant FC option name is required to be
821 * protected (reserved TSDL keyword or starts with `_`). In that
822 * case, the name of the selector FC mapping we find must match
823 * exactly the protected name.
825 force_protect
= must_protect_identifier(ir_opt_name
);
827 g_string_assign(name_buf
, "_");
828 g_string_append(name_buf
, ir_opt_name
);
830 g_string_assign(name_buf
, ir_opt_name
);
833 /* Borrow option's ranges */
834 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
) {
835 /* No ranges: we're done */
837 } if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
838 const bt_field_class_variant_with_selector_field_integer_unsigned_option
*var_opt
=
839 bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const(
842 bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
845 const bt_field_class_variant_with_selector_field_integer_signed_option
*var_opt
=
846 bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const(
849 bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const(
853 /* Find corresponding mapping by range set in selector FC */
854 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_tag_fc
);
856 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
857 const bt_field_class_enumeration_mapping
*mapping_base
;
858 const bt_field_class_enumeration_unsigned_mapping
*mapping
;
859 const bt_integer_range_set_unsigned
*mapping_ranges
;
861 mapping
= bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
863 mapping_ranges
= bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
866 if (bt_integer_range_set_unsigned_is_equal(opt_ranges
,
868 /* We have a winner */
870 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
873 bt_field_class_enumeration_mapping_get_label(
878 const bt_field_class_enumeration_mapping
*mapping_base
;
879 const bt_field_class_enumeration_signed_mapping
*mapping
;
880 const bt_integer_range_set_signed
*mapping_ranges
;
882 mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
884 mapping_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
887 if (bt_integer_range_set_signed_is_equal(opt_ranges
,
889 /* We have a winner */
891 bt_field_class_enumeration_signed_mapping_as_mapping_const(
894 bt_field_class_enumeration_mapping_get_label(
901 if (!mapping_label
) {
902 /* Range set not found: invalid selector for CTF 1.8 */
908 * If the enumeration FC mapping name is not the same as the
909 * variant FC option name and we didn't protect already, try
910 * protecting the option name and check again.
912 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
918 if (mapping_label
[0] == '\0') {
923 g_string_assign(name_buf
, "_");
924 g_string_append(name_buf
, ir_opt_name
);
926 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
937 int translate_option_field_class(struct ctx
*ctx
)
939 struct fs_sink_ctf_field_class_option
*fc
=
940 fs_sink_ctf_field_class_option_create_empty(
941 cur_path_stack_top(ctx
)->ir_fc
,
942 cur_path_stack_top(ctx
)->index_in_parent
);
943 const bt_field_class
*content_ir_fc
=
944 bt_field_class_option_borrow_field_class_const(fc
->base
.ir_fc
);
950 * CTF 1.8 does not support the option field class type. To
951 * write something anyway, this component translates this type
952 * to a variant field class where the options are:
954 * * An empty structure field class.
955 * * The optional field class itself.
957 * The "tag" is always generated/before in that case (an 8-bit
958 * unsigned enumeration field class).
960 append_to_parent_field_class(ctx
, (void *) fc
);
961 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, content_ir_fc
,
964 BT_COMP_LOGE_STR("Cannot translate option field class content.");
968 ret
= translate_field_class(ctx
);
970 BT_COMP_LOGE_STR("Cannot translate option field class content.");
974 cur_path_stack_pop(ctx
);
975 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
982 int translate_variant_field_class(struct ctx
*ctx
)
986 struct fs_sink_ctf_field_class_variant
*fc
=
987 fs_sink_ctf_field_class_variant_create_empty(
988 cur_path_stack_top(ctx
)->ir_fc
,
989 cur_path_stack_top(ctx
)->index_in_parent
);
990 bt_field_class_type ir_fc_type
;
991 const bt_field_path
*ir_selector_field_path
= NULL
;
992 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
993 GString
*name_buf
= g_string_new(NULL
);
994 bt_value
*prot_opt_names
= bt_value_array_create();
999 BT_ASSERT(prot_opt_names
);
1000 ir_fc_type
= bt_field_class_get_type(fc
->base
.ir_fc
);
1001 opt_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
1003 if (bt_field_class_type_is(ir_fc_type
,
1004 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SELECTOR_FIELD
)) {
1005 ir_selector_field_path
= bt_field_class_variant_with_selector_field_borrow_selector_field_path_const(
1007 BT_ASSERT(ir_selector_field_path
);
1010 /* Resolve tag field class before appending to parent */
1011 resolve_field_class(ctx
, ir_selector_field_path
, fc
->tag_ref
,
1012 &fc
->tag_is_before
, &tgt_fc
);
1014 if (ir_selector_field_path
&& tgt_fc
) {
1015 uint64_t mapping_count
;
1016 uint64_t option_count
;
1018 /* CTF 1.8: selector FC must be an enumeration FC */
1019 bt_field_class_type type
= bt_field_class_get_type(
1022 if (!bt_field_class_type_is(type
,
1023 BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
1024 fc
->tag_is_before
= true;
1029 * Call maybe_protect_variant_option_name() for each
1030 * option below. In that case we also want selector FC
1031 * to contain as many mappings as the variant FC has
1034 mapping_count
= bt_field_class_enumeration_get_mapping_count(
1036 option_count
= bt_field_class_variant_get_option_count(
1039 if (mapping_count
!= option_count
) {
1040 fc
->tag_is_before
= true;
1045 * No compatible selector field class for CTF 1.8:
1046 * create the appropriate selector field class.
1048 fc
->tag_is_before
= true;
1054 * First pass: detect any option name clash with option name
1055 * protection. In that case, we don't fail: just create the
1056 * selector field class before the variant field class.
1058 * After this, `prot_opt_names` contains the final option names,
1059 * potentially protected if needed. They can still be invalid
1060 * TSDL identifiers however; this will be checked by
1061 * cur_path_stack_push().
1063 for (i
= 0; i
< opt_count
; i
++) {
1064 if (!fc
->tag_is_before
) {
1065 BT_ASSERT(tgt_fc
->ir_fc
);
1066 ret
= maybe_protect_variant_option_name(fc
->base
.ir_fc
,
1067 tgt_fc
->ir_fc
, i
, name_buf
);
1069 fc
->tag_is_before
= true;
1073 ret
= bt_value_array_append_string_element(prot_opt_names
,
1080 for (i
= 0; i
< opt_count
; i
++) {
1082 const bt_value
*opt_name_a
=
1083 bt_value_array_borrow_element_by_index_const(
1086 for (j
= 0; j
< opt_count
; j
++) {
1087 const bt_value
*opt_name_b
;
1094 bt_value_array_borrow_element_by_index_const(
1096 if (bt_value_is_equal(opt_name_a
, opt_name_b
)) {
1098 * Variant FC option names are not
1099 * unique when protected.
1101 fc
->tag_is_before
= true;
1102 goto append_to_parent
;
1108 append_to_parent_field_class(ctx
, (void *) fc
);
1110 for (i
= 0; i
< opt_count
; i
++) {
1111 const bt_field_class_variant_option
*opt
;
1112 const bt_field_class
*opt_ir_fc
;
1113 const bt_value
*prot_opt_name_val
=
1114 bt_value_array_borrow_element_by_index_const(
1116 const char *prot_opt_name
= bt_value_string_get(
1119 BT_ASSERT(prot_opt_name
);
1120 opt
= bt_field_class_variant_borrow_option_by_index_const(
1122 opt_ir_fc
= bt_field_class_variant_option_borrow_field_class_const(
1126 * We don't ask cur_path_stack_push() to protect the
1127 * option name because it's already protected at this
1130 ret
= cur_path_stack_push(ctx
, i
, prot_opt_name
, false,
1131 opt_ir_fc
, (void *) fc
);
1133 BT_COMP_LOGE("Cannot translate variant field class option: "
1134 "name=\"%s\"", prot_opt_name
);
1138 ret
= translate_field_class(ctx
);
1140 BT_COMP_LOGE("Cannot translate variant field class option: "
1141 "name=\"%s\"", prot_opt_name
);
1145 cur_path_stack_pop(ctx
);
1150 g_string_free(name_buf
, TRUE
);
1153 bt_value_put_ref(prot_opt_names
);
1158 int translate_static_array_field_class(struct ctx
*ctx
)
1160 struct fs_sink_ctf_field_class_array
*fc
=
1161 fs_sink_ctf_field_class_array_create_empty(
1162 cur_path_stack_top(ctx
)->ir_fc
,
1163 cur_path_stack_top(ctx
)->index_in_parent
);
1164 const bt_field_class
*elem_ir_fc
=
1165 bt_field_class_array_borrow_element_field_class_const(
1166 fc
->base
.base
.ir_fc
);
1170 append_to_parent_field_class(ctx
, (void *) fc
);
1171 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
,
1174 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1178 ret
= translate_field_class(ctx
);
1180 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1184 cur_path_stack_pop(ctx
);
1185 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1192 int translate_dynamic_array_field_class(struct ctx
*ctx
)
1194 struct fs_sink_ctf_field_class_sequence
*fc
=
1195 fs_sink_ctf_field_class_sequence_create_empty(
1196 cur_path_stack_top(ctx
)->ir_fc
,
1197 cur_path_stack_top(ctx
)->index_in_parent
);
1198 const bt_field_class
*elem_ir_fc
=
1199 bt_field_class_array_borrow_element_field_class_const(
1200 fc
->base
.base
.ir_fc
);
1205 /* Resolve length field class before appending to parent */
1206 if (bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
) ==
1207 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
) {
1208 resolve_field_class(ctx
,
1209 bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const(
1210 fc
->base
.base
.ir_fc
),
1211 fc
->length_ref
, &fc
->length_is_before
, NULL
);
1214 append_to_parent_field_class(ctx
, (void *) fc
);
1215 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
,
1218 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1222 ret
= translate_field_class(ctx
);
1224 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1228 cur_path_stack_pop(ctx
);
1229 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1236 int translate_bool_field_class(struct ctx
*ctx
)
1238 struct fs_sink_ctf_field_class_bool
*fc
=
1239 fs_sink_ctf_field_class_bool_create(
1240 cur_path_stack_top(ctx
)->ir_fc
,
1241 cur_path_stack_top(ctx
)->index_in_parent
);
1244 append_to_parent_field_class(ctx
, (void *) fc
);
1249 int translate_bit_array_field_class(struct ctx
*ctx
)
1251 struct fs_sink_ctf_field_class_bit_array
*fc
=
1252 fs_sink_ctf_field_class_bit_array_create(
1253 cur_path_stack_top(ctx
)->ir_fc
,
1254 cur_path_stack_top(ctx
)->index_in_parent
);
1257 append_to_parent_field_class(ctx
, (void *) fc
);
1262 int translate_integer_field_class(struct ctx
*ctx
)
1264 struct fs_sink_ctf_field_class_int
*fc
=
1265 fs_sink_ctf_field_class_int_create(
1266 cur_path_stack_top(ctx
)->ir_fc
,
1267 cur_path_stack_top(ctx
)->index_in_parent
);
1270 append_to_parent_field_class(ctx
, (void *) fc
);
1275 int translate_real_field_class(struct ctx
*ctx
)
1277 struct fs_sink_ctf_field_class_float
*fc
=
1278 fs_sink_ctf_field_class_float_create(
1279 cur_path_stack_top(ctx
)->ir_fc
,
1280 cur_path_stack_top(ctx
)->index_in_parent
);
1283 append_to_parent_field_class(ctx
, (void *) fc
);
1288 int translate_string_field_class(struct ctx
*ctx
)
1290 struct fs_sink_ctf_field_class_string
*fc
=
1291 fs_sink_ctf_field_class_string_create(
1292 cur_path_stack_top(ctx
)->ir_fc
,
1293 cur_path_stack_top(ctx
)->index_in_parent
);
1296 append_to_parent_field_class(ctx
, (void *) fc
);
1301 * Translates a field class, recursively.
1303 * The field class's IR field class, parent field class, and index
1304 * within its parent are in the context's current path's top element
1305 * (cur_path_stack_top()).
1308 int translate_field_class(struct ctx
*ctx
)
1311 bt_field_class_type ir_fc_type
=
1312 bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
);
1314 if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BOOL
) {
1315 ret
= translate_bool_field_class(ctx
);
1316 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BIT_ARRAY
) {
1317 ret
= translate_bit_array_field_class(ctx
);
1318 } else if (bt_field_class_type_is(ir_fc_type
,
1319 BT_FIELD_CLASS_TYPE_INTEGER
)) {
1320 ret
= translate_integer_field_class(ctx
);
1321 } else if (bt_field_class_type_is(ir_fc_type
,
1322 BT_FIELD_CLASS_TYPE_REAL
)) {
1323 ret
= translate_real_field_class(ctx
);
1324 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRING
) {
1325 ret
= translate_string_field_class(ctx
);
1326 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRUCTURE
) {
1327 ret
= translate_structure_field_class(ctx
);
1328 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
1329 ret
= translate_static_array_field_class(ctx
);
1330 } else if (bt_field_class_type_is(ir_fc_type
,
1331 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
)) {
1332 ret
= translate_dynamic_array_field_class(ctx
);
1333 } else if (bt_field_class_type_is(ir_fc_type
,
1334 BT_FIELD_CLASS_TYPE_OPTION
)) {
1335 ret
= translate_option_field_class(ctx
);
1336 } else if (bt_field_class_type_is(ir_fc_type
,
1337 BT_FIELD_CLASS_TYPE_VARIANT
)) {
1338 ret
= translate_variant_field_class(ctx
);
1347 int set_field_ref(struct fs_sink_ctf_field_class
*fc
, const char *fc_name
,
1348 struct fs_sink_ctf_field_class
*parent_fc
)
1351 GString
*field_ref
= NULL
;
1353 const char *tgt_type
;
1354 struct fs_sink_ctf_field_class_struct
*parent_struct_fc
=
1357 unsigned int suffix
= 0;
1359 if (!fc_name
|| !parent_fc
||
1360 parent_fc
->type
!= FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1367 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1370 * CTF 1.8 does not support the option field class type.
1371 * To write something anyway, this component translates
1372 * this type to a variant field class where the options
1375 * * An empty structure field class.
1376 * * The optional field class itself.
1378 * Because the option field class becomes a CTF variant
1379 * field class, we use the term "tag" too here.
1381 * The "tag" is always generated/before in that case (an
1382 * 8-bit unsigned enumeration field class).
1384 struct fs_sink_ctf_field_class_option
*opt_fc
= (void *) fc
;
1386 field_ref
= opt_fc
->tag_ref
;
1391 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1393 struct fs_sink_ctf_field_class_sequence
*seq_fc
= (void *) fc
;
1395 field_ref
= seq_fc
->length_ref
;
1396 is_before
= seq_fc
->length_is_before
;
1400 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1402 struct fs_sink_ctf_field_class_variant
*var_fc
= (void *) fc
;
1404 field_ref
= var_fc
->tag_ref
;
1405 is_before
= var_fc
->tag_is_before
;
1413 BT_ASSERT(field_ref
);
1419 /* Initial field ref */
1420 g_string_printf(field_ref
, "__%s_%s", fc_name
, tgt_type
);
1423 * Make sure field ref does not clash with an existing field
1424 * class name within the same parent structure field class.
1427 bool name_ok
= true;
1429 for (i
= 0; i
< parent_struct_fc
->members
->len
; i
++) {
1430 struct fs_sink_ctf_named_field_class
*named_fc
=
1431 fs_sink_ctf_field_class_struct_borrow_member_by_index(
1432 parent_struct_fc
, i
);
1434 if (strcmp(field_ref
->str
, named_fc
->name
->str
) == 0) {
1442 /* No clash: we're done */
1446 /* Append suffix and try again */
1447 g_string_printf(field_ref
, "__%s_%s_%u", fc_name
, tgt_type
,
1457 * This function recursively sets field refs of sequence and variant
1458 * field classes when they are immediately before, avoiding name clashes
1459 * with existing field class names.
1461 * It can fail at this point if, for example, a sequence field class of
1462 * which to set the length's field ref has something else than a
1463 * structure field class as its parent: in this case, there's no
1464 * location to place the length field class immediately before the
1465 * sequence field class.
1468 int set_field_refs(struct fs_sink_ctf_field_class
* const fc
,
1469 const char *fc_name
, struct fs_sink_ctf_field_class
*parent_fc
)
1472 enum fs_sink_ctf_field_class_type fc_type
;
1478 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1480 struct fs_sink_ctf_field_class_option
*opt_fc
= (void *) fc
;
1482 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1487 ret
= set_field_refs(opt_fc
->content_fc
, NULL
, fc
);
1494 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
1495 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1499 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
1500 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
1501 struct fs_sink_ctf_named_field_class
*named_fc
;
1503 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1504 struct_fc
= (void *) fc
;
1505 len
= struct_fc
->members
->len
;
1507 var_fc
= (void *) fc
;
1508 len
= var_fc
->options
->len
;
1509 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1515 for (i
= 0; i
< len
; i
++) {
1516 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1517 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
1520 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
1524 ret
= set_field_refs(named_fc
->fc
, named_fc
->name
->str
,
1533 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
1534 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1536 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
1539 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
1540 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1546 ret
= set_field_refs(array_base_fc
->elem_fc
, NULL
, fc
);
1562 * This function translates a root scope trace IR field class to
1563 * a CTF IR field class.
1565 * The resulting CTF IR field class is written to `*fc` so that it
1566 * exists as the parent object's (stream class or event class) true root
1567 * field class during the recursive translation for resolving purposes.
1568 * This is also why this function creates the empty structure field
1569 * class and then calls translate_structure_field_class_members() to
1573 int translate_scope_field_class(struct ctx
*ctx
, bt_field_path_scope scope
,
1574 struct fs_sink_ctf_field_class
**fc
,
1575 const bt_field_class
*ir_fc
)
1583 BT_ASSERT(bt_field_class_get_type(ir_fc
) ==
1584 BT_FIELD_CLASS_TYPE_STRUCTURE
);
1586 *fc
= (void *) fs_sink_ctf_field_class_struct_create_empty(
1587 ir_fc
, UINT64_C(-1));
1589 ctx
->cur_scope
= scope
;
1590 BT_ASSERT(ctx
->cur_path
->len
== 0);
1591 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, ir_fc
, NULL
);
1593 BT_COMP_LOGE("Cannot translate scope structure field class: "
1598 ret
= translate_structure_field_class_members(ctx
, (void *) *fc
, ir_fc
);
1600 BT_COMP_LOGE("Cannot translate scope structure field class: "
1605 cur_path_stack_pop(ctx
);
1607 /* Set field refs for preceding targets */
1608 ret
= set_field_refs(*fc
, NULL
, NULL
);
1615 void ctx_init(struct ctx
*ctx
, struct fs_sink_comp
*fs_sink
)
1617 memset(ctx
, 0, sizeof(struct ctx
));
1618 ctx
->cur_path
= g_array_new(FALSE
, TRUE
,
1619 sizeof(struct field_path_elem
));
1620 BT_ASSERT(ctx
->cur_path
);
1621 ctx
->log_level
= fs_sink
->log_level
;
1622 ctx
->self_comp
= fs_sink
->self_comp
;
1626 void ctx_fini(struct ctx
*ctx
)
1628 if (ctx
->cur_path
) {
1629 g_array_free(ctx
->cur_path
, TRUE
);
1630 ctx
->cur_path
= NULL
;
1635 int translate_event_class(struct fs_sink_comp
*fs_sink
,
1636 struct fs_sink_ctf_stream_class
*sc
,
1637 const bt_event_class
*ir_ec
,
1638 struct fs_sink_ctf_event_class
**out_ec
)
1642 struct fs_sink_ctf_event_class
*ec
;
1647 ctx_init(&ctx
, fs_sink
);
1648 ec
= fs_sink_ctf_event_class_create(sc
, ir_ec
);
1652 ret
= translate_scope_field_class(&ctx
, BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
,
1653 &ec
->spec_context_fc
,
1654 bt_event_class_borrow_specific_context_field_class_const(
1660 ret
= translate_scope_field_class(&ctx
, BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
,
1662 bt_event_class_borrow_payload_field_class_const(ir_ec
));
1674 int try_translate_event_class_trace_ir_to_ctf_ir(
1675 struct fs_sink_comp
*fs_sink
,
1676 struct fs_sink_ctf_stream_class
*sc
,
1677 const bt_event_class
*ir_ec
,
1678 struct fs_sink_ctf_event_class
**out_ec
)
1685 /* Check in hash table first */
1686 *out_ec
= g_hash_table_lookup(sc
->event_classes_from_ir
, ir_ec
);
1687 if (G_LIKELY(*out_ec
)) {
1691 ret
= translate_event_class(fs_sink
, sc
, ir_ec
, out_ec
);
1698 bool default_clock_class_name_exists(struct fs_sink_ctf_trace
*trace
,
1701 bool exists
= false;
1704 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1705 struct fs_sink_ctf_stream_class
*sc
=
1706 trace
->stream_classes
->pdata
[i
];
1708 if (sc
->default_clock_class_name
->len
== 0) {
1709 /* No default clock class */
1713 if (strcmp(sc
->default_clock_class_name
->str
, name
) == 0) {
1724 void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class
*sc
)
1726 unsigned int suffix
= 0;
1729 g_string_assign(sc
->default_clock_class_name
, "");
1730 sprintf(buf
, "default");
1732 while (default_clock_class_name_exists(sc
->trace
, buf
)) {
1733 sprintf(buf
, "default%u", suffix
);
1737 g_string_assign(sc
->default_clock_class_name
, buf
);
1741 int translate_stream_class(struct fs_sink_comp
*fs_sink
,
1742 struct fs_sink_ctf_trace
*trace
,
1743 const bt_stream_class
*ir_sc
,
1744 struct fs_sink_ctf_stream_class
**out_sc
)
1751 ctx_init(&ctx
, fs_sink
);
1752 *out_sc
= fs_sink_ctf_stream_class_create(trace
, ir_sc
);
1755 /* Set default clock class's protected name, if any */
1756 if ((*out_sc
)->default_clock_class
) {
1757 const char *name
= bt_clock_class_get_name(
1758 (*out_sc
)->default_clock_class
);
1761 /* Try original name, protected */
1762 g_string_assign((*out_sc
)->default_clock_class_name
,
1765 if (must_protect_identifier(name
)) {
1767 (*out_sc
)->default_clock_class_name
,
1771 g_string_assign((*out_sc
)->default_clock_class_name
,
1773 if (!ist_valid_identifier(
1774 (*out_sc
)->default_clock_class_name
->str
)) {
1775 /* Invalid: create a new name */
1776 make_unique_default_clock_class_name(*out_sc
);
1779 /* No name: create a name */
1780 make_unique_default_clock_class_name(*out_sc
);
1784 ctx
.cur_sc
= *out_sc
;
1785 ret
= translate_scope_field_class(&ctx
, BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
,
1786 &(*out_sc
)->packet_context_fc
,
1787 bt_stream_class_borrow_packet_context_field_class_const(ir_sc
));
1792 if ((*out_sc
)->packet_context_fc
) {
1794 * Make sure the structure field class's alignment is
1795 * enough: 8 is what we use for our own special members
1796 * in the packet context.
1798 fs_sink_ctf_field_class_struct_align_at_least(
1799 (void *) (*out_sc
)->packet_context_fc
, 8);
1802 ret
= translate_scope_field_class(&ctx
, BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
,
1803 &(*out_sc
)->event_common_context_fc
,
1804 bt_stream_class_borrow_event_common_context_field_class_const(
1813 fs_sink_ctf_stream_class_destroy(*out_sc
);
1822 int try_translate_stream_class_trace_ir_to_ctf_ir(
1823 struct fs_sink_comp
*fs_sink
,
1824 struct fs_sink_ctf_trace
*trace
,
1825 const bt_stream_class
*ir_sc
,
1826 struct fs_sink_ctf_stream_class
**out_sc
)
1834 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1835 *out_sc
= trace
->stream_classes
->pdata
[i
];
1837 if ((*out_sc
)->ir_sc
== ir_sc
) {
1842 ret
= translate_stream_class(fs_sink
, trace
, ir_sc
, out_sc
);
1849 struct fs_sink_ctf_trace
*translate_trace_trace_ir_to_ctf_ir(
1850 struct fs_sink_comp
*fs_sink
, const bt_trace
*ir_trace
)
1854 struct fs_sink_ctf_trace
*trace
= NULL
;
1856 /* Check that trace's environment is TSDL-compatible */
1857 count
= bt_trace_get_environment_entry_count(ir_trace
);
1858 for (i
= 0; i
< count
; i
++) {
1860 const bt_value
*val
;
1862 bt_trace_borrow_environment_entry_by_index_const(
1863 ir_trace
, i
, &name
, &val
);
1865 if (!ist_valid_identifier(name
)) {
1866 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
,
1868 "Unsupported trace class's environment entry name: "
1869 "name=\"%s\"", name
);
1873 switch (bt_value_get_type(val
)) {
1874 case BT_VALUE_TYPE_SIGNED_INTEGER
:
1875 case BT_VALUE_TYPE_STRING
:
1878 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
,
1880 "Unsupported trace class's environment entry value type: "
1882 bt_common_value_type_string(
1883 bt_value_get_type(val
)));
1888 trace
= fs_sink_ctf_trace_create(ir_trace
);