2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
7 #define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
8 #define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
9 #define BT_LOG_TAG "PLUGIN/SINK.CTF.FS/TRANSLATE-TRACE-IR-TO-CTF-IR"
10 #include "logging/comp-logging.h"
12 #include "translate-trace-ir-to-ctf-ir.hpp"
14 #include <babeltrace2/babeltrace.h>
15 #include "common/macros.h"
16 #include "common/common.h"
17 #include "common/assert.h"
24 #include "fs-sink.hpp"
25 #include "fs-sink-ctf-meta.hpp"
27 struct field_path_elem
29 uint64_t index_in_parent
;
33 const bt_field_class
*ir_fc
;
36 struct fs_sink_ctf_field_class
*parent_fc
;
41 bt_logging_level log_level
;
42 bt_self_component
*self_comp
;
45 struct fs_sink_ctf_stream_class
*cur_sc
;
48 struct fs_sink_ctf_event_class
*cur_ec
;
50 bt_field_path_scope cur_scope
;
53 * Array of `struct field_path_elem` */
57 static inline struct field_path_elem
*cur_path_stack_at(struct ctx
*ctx
, uint64_t i
)
59 BT_ASSERT(i
< ctx
->cur_path
->len
);
60 return &g_array_index(ctx
->cur_path
, struct field_path_elem
, i
);
63 static inline struct field_path_elem
*cur_path_stack_top(struct ctx
*ctx
)
65 BT_ASSERT(ctx
->cur_path
->len
> 0);
66 return cur_path_stack_at(ctx
, ctx
->cur_path
->len
- 1);
69 static inline bool is_reserved_member_name(const char *name
, const char *reserved_name
)
71 bool is_reserved
= false;
73 if (strcmp(name
, reserved_name
) == 0) {
78 if (name
[0] == '_' && strcmp(&name
[1], reserved_name
) == 0) {
87 static const char *reserved_tsdl_keywords
[] = {
88 "align", "callsite", "const", "char", "clock", "double", "enum",
89 "env", "event", "floating_point", "float", "integer", "int", "long",
90 "short", "signed", "stream", "string", "struct", "trace", "typealias",
91 "typedef", "unsigned", "variant", "void", "_Bool", "_Complex", "_Imaginary",
94 static inline bool ist_valid_identifier(const char *name
)
98 bool ist_valid
= true;
100 /* Make sure the name is not a reserved keyword */
101 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
); i
++) {
102 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
108 /* Make sure the name is not an empty string */
109 if (strlen(name
) == 0) {
114 /* Make sure the name starts with a letter or `_` */
115 if (!isalpha((unsigned char) name
[0]) && name
[0] != '_') {
120 /* Make sure the name only contains letters, digits, and `_` */
121 for (at
= name
; *at
!= '\0'; at
++) {
122 if (!isalnum((unsigned char) *at
) && *at
!= '_') {
132 static inline bool must_protect_identifier(const char *name
)
135 bool must_protect
= false;
137 /* Protect a reserved keyword */
138 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
); i
++) {
139 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
145 /* Protect an identifier which already starts with `_` */
146 if (name
[0] == '_') {
155 static inline int cur_path_stack_push(struct ctx
*ctx
, uint64_t index_in_parent
, const char *name
,
156 bool force_protect_name
, const bt_field_class
*ir_fc
,
157 struct fs_sink_ctf_field_class
*parent_fc
)
160 struct field_path_elem
*field_path_elem
;
162 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
+ 1);
163 field_path_elem
= cur_path_stack_top(ctx
);
164 field_path_elem
->index_in_parent
= index_in_parent
;
165 field_path_elem
->name
= g_string_new(NULL
);
168 if (force_protect_name
) {
169 g_string_assign(field_path_elem
->name
, "_");
172 g_string_append(field_path_elem
->name
, name
);
174 if (ctx
->cur_scope
== BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
) {
175 if (is_reserved_member_name(name
, "packet_size") ||
176 is_reserved_member_name(name
, "content_size") ||
177 is_reserved_member_name(name
, "timestamp_begin") ||
178 is_reserved_member_name(name
, "timestamp_end") ||
179 is_reserved_member_name(name
, "events_discarded") ||
180 is_reserved_member_name(name
, "packet_seq_num")) {
181 BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
182 "or variant field class option name: name=\"%s\"",
189 if (!ist_valid_identifier(field_path_elem
->name
->str
)) {
191 BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
192 "or variant field class option name: name=\"%s\"",
193 field_path_elem
->name
->str
);
198 field_path_elem
->ir_fc
= ir_fc
;
199 field_path_elem
->parent_fc
= parent_fc
;
205 static inline void cur_path_stack_pop(struct ctx
*ctx
)
207 struct field_path_elem
*field_path_elem
;
209 BT_ASSERT(ctx
->cur_path
->len
> 0);
210 field_path_elem
= cur_path_stack_top(ctx
);
212 if (field_path_elem
->name
) {
213 g_string_free(field_path_elem
->name
, TRUE
);
214 field_path_elem
->name
= NULL
;
217 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
- 1);
221 * Creates a relative field ref (a single name) from IR field path
222 * `tgt_ir_field_path`.
224 * This function tries to locate the target field class recursively from
225 * the top to the bottom of the context's current path using only the
226 * target field class's own name. This is because many CTF reading tools
227 * do not support a relative field ref with more than one element, for
228 * example `prev_struct.len`.
230 * Returns a negative value if this resolving operation failed.
232 static int create_relative_field_ref(struct ctx
*ctx
, const bt_field_path
*tgt_ir_field_path
,
233 GString
*tgt_field_ref
,
234 struct fs_sink_ctf_field_class
**user_tgt_fc
)
237 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
240 const char *tgt_fc_name
= NULL
;
241 struct field_path_elem
*field_path_elem
;
243 /* Get target field class's name */
244 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
245 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
246 BT_ASSERT(ctx
->cur_sc
);
247 tgt_fc
= ctx
->cur_sc
->packet_context_fc
;
249 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
250 BT_ASSERT(ctx
->cur_sc
);
251 tgt_fc
= ctx
->cur_sc
->event_common_context_fc
;
253 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
254 BT_ASSERT(ctx
->cur_ec
);
255 tgt_fc
= ctx
->cur_ec
->spec_context_fc
;
257 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
258 BT_ASSERT(ctx
->cur_ec
);
259 tgt_fc
= ctx
->cur_ec
->payload_fc
;
267 while (i
< bt_field_path_get_item_count(tgt_ir_field_path
)) {
268 const bt_field_path_item
*fp_item
=
269 bt_field_path_borrow_item_by_index_const(tgt_ir_field_path
, i
);
270 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
275 if (bt_field_path_item_get_type(fp_item
) ==
276 BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT
) {
277 /* Not supported by CTF 1.8 */
282 switch (tgt_fc
->type
) {
283 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
284 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
285 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
286 fs_sink_ctf_field_class_as_struct(tgt_fc
),
287 bt_field_path_item_index_get_index(fp_item
));
289 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
290 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
291 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
292 fs_sink_ctf_field_class_as_variant(tgt_fc
),
293 bt_field_path_item_index_get_index(fp_item
));
295 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
296 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
298 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
299 fs_sink_ctf_field_class_as_array_base(tgt_fc
);
301 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
302 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
);
303 tgt_fc
= array_base_fc
->elem_fc
;
311 tgt_fc
= named_fc
->fc
;
312 tgt_fc_name
= named_fc
->name
->str
;
318 BT_ASSERT(tgt_fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_INT
);
319 BT_ASSERT(tgt_fc_name
);
321 /* Find target field class having this name in current context */
322 for (si
= ctx
->cur_path
->len
- 1; si
>= 0; si
--) {
323 struct fs_sink_ctf_field_class
*fc
;
324 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
325 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
326 struct fs_sink_ctf_named_field_class
*named_fc
;
329 field_path_elem
= cur_path_stack_at(ctx
, (uint64_t) si
);
330 fc
= field_path_elem
->parent_fc
;
332 /* Reached stack's bottom */
338 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
339 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
341 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
342 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
345 /* Not supported by TSDL 1.8 */
350 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
351 struct_fc
= fs_sink_ctf_field_class_as_struct(fc
);
352 len
= struct_fc
->members
->len
;
354 var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
355 len
= var_fc
->options
->len
;
358 for (i
= 0; i
< len
; i
++) {
359 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
360 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
362 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
365 if (strcmp(named_fc
->name
->str
, tgt_fc_name
) == 0) {
366 if (named_fc
->fc
== tgt_fc
) {
367 g_string_assign(tgt_field_ref
, tgt_fc_name
);
370 *user_tgt_fc
= tgt_fc
;
374 * Using only the target field
375 * class's name, we're not
376 * reaching the target field
377 * class. This is not supported
393 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
395 * Returns a negative value if this resolving operation failed.
397 static int create_absolute_field_ref(struct ctx
*ctx
, const bt_field_path
*tgt_ir_field_path
,
398 GString
*tgt_field_ref
,
399 struct fs_sink_ctf_field_class
**user_tgt_fc
)
402 struct fs_sink_ctf_field_class
*fc
= NULL
;
405 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
406 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
407 BT_ASSERT(ctx
->cur_sc
);
408 fc
= ctx
->cur_sc
->packet_context_fc
;
409 g_string_assign(tgt_field_ref
, "stream.packet.context");
411 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
412 BT_ASSERT(ctx
->cur_sc
);
413 fc
= ctx
->cur_sc
->event_common_context_fc
;
414 g_string_assign(tgt_field_ref
, "stream.event.context");
416 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
417 BT_ASSERT(ctx
->cur_ec
);
418 fc
= ctx
->cur_ec
->spec_context_fc
;
419 g_string_assign(tgt_field_ref
, "event.context");
421 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
422 BT_ASSERT(ctx
->cur_ec
);
423 fc
= ctx
->cur_ec
->payload_fc
;
424 g_string_assign(tgt_field_ref
, "event.fields");
432 for (i
= 0; i
< bt_field_path_get_item_count(tgt_ir_field_path
); i
++) {
433 const bt_field_path_item
*fp_item
=
434 bt_field_path_borrow_item_by_index_const(tgt_ir_field_path
, i
);
435 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
437 if (bt_field_path_item_get_type(fp_item
) != BT_FIELD_PATH_ITEM_TYPE_INDEX
) {
438 /* Not supported by TSDL 1.8 */
444 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
445 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
446 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
447 fs_sink_ctf_field_class_as_struct(fc
), bt_field_path_item_index_get_index(fp_item
));
449 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
450 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
451 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
452 fs_sink_ctf_field_class_as_variant(fc
),
453 bt_field_path_item_index_get_index(fp_item
));
460 g_string_append_c(tgt_field_ref
, '.');
461 g_string_append(tgt_field_ref
, named_fc
->name
->str
);
474 * Resolves a target field class located at `tgt_ir_field_path`, writing
475 * the resolved field ref to `tgt_field_ref` and setting
476 * `*create_before` according to whether or not the target field must be
477 * created immediately before (in which case `tgt_field_ref` is
480 static void resolve_field_class(struct ctx
*ctx
, const bt_field_path
*tgt_ir_field_path
,
481 GString
*tgt_field_ref
, bool *create_before
,
482 struct fs_sink_ctf_field_class
**user_tgt_fc
)
485 bt_field_path_scope tgt_scope
;
487 *create_before
= false;
489 if (!tgt_ir_field_path
) {
490 *create_before
= true;
494 tgt_scope
= bt_field_path_get_root_scope(tgt_ir_field_path
);
496 if (tgt_scope
== ctx
->cur_scope
) {
498 * Try, in this order:
500 * 1. Use a relative path, using only the target field
501 * class's name. This is what is the most commonly
502 * supported by popular CTF reading tools.
504 * 2. Use an absolute path. This could fail if there's
505 * an array field class from the current root's field
506 * class to the target field class.
508 * 3. Create the target field class before the
509 * requesting field class (fallback).
511 ret
= create_relative_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
513 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
515 *create_before
= true;
520 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
522 /* It must always work in previous scopes */
530 static int translate_field_class(struct ctx
*ctx
);
532 static inline void append_to_parent_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
)
534 struct fs_sink_ctf_field_class
*parent_fc
= cur_path_stack_top(ctx
)->parent_fc
;
536 switch (parent_fc
->type
) {
537 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
538 fs_sink_ctf_field_class_struct_append_member(fs_sink_ctf_field_class_as_struct(parent_fc
),
539 cur_path_stack_top(ctx
)->name
->str
, fc
);
541 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
543 struct fs_sink_ctf_field_class_option
*opt_fc
=
544 fs_sink_ctf_field_class_as_option(parent_fc
);
546 BT_ASSERT(!opt_fc
->content_fc
);
547 opt_fc
->content_fc
= fc
;
548 opt_fc
->base
.alignment
= fc
->alignment
;
551 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
552 fs_sink_ctf_field_class_variant_append_option(fs_sink_ctf_field_class_as_variant(parent_fc
),
553 cur_path_stack_top(ctx
)->name
->str
, fc
);
555 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
556 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
558 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
559 fs_sink_ctf_field_class_as_array_base(parent_fc
);
561 BT_ASSERT(!array_base_fc
->elem_fc
);
562 array_base_fc
->elem_fc
= fc
;
563 array_base_fc
->base
.alignment
= fc
->alignment
;
571 static inline void update_parent_field_class_alignment(struct ctx
*ctx
, unsigned int alignment
)
573 struct fs_sink_ctf_field_class
*parent_fc
= cur_path_stack_top(ctx
)->parent_fc
;
575 switch (parent_fc
->type
) {
576 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
577 fs_sink_ctf_field_class_struct_align_at_least(fs_sink_ctf_field_class_as_struct(parent_fc
),
580 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
581 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
583 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
584 fs_sink_ctf_field_class_as_array_base(parent_fc
);
586 array_base_fc
->base
.alignment
= alignment
;
594 static inline int translate_structure_field_class_members(
595 struct ctx
*ctx
, struct fs_sink_ctf_field_class_struct
*struct_fc
, const bt_field_class
*ir_fc
)
600 for (i
= 0; i
< bt_field_class_structure_get_member_count(ir_fc
); i
++) {
601 const bt_field_class_structure_member
*member
;
603 const bt_field_class
*memb_ir_fc
;
605 member
= bt_field_class_structure_borrow_member_by_index_const(ir_fc
, i
);
606 name
= bt_field_class_structure_member_get_name(member
);
607 memb_ir_fc
= bt_field_class_structure_member_borrow_field_class_const(member
);
608 ret
= cur_path_stack_push(ctx
, i
, name
, true, memb_ir_fc
, &struct_fc
->base
);
610 BT_COMP_LOGE("Cannot translate structure field class member: "
616 ret
= translate_field_class(ctx
);
618 BT_COMP_LOGE("Cannot translate structure field class member: "
624 cur_path_stack_pop(ctx
);
631 static inline int translate_structure_field_class(struct ctx
*ctx
)
634 struct fs_sink_ctf_field_class_struct
*fc
= fs_sink_ctf_field_class_struct_create_empty(
635 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
638 append_to_parent_field_class(ctx
, &fc
->base
);
639 ret
= translate_structure_field_class_members(ctx
, fc
, fc
->base
.ir_fc
);
644 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
651 * This function protects a given variant FC option name (with the `_`
652 * prefix) if required. On success, `name_buf->str` contains the variant
653 * FC option name to use (original option name or protected if
656 * One of the goals of `sink.ctf.fs` is to write a CTF trace which is as
657 * close as possible to an original CTF trace as decoded by
660 * This scenario is valid in CTF 1.8:
672 * Once in trace IR, the enumeration FC mapping names and variant FC
673 * option names are kept as is. For this reason, we don't want to
674 * protect the variant FC option names here (by prepending `_`): this
675 * would make the variant FC option name and the enumeration FC mapping
678 * This scenario is also valid in CTF 1.8:
690 * Once in trace IR, the enumeration FC mapping names are kept as is,
691 * but the `_HELLO` variant FC option name becomes `HELLO` (unprotected
692 * for presentation, as recommended by CTF 1.8). When going back to
693 * TSDL, we need to protect `HELLO` so that it becomes `_HELLO` to match
694 * the corresponding enumeration FC mapping name.
696 * This scenario is also valid in CTF 1.8:
708 * Once in trace IR, the enumeration FC mapping names are kept as is,
709 * but the `__HELLO` variant FC option name becomes `_HELLO`
710 * (unprotected). When going back to TSDL, we need to protect `_HELLO`
711 * so that it becomes `__HELLO` to match the corresponding enumeration
714 * `src.ctf.fs` always uses the _same_ integer range sets for a selector
715 * FC mapping and a corresponding variant FC option. We can use that
716 * fact to find the original variant FC option names by matching variant
717 * FC options and enumeration FC mappings by range set.
719 static int maybe_protect_variant_option_name(const bt_field_class
*ir_var_fc
,
720 const bt_field_class
*ir_tag_fc
, uint64_t opt_i
,
725 bt_field_class_type ir_var_fc_type
;
726 const bt_integer_range_set_unsigned
*opt_ranges_unsigned
= NULL
;
727 const bt_integer_range_set_signed
*opt_ranges_signed
= NULL
;
728 const char *mapping_label
= NULL
;
729 const char *ir_opt_name
;
730 const bt_field_class_variant_option
*base_var_opt
;
731 bool force_protect
= false;
733 ir_var_fc_type
= bt_field_class_get_type(ir_var_fc
);
734 base_var_opt
= bt_field_class_variant_borrow_option_by_index_const(ir_var_fc
, opt_i
);
735 BT_ASSERT(base_var_opt
);
736 ir_opt_name
= bt_field_class_variant_option_get_name(base_var_opt
);
737 BT_ASSERT(ir_opt_name
);
740 * Check if the variant FC option name is required to be
741 * protected (reserved TSDL keyword or starts with `_`). In that
742 * case, the name of the selector FC mapping we find must match
743 * exactly the protected name.
745 force_protect
= must_protect_identifier(ir_opt_name
);
747 g_string_assign(name_buf
, "_");
748 g_string_append(name_buf
, ir_opt_name
);
750 g_string_assign(name_buf
, ir_opt_name
);
753 /* Borrow option's ranges */
754 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
) {
755 /* No ranges: we're done */
758 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
759 const bt_field_class_variant_with_selector_field_integer_unsigned_option
*var_opt
=
760 bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const(
762 opt_ranges_unsigned
=
763 bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
766 const bt_field_class_variant_with_selector_field_integer_signed_option
*var_opt
=
767 bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const(
770 bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const(
774 /* Find corresponding mapping by range set in selector FC */
775 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_tag_fc
); i
++) {
776 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
777 const bt_field_class_enumeration_mapping
*mapping_base
;
778 const bt_field_class_enumeration_unsigned_mapping
*mapping
;
779 const bt_integer_range_set_unsigned
*mapping_ranges
;
782 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(ir_tag_fc
, i
);
784 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(mapping
);
786 if (bt_integer_range_set_unsigned_is_equal(opt_ranges_unsigned
, mapping_ranges
)) {
787 /* We have a winner */
789 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(mapping
);
790 mapping_label
= bt_field_class_enumeration_mapping_get_label(mapping_base
);
794 const bt_field_class_enumeration_mapping
*mapping_base
;
795 const bt_field_class_enumeration_signed_mapping
*mapping
;
796 const bt_integer_range_set_signed
*mapping_ranges
;
798 mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(ir_tag_fc
, i
);
799 mapping_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(mapping
);
801 if (bt_integer_range_set_signed_is_equal(opt_ranges_signed
, mapping_ranges
)) {
802 /* We have a winner */
803 mapping_base
= bt_field_class_enumeration_signed_mapping_as_mapping_const(mapping
);
804 mapping_label
= bt_field_class_enumeration_mapping_get_label(mapping_base
);
810 if (!mapping_label
) {
811 /* Range set not found: invalid selector for CTF 1.8 */
817 * If the enumeration FC mapping name is not the same as the
818 * variant FC option name and we didn't protect already, try
819 * protecting the option name and check again.
821 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
827 if (mapping_label
[0] == '\0') {
832 g_string_assign(name_buf
, "_");
833 g_string_append(name_buf
, ir_opt_name
);
835 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
845 static inline int translate_option_field_class(struct ctx
*ctx
)
847 struct fs_sink_ctf_field_class_option
*fc
= fs_sink_ctf_field_class_option_create_empty(
848 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
849 const bt_field_class
*content_ir_fc
=
850 bt_field_class_option_borrow_field_class_const(fc
->base
.ir_fc
);
856 * CTF 1.8 does not support the option field class type. To
857 * write something anyway, this component translates this type
858 * to a variant field class where the options are:
860 * * An empty structure field class.
861 * * The optional field class itself.
863 * The "tag" is always generated/before in that case (an 8-bit
864 * unsigned enumeration field class).
866 append_to_parent_field_class(ctx
, &fc
->base
);
867 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, content_ir_fc
, &fc
->base
);
869 BT_COMP_LOGE_STR("Cannot translate option field class content.");
873 ret
= translate_field_class(ctx
);
875 BT_COMP_LOGE_STR("Cannot translate option field class content.");
879 cur_path_stack_pop(ctx
);
880 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
886 static inline int translate_variant_field_class(struct ctx
*ctx
)
890 struct fs_sink_ctf_field_class_variant
*fc
= fs_sink_ctf_field_class_variant_create_empty(
891 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
892 bt_field_class_type ir_fc_type
;
893 const bt_field_path
*ir_selector_field_path
= NULL
;
894 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
895 GString
*name_buf
= g_string_new(NULL
);
896 bt_value
*prot_opt_names
= bt_value_array_create();
901 BT_ASSERT(prot_opt_names
);
902 ir_fc_type
= bt_field_class_get_type(fc
->base
.ir_fc
);
903 opt_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
905 if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_VARIANT_WITH_SELECTOR_FIELD
)) {
906 ir_selector_field_path
=
907 bt_field_class_variant_with_selector_field_borrow_selector_field_path_const(
909 BT_ASSERT(ir_selector_field_path
);
912 /* Resolve tag field class before appending to parent */
913 resolve_field_class(ctx
, ir_selector_field_path
, fc
->tag_ref
, &fc
->tag_is_before
, &tgt_fc
);
915 if (ir_selector_field_path
&& tgt_fc
) {
916 uint64_t mapping_count
;
917 uint64_t option_count
;
919 /* CTF 1.8: selector FC must be an enumeration FC */
920 bt_field_class_type type
= bt_field_class_get_type(tgt_fc
->ir_fc
);
922 if (!bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
923 fc
->tag_is_before
= true;
928 * Call maybe_protect_variant_option_name() for each
929 * option below. In that case we also want selector FC
930 * to contain as many mappings as the variant FC has
933 mapping_count
= bt_field_class_enumeration_get_mapping_count(tgt_fc
->ir_fc
);
934 option_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
936 if (mapping_count
!= option_count
) {
937 fc
->tag_is_before
= true;
942 * No compatible selector field class for CTF 1.8:
943 * create the appropriate selector field class.
945 fc
->tag_is_before
= true;
951 * First pass: detect any option name clash with option name
952 * protection. In that case, we don't fail: just create the
953 * selector field class before the variant field class.
955 * After this, `prot_opt_names` contains the final option names,
956 * potentially protected if needed. They can still be invalid
957 * TSDL identifiers however; this will be checked by
958 * cur_path_stack_push().
960 for (i
= 0; i
< opt_count
; i
++) {
961 if (!fc
->tag_is_before
) {
962 BT_ASSERT(tgt_fc
->ir_fc
);
963 ret
= maybe_protect_variant_option_name(fc
->base
.ir_fc
, tgt_fc
->ir_fc
, i
, name_buf
);
965 fc
->tag_is_before
= true;
969 ret
= bt_value_array_append_string_element(prot_opt_names
, name_buf
->str
);
975 for (i
= 0; i
< opt_count
; i
++) {
977 const bt_value
*opt_name_a
=
978 bt_value_array_borrow_element_by_index_const(prot_opt_names
, i
);
980 for (j
= 0; j
< opt_count
; j
++) {
981 const bt_value
*opt_name_b
;
987 opt_name_b
= bt_value_array_borrow_element_by_index_const(prot_opt_names
, j
);
988 if (bt_value_is_equal(opt_name_a
, opt_name_b
)) {
990 * Variant FC option names are not
991 * unique when protected.
993 fc
->tag_is_before
= true;
994 goto append_to_parent
;
1000 append_to_parent_field_class(ctx
, &fc
->base
);
1002 for (i
= 0; i
< opt_count
; i
++) {
1003 const bt_field_class_variant_option
*opt
;
1004 const bt_field_class
*opt_ir_fc
;
1005 const bt_value
*prot_opt_name_val
=
1006 bt_value_array_borrow_element_by_index_const(prot_opt_names
, i
);
1007 const char *prot_opt_name
= bt_value_string_get(prot_opt_name_val
);
1009 BT_ASSERT(prot_opt_name
);
1010 opt
= bt_field_class_variant_borrow_option_by_index_const(fc
->base
.ir_fc
, i
);
1011 opt_ir_fc
= bt_field_class_variant_option_borrow_field_class_const(opt
);
1014 * We don't ask cur_path_stack_push() to protect the
1015 * option name because it's already protected at this
1018 ret
= cur_path_stack_push(ctx
, i
, prot_opt_name
, false, opt_ir_fc
, &fc
->base
);
1020 BT_COMP_LOGE("Cannot translate variant field class option: "
1026 ret
= translate_field_class(ctx
);
1028 BT_COMP_LOGE("Cannot translate variant field class option: "
1034 cur_path_stack_pop(ctx
);
1039 g_string_free(name_buf
, TRUE
);
1042 bt_value_put_ref(prot_opt_names
);
1046 static inline int translate_static_array_field_class(struct ctx
*ctx
)
1048 struct fs_sink_ctf_field_class_array
*fc
= fs_sink_ctf_field_class_array_create_empty(
1049 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1050 const bt_field_class
*elem_ir_fc
=
1051 bt_field_class_array_borrow_element_field_class_const(fc
->base
.base
.ir_fc
);
1055 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1056 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
, &fc
->base
.base
);
1058 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1062 ret
= translate_field_class(ctx
);
1064 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1068 cur_path_stack_pop(ctx
);
1069 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1075 static inline int translate_dynamic_array_field_class(struct ctx
*ctx
)
1077 struct fs_sink_ctf_field_class_sequence
*fc
= fs_sink_ctf_field_class_sequence_create_empty(
1078 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1079 const bt_field_class
*elem_ir_fc
=
1080 bt_field_class_array_borrow_element_field_class_const(fc
->base
.base
.ir_fc
);
1085 /* Resolve length field class before appending to parent */
1086 if (bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
) ==
1087 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
) {
1088 resolve_field_class(
1090 bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const(
1091 fc
->base
.base
.ir_fc
),
1092 fc
->length_ref
, &fc
->length_is_before
, NULL
);
1095 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1096 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
, &fc
->base
.base
);
1098 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1102 ret
= translate_field_class(ctx
);
1104 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1108 cur_path_stack_pop(ctx
);
1109 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1115 static inline int translate_bool_field_class(struct ctx
*ctx
)
1117 struct fs_sink_ctf_field_class_bool
*fc
= fs_sink_ctf_field_class_bool_create(
1118 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1121 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1125 static inline int translate_bit_array_field_class(struct ctx
*ctx
)
1127 struct fs_sink_ctf_field_class_bit_array
*fc
= fs_sink_ctf_field_class_bit_array_create(
1128 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1131 append_to_parent_field_class(ctx
, &fc
->base
);
1135 static inline int translate_integer_field_class(struct ctx
*ctx
)
1137 struct fs_sink_ctf_field_class_int
*fc
= fs_sink_ctf_field_class_int_create(
1138 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1141 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1145 static inline int translate_real_field_class(struct ctx
*ctx
)
1147 struct fs_sink_ctf_field_class_float
*fc
= fs_sink_ctf_field_class_float_create(
1148 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1151 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1155 static inline int translate_string_field_class(struct ctx
*ctx
)
1157 struct fs_sink_ctf_field_class_string
*fc
= fs_sink_ctf_field_class_string_create(
1158 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1161 append_to_parent_field_class(ctx
, &fc
->base
);
1166 * Translates a field class, recursively.
1168 * The field class's IR field class, parent field class, and index
1169 * within its parent are in the context's current path's top element
1170 * (cur_path_stack_top()).
1172 static int translate_field_class(struct ctx
*ctx
)
1175 bt_field_class_type ir_fc_type
= bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
);
1177 if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BOOL
) {
1178 ret
= translate_bool_field_class(ctx
);
1179 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BIT_ARRAY
) {
1180 ret
= translate_bit_array_field_class(ctx
);
1181 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_INTEGER
)) {
1182 ret
= translate_integer_field_class(ctx
);
1183 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_REAL
)) {
1184 ret
= translate_real_field_class(ctx
);
1185 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRING
) {
1186 ret
= translate_string_field_class(ctx
);
1187 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRUCTURE
) {
1188 ret
= translate_structure_field_class(ctx
);
1189 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
1190 ret
= translate_static_array_field_class(ctx
);
1191 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
)) {
1192 ret
= translate_dynamic_array_field_class(ctx
);
1193 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_OPTION
)) {
1194 ret
= translate_option_field_class(ctx
);
1195 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_VARIANT
)) {
1196 ret
= translate_variant_field_class(ctx
);
1204 static int set_field_ref(struct fs_sink_ctf_field_class
*fc
, const char *fc_name
,
1205 struct fs_sink_ctf_field_class
*parent_fc
)
1208 GString
*field_ref
= NULL
;
1210 const char *tgt_type
;
1211 struct fs_sink_ctf_field_class_struct
*parent_struct_fc
=
1212 fs_sink_ctf_field_class_as_struct(parent_fc
);
1214 unsigned int suffix
= 0;
1216 if (!fc_name
|| !parent_fc
|| parent_fc
->type
!= FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1223 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1226 * CTF 1.8 does not support the option field class type.
1227 * To write something anyway, this component translates
1228 * this type to a variant field class where the options
1231 * * An empty structure field class.
1232 * * The optional field class itself.
1234 * Because the option field class becomes a CTF variant
1235 * field class, we use the term "tag" too here.
1237 * The "tag" is always generated/before in that case (an
1238 * 8-bit unsigned enumeration field class).
1240 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
1242 field_ref
= opt_fc
->tag_ref
;
1247 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1249 struct fs_sink_ctf_field_class_sequence
*seq_fc
= fs_sink_ctf_field_class_as_sequence(fc
);
1251 field_ref
= seq_fc
->length_ref
;
1252 is_before
= seq_fc
->length_is_before
;
1256 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1258 struct fs_sink_ctf_field_class_variant
*var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
1260 field_ref
= var_fc
->tag_ref
;
1261 is_before
= var_fc
->tag_is_before
;
1269 BT_ASSERT(field_ref
);
1275 /* Initial field ref */
1276 g_string_printf(field_ref
, "__%s_%s", fc_name
, tgt_type
);
1279 * Make sure field ref does not clash with an existing field
1280 * class name within the same parent structure field class.
1283 bool name_ok
= true;
1285 for (i
= 0; i
< parent_struct_fc
->members
->len
; i
++) {
1286 struct fs_sink_ctf_named_field_class
*named_fc
=
1287 fs_sink_ctf_field_class_struct_borrow_member_by_index(parent_struct_fc
, i
);
1289 if (strcmp(field_ref
->str
, named_fc
->name
->str
) == 0) {
1297 /* No clash: we're done */
1301 /* Append suffix and try again */
1302 g_string_printf(field_ref
, "__%s_%s_%u", fc_name
, tgt_type
, suffix
);
1311 * This function recursively sets field refs of sequence and variant
1312 * field classes when they are immediately before, avoiding name clashes
1313 * with existing field class names.
1315 * It can fail at this point if, for example, a sequence field class of
1316 * which to set the length's field ref has something else than a
1317 * structure field class as its parent: in this case, there's no
1318 * location to place the length field class immediately before the
1319 * sequence field class.
1321 static int set_field_refs(struct fs_sink_ctf_field_class
* const fc
, const char *fc_name
,
1322 struct fs_sink_ctf_field_class
*parent_fc
)
1325 enum fs_sink_ctf_field_class_type fc_type
;
1331 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1333 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
1335 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1340 ret
= set_field_refs(opt_fc
->content_fc
, NULL
, fc
);
1347 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
1348 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1352 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
1353 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
1354 struct fs_sink_ctf_named_field_class
*named_fc
;
1356 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1357 struct_fc
= fs_sink_ctf_field_class_as_struct(fc
);
1358 len
= struct_fc
->members
->len
;
1360 var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
1361 len
= var_fc
->options
->len
;
1362 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1368 for (i
= 0; i
< len
; i
++) {
1369 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1370 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
1372 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
1375 ret
= set_field_refs(named_fc
->fc
, named_fc
->name
->str
, fc
);
1383 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
1384 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1386 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
1387 fs_sink_ctf_field_class_as_array_base(fc
);
1389 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
1390 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1396 ret
= set_field_refs(array_base_fc
->elem_fc
, NULL
, fc
);
1412 * This function translates a root scope trace IR field class to
1413 * a CTF IR field class.
1415 * The resulting CTF IR field class is written to `*fc` so that it
1416 * exists as the parent object's (stream class or event class) true root
1417 * field class during the recursive translation for resolving purposes.
1418 * This is also why this function creates the empty structure field
1419 * class and then calls translate_structure_field_class_members() to
1422 static int translate_scope_field_class(struct ctx
*ctx
, bt_field_path_scope scope
,
1423 struct fs_sink_ctf_field_class
**fc
,
1424 const bt_field_class
*ir_fc
)
1432 BT_ASSERT(bt_field_class_get_type(ir_fc
) == BT_FIELD_CLASS_TYPE_STRUCTURE
);
1434 *fc
= &fs_sink_ctf_field_class_struct_create_empty(ir_fc
, UINT64_C(-1))->base
;
1436 ctx
->cur_scope
= scope
;
1437 BT_ASSERT(ctx
->cur_path
->len
== 0);
1438 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, ir_fc
, NULL
);
1440 BT_COMP_LOGE("Cannot translate scope structure field class: "
1447 translate_structure_field_class_members(ctx
, fs_sink_ctf_field_class_as_struct(*fc
), ir_fc
);
1449 BT_COMP_LOGE("Cannot translate scope structure field class: "
1455 cur_path_stack_pop(ctx
);
1457 /* Set field refs for preceding targets */
1458 ret
= set_field_refs(*fc
, NULL
, NULL
);
1464 static inline void ctx_init(struct ctx
*ctx
, struct fs_sink_comp
*fs_sink
)
1466 memset(ctx
, 0, sizeof(struct ctx
));
1467 ctx
->cur_path
= g_array_new(FALSE
, TRUE
, sizeof(struct field_path_elem
));
1468 BT_ASSERT(ctx
->cur_path
);
1469 ctx
->log_level
= fs_sink
->log_level
;
1470 ctx
->self_comp
= fs_sink
->self_comp
;
1473 static inline void ctx_fini(struct ctx
*ctx
)
1475 if (ctx
->cur_path
) {
1476 g_array_free(ctx
->cur_path
, TRUE
);
1477 ctx
->cur_path
= NULL
;
1481 static int translate_event_class(struct fs_sink_comp
*fs_sink
, struct fs_sink_ctf_stream_class
*sc
,
1482 const bt_event_class
*ir_ec
,
1483 struct fs_sink_ctf_event_class
**out_ec
)
1487 struct fs_sink_ctf_event_class
*ec
;
1492 ctx_init(&ctx
, fs_sink
);
1493 ec
= fs_sink_ctf_event_class_create(sc
, ir_ec
);
1497 ret
= translate_scope_field_class(
1498 &ctx
, BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
, &ec
->spec_context_fc
,
1499 bt_event_class_borrow_specific_context_field_class_const(ir_ec
));
1504 ret
= translate_scope_field_class(&ctx
, BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
, &ec
->payload_fc
,
1505 bt_event_class_borrow_payload_field_class_const(ir_ec
));
1517 int try_translate_event_class_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1518 struct fs_sink_ctf_stream_class
*sc
,
1519 const bt_event_class
*ir_ec
,
1520 struct fs_sink_ctf_event_class
**out_ec
)
1527 /* Check in hash table first */
1528 *out_ec
= (fs_sink_ctf_event_class
*) g_hash_table_lookup(sc
->event_classes_from_ir
, ir_ec
);
1529 if (G_LIKELY(*out_ec
)) {
1533 ret
= translate_event_class(fs_sink
, sc
, ir_ec
, out_ec
);
1539 static bool default_clock_class_name_exists(struct fs_sink_ctf_trace
*trace
, const char *name
)
1541 bool exists
= false;
1544 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1545 struct fs_sink_ctf_stream_class
*sc
=
1546 (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
];
1548 if (sc
->default_clock_class_name
->len
== 0) {
1549 /* No default clock class */
1553 if (strcmp(sc
->default_clock_class_name
->str
, name
) == 0) {
1563 static void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class
*sc
)
1565 unsigned int suffix
= 0;
1567 std::string name
= "default";
1569 while (default_clock_class_name_exists(sc
->trace
, name
.c_str())) {
1570 name
= "default" + std::to_string(suffix
);
1574 g_string_assign(sc
->default_clock_class_name
, name
.c_str());
1577 static int translate_stream_class(struct fs_sink_comp
*fs_sink
, struct fs_sink_ctf_trace
*trace
,
1578 const bt_stream_class
*ir_sc
,
1579 struct fs_sink_ctf_stream_class
**out_sc
)
1586 ctx_init(&ctx
, fs_sink
);
1587 *out_sc
= fs_sink_ctf_stream_class_create(trace
, ir_sc
);
1590 /* Set default clock class's protected name, if any */
1591 if ((*out_sc
)->default_clock_class
) {
1592 const char *name
= bt_clock_class_get_name((*out_sc
)->default_clock_class
);
1595 /* Try original name, protected */
1596 g_string_assign((*out_sc
)->default_clock_class_name
, "");
1598 if (must_protect_identifier(name
)) {
1599 g_string_assign((*out_sc
)->default_clock_class_name
, "_");
1602 g_string_assign((*out_sc
)->default_clock_class_name
, name
);
1603 if (!ist_valid_identifier((*out_sc
)->default_clock_class_name
->str
)) {
1604 /* Invalid: create a new name */
1605 make_unique_default_clock_class_name(*out_sc
);
1608 /* No name: create a name */
1609 make_unique_default_clock_class_name(*out_sc
);
1613 ctx
.cur_sc
= *out_sc
;
1614 ret
= translate_scope_field_class(
1615 &ctx
, BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
, &(*out_sc
)->packet_context_fc
,
1616 bt_stream_class_borrow_packet_context_field_class_const(ir_sc
));
1621 if ((*out_sc
)->packet_context_fc
) {
1623 * Make sure the structure field class's alignment is
1624 * enough: 8 is what we use for our own special members
1625 * in the packet context.
1627 fs_sink_ctf_field_class_struct_align_at_least(
1628 fs_sink_ctf_field_class_as_struct((*out_sc
)->packet_context_fc
), 8);
1631 ret
= translate_scope_field_class(
1632 &ctx
, BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
, &(*out_sc
)->event_common_context_fc
,
1633 bt_stream_class_borrow_event_common_context_field_class_const(ir_sc
));
1641 fs_sink_ctf_stream_class_destroy(*out_sc
);
1650 int try_translate_stream_class_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1651 struct fs_sink_ctf_trace
*trace
,
1652 const bt_stream_class
*ir_sc
,
1653 struct fs_sink_ctf_stream_class
**out_sc
)
1661 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1662 *out_sc
= (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
];
1664 if ((*out_sc
)->ir_sc
== ir_sc
) {
1669 ret
= translate_stream_class(fs_sink
, trace
, ir_sc
, out_sc
);
1676 struct fs_sink_ctf_trace
*translate_trace_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1677 const bt_trace
*ir_trace
)
1681 struct fs_sink_ctf_trace
*trace
= NULL
;
1683 /* Check that trace's environment is TSDL-compatible */
1684 count
= bt_trace_get_environment_entry_count(ir_trace
);
1685 for (i
= 0; i
< count
; i
++) {
1687 const bt_value
*val
;
1689 bt_trace_borrow_environment_entry_by_index_const(ir_trace
, i
, &name
, &val
);
1691 if (!ist_valid_identifier(name
)) {
1692 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
, fs_sink
->self_comp
,
1693 "Unsupported trace class's environment entry name: "
1699 switch (bt_value_get_type(val
)) {
1700 case BT_VALUE_TYPE_SIGNED_INTEGER
:
1701 case BT_VALUE_TYPE_STRING
:
1704 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
, fs_sink
->self_comp
,
1705 "Unsupported trace class's environment entry value type: "
1707 bt_common_value_type_string(bt_value_get_type(val
)));
1712 trace
= fs_sink_ctf_trace_create(ir_trace
);