2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
13 #include <babeltrace2/babeltrace.h>
15 #define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
16 #define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
17 #define BT_LOG_TAG "PLUGIN/SINK.CTF.FS/TRANSLATE-TRACE-IR-TO-CTF-IR"
18 #include "logging/comp-logging.h"
20 #include "common/assert.h"
21 #include "common/common.h"
22 #include "common/macros.h"
24 #include "fs-sink-ctf-meta.hpp"
25 #include "fs-sink.hpp"
26 #include "translate-trace-ir-to-ctf-ir.hpp"
28 struct field_path_elem
30 uint64_t index_in_parent
;
34 const bt_field_class
*ir_fc
;
37 struct fs_sink_ctf_field_class
*parent_fc
;
42 bt_logging_level log_level
;
43 bt_self_component
*self_comp
;
46 struct fs_sink_ctf_stream_class
*cur_sc
;
49 struct fs_sink_ctf_event_class
*cur_ec
;
51 bt_field_path_scope cur_scope
;
54 * Array of `struct field_path_elem` */
58 static inline struct field_path_elem
*cur_path_stack_at(struct ctx
*ctx
, uint64_t i
)
60 BT_ASSERT(i
< ctx
->cur_path
->len
);
61 return &bt_g_array_index(ctx
->cur_path
, struct field_path_elem
, i
);
64 static inline struct field_path_elem
*cur_path_stack_top(struct ctx
*ctx
)
66 BT_ASSERT(ctx
->cur_path
->len
> 0);
67 return cur_path_stack_at(ctx
, ctx
->cur_path
->len
- 1);
70 static inline bool is_reserved_member_name(const char *name
, const char *reserved_name
)
72 bool is_reserved
= false;
74 if (strcmp(name
, reserved_name
) == 0) {
79 if (name
[0] == '_' && strcmp(&name
[1], reserved_name
) == 0) {
88 static const char *reserved_tsdl_keywords
[] = {
89 "align", "callsite", "const", "char", "clock", "double", "enum",
90 "env", "event", "floating_point", "float", "integer", "int", "long",
91 "short", "signed", "stream", "string", "struct", "trace", "typealias",
92 "typedef", "unsigned", "variant", "void", "_Bool", "_Complex", "_Imaginary",
95 static inline bool ist_valid_identifier(const char *name
)
99 bool ist_valid
= true;
101 /* Make sure the name is not a reserved keyword */
102 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
); i
++) {
103 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
109 /* Make sure the name is not an empty string */
110 if (strlen(name
) == 0) {
115 /* Make sure the name starts with a letter or `_` */
116 if (!isalpha((unsigned char) name
[0]) && name
[0] != '_') {
121 /* Make sure the name only contains letters, digits, and `_` */
122 for (at
= name
; *at
!= '\0'; at
++) {
123 if (!isalnum((unsigned char) *at
) && *at
!= '_') {
133 static inline bool must_protect_identifier(const char *name
)
136 bool must_protect
= false;
138 /* Protect a reserved keyword */
139 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
); i
++) {
140 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
146 /* Protect an identifier which already starts with `_` */
147 if (name
[0] == '_') {
156 static inline int cur_path_stack_push(struct ctx
*ctx
, uint64_t index_in_parent
, const char *name
,
157 bool force_protect_name
, const bt_field_class
*ir_fc
,
158 struct fs_sink_ctf_field_class
*parent_fc
)
161 struct field_path_elem
*field_path_elem
;
163 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
+ 1);
164 field_path_elem
= cur_path_stack_top(ctx
);
165 field_path_elem
->index_in_parent
= index_in_parent
;
166 field_path_elem
->name
= g_string_new(NULL
);
169 if (force_protect_name
) {
170 g_string_assign(field_path_elem
->name
, "_");
173 g_string_append(field_path_elem
->name
, name
);
175 if (ctx
->cur_scope
== BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
) {
176 if (is_reserved_member_name(name
, "packet_size") ||
177 is_reserved_member_name(name
, "content_size") ||
178 is_reserved_member_name(name
, "timestamp_begin") ||
179 is_reserved_member_name(name
, "timestamp_end") ||
180 is_reserved_member_name(name
, "events_discarded") ||
181 is_reserved_member_name(name
, "packet_seq_num")) {
182 BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
183 "or variant field class option name: name=\"%s\"",
190 if (!ist_valid_identifier(field_path_elem
->name
->str
)) {
192 BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
193 "or variant field class option name: name=\"%s\"",
194 field_path_elem
->name
->str
);
199 field_path_elem
->ir_fc
= ir_fc
;
200 field_path_elem
->parent_fc
= parent_fc
;
206 static inline void cur_path_stack_pop(struct ctx
*ctx
)
208 struct field_path_elem
*field_path_elem
;
210 BT_ASSERT(ctx
->cur_path
->len
> 0);
211 field_path_elem
= cur_path_stack_top(ctx
);
213 if (field_path_elem
->name
) {
214 g_string_free(field_path_elem
->name
, TRUE
);
215 field_path_elem
->name
= NULL
;
218 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
- 1);
222 * Creates a relative field ref (a single name) from IR field path
223 * `tgt_ir_field_path`.
225 * This function tries to locate the target field class recursively from
226 * the top to the bottom of the context's current path using only the
227 * target field class's own name. This is because many CTF reading tools
228 * do not support a relative field ref with more than one element, for
229 * example `prev_struct.len`.
231 * Returns a negative value if this resolving operation failed.
233 static int create_relative_field_ref(struct ctx
*ctx
, const bt_field_path
*tgt_ir_field_path
,
234 GString
*tgt_field_ref
,
235 struct fs_sink_ctf_field_class
**user_tgt_fc
)
238 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
241 const char *tgt_fc_name
= NULL
;
242 struct field_path_elem
*field_path_elem
;
244 /* Get target field class's name */
245 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
246 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
247 BT_ASSERT(ctx
->cur_sc
);
248 tgt_fc
= ctx
->cur_sc
->packet_context_fc
;
250 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
251 BT_ASSERT(ctx
->cur_sc
);
252 tgt_fc
= ctx
->cur_sc
->event_common_context_fc
;
254 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
255 BT_ASSERT(ctx
->cur_ec
);
256 tgt_fc
= ctx
->cur_ec
->spec_context_fc
;
258 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
259 BT_ASSERT(ctx
->cur_ec
);
260 tgt_fc
= ctx
->cur_ec
->payload_fc
;
268 while (i
< bt_field_path_get_item_count(tgt_ir_field_path
)) {
269 const bt_field_path_item
*fp_item
=
270 bt_field_path_borrow_item_by_index_const(tgt_ir_field_path
, i
);
271 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
276 if (bt_field_path_item_get_type(fp_item
) ==
277 BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT
) {
278 /* Not supported by CTF 1.8 */
283 switch (tgt_fc
->type
) {
284 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
285 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
286 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
287 fs_sink_ctf_field_class_as_struct(tgt_fc
),
288 bt_field_path_item_index_get_index(fp_item
));
290 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
291 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
292 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
293 fs_sink_ctf_field_class_as_variant(tgt_fc
),
294 bt_field_path_item_index_get_index(fp_item
));
296 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
297 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
299 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
300 fs_sink_ctf_field_class_as_array_base(tgt_fc
);
302 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
303 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
);
304 tgt_fc
= array_base_fc
->elem_fc
;
312 tgt_fc
= named_fc
->fc
;
313 tgt_fc_name
= named_fc
->name
->str
;
319 BT_ASSERT(tgt_fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_INT
);
320 BT_ASSERT(tgt_fc_name
);
322 /* Find target field class having this name in current context */
323 for (si
= ctx
->cur_path
->len
- 1; si
>= 0; si
--) {
324 struct fs_sink_ctf_field_class
*fc
;
325 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
326 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
327 struct fs_sink_ctf_named_field_class
*named_fc
;
330 field_path_elem
= cur_path_stack_at(ctx
, (uint64_t) si
);
331 fc
= field_path_elem
->parent_fc
;
333 /* Reached stack's bottom */
339 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
340 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
342 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
343 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
346 /* Not supported by TSDL 1.8 */
351 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
352 struct_fc
= fs_sink_ctf_field_class_as_struct(fc
);
353 len
= struct_fc
->members
->len
;
355 var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
356 len
= var_fc
->options
->len
;
359 for (i
= 0; i
< len
; i
++) {
360 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
361 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
363 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
366 if (strcmp(named_fc
->name
->str
, tgt_fc_name
) == 0) {
367 if (named_fc
->fc
== tgt_fc
) {
368 g_string_assign(tgt_field_ref
, tgt_fc_name
);
371 *user_tgt_fc
= tgt_fc
;
375 * Using only the target field
376 * class's name, we're not
377 * reaching the target field
378 * class. This is not supported
394 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
396 * Returns a negative value if this resolving operation failed.
398 static int create_absolute_field_ref(struct ctx
*ctx
, const bt_field_path
*tgt_ir_field_path
,
399 GString
*tgt_field_ref
,
400 struct fs_sink_ctf_field_class
**user_tgt_fc
)
403 struct fs_sink_ctf_field_class
*fc
= NULL
;
406 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
407 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
408 BT_ASSERT(ctx
->cur_sc
);
409 fc
= ctx
->cur_sc
->packet_context_fc
;
410 g_string_assign(tgt_field_ref
, "stream.packet.context");
412 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
413 BT_ASSERT(ctx
->cur_sc
);
414 fc
= ctx
->cur_sc
->event_common_context_fc
;
415 g_string_assign(tgt_field_ref
, "stream.event.context");
417 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
418 BT_ASSERT(ctx
->cur_ec
);
419 fc
= ctx
->cur_ec
->spec_context_fc
;
420 g_string_assign(tgt_field_ref
, "event.context");
422 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
423 BT_ASSERT(ctx
->cur_ec
);
424 fc
= ctx
->cur_ec
->payload_fc
;
425 g_string_assign(tgt_field_ref
, "event.fields");
433 for (i
= 0; i
< bt_field_path_get_item_count(tgt_ir_field_path
); i
++) {
434 const bt_field_path_item
*fp_item
=
435 bt_field_path_borrow_item_by_index_const(tgt_ir_field_path
, i
);
436 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
438 if (bt_field_path_item_get_type(fp_item
) != BT_FIELD_PATH_ITEM_TYPE_INDEX
) {
439 /* Not supported by TSDL 1.8 */
445 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
446 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
447 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
448 fs_sink_ctf_field_class_as_struct(fc
), bt_field_path_item_index_get_index(fp_item
));
450 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
451 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
452 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
453 fs_sink_ctf_field_class_as_variant(fc
),
454 bt_field_path_item_index_get_index(fp_item
));
461 g_string_append_c(tgt_field_ref
, '.');
462 g_string_append(tgt_field_ref
, named_fc
->name
->str
);
475 * Resolves a target field class located at `tgt_ir_field_path`, writing
476 * the resolved field ref to `tgt_field_ref` and setting
477 * `*create_before` according to whether or not the target field must be
478 * created immediately before (in which case `tgt_field_ref` is
481 static void resolve_field_class(struct ctx
*ctx
, const bt_field_path
*tgt_ir_field_path
,
482 GString
*tgt_field_ref
, bool *create_before
,
483 struct fs_sink_ctf_field_class
**user_tgt_fc
)
486 bt_field_path_scope tgt_scope
;
488 *create_before
= false;
490 if (!tgt_ir_field_path
) {
491 *create_before
= true;
495 tgt_scope
= bt_field_path_get_root_scope(tgt_ir_field_path
);
497 if (tgt_scope
== ctx
->cur_scope
) {
499 * Try, in this order:
501 * 1. Use a relative path, using only the target field
502 * class's name. This is what is the most commonly
503 * supported by popular CTF reading tools.
505 * 2. Use an absolute path. This could fail if there's
506 * an array field class from the current root's field
507 * class to the target field class.
509 * 3. Create the target field class before the
510 * requesting field class (fallback).
512 ret
= create_relative_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
514 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
516 *create_before
= true;
521 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
523 /* It must always work in previous scopes */
531 static int translate_field_class(struct ctx
*ctx
);
533 static inline void append_to_parent_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
)
535 struct fs_sink_ctf_field_class
*parent_fc
= cur_path_stack_top(ctx
)->parent_fc
;
537 switch (parent_fc
->type
) {
538 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
539 fs_sink_ctf_field_class_struct_append_member(fs_sink_ctf_field_class_as_struct(parent_fc
),
540 cur_path_stack_top(ctx
)->name
->str
, fc
);
542 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
544 struct fs_sink_ctf_field_class_option
*opt_fc
=
545 fs_sink_ctf_field_class_as_option(parent_fc
);
547 BT_ASSERT(!opt_fc
->content_fc
);
548 opt_fc
->content_fc
= fc
;
549 opt_fc
->base
.alignment
= fc
->alignment
;
552 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
553 fs_sink_ctf_field_class_variant_append_option(fs_sink_ctf_field_class_as_variant(parent_fc
),
554 cur_path_stack_top(ctx
)->name
->str
, fc
);
556 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
557 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
559 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
560 fs_sink_ctf_field_class_as_array_base(parent_fc
);
562 BT_ASSERT(!array_base_fc
->elem_fc
);
563 array_base_fc
->elem_fc
= fc
;
564 array_base_fc
->base
.alignment
= fc
->alignment
;
572 static inline void update_parent_field_class_alignment(struct ctx
*ctx
, unsigned int alignment
)
574 struct fs_sink_ctf_field_class
*parent_fc
= cur_path_stack_top(ctx
)->parent_fc
;
576 switch (parent_fc
->type
) {
577 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
578 fs_sink_ctf_field_class_struct_align_at_least(fs_sink_ctf_field_class_as_struct(parent_fc
),
581 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
582 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
584 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
585 fs_sink_ctf_field_class_as_array_base(parent_fc
);
587 array_base_fc
->base
.alignment
= alignment
;
595 static inline int translate_structure_field_class_members(
596 struct ctx
*ctx
, struct fs_sink_ctf_field_class_struct
*struct_fc
, const bt_field_class
*ir_fc
)
601 for (i
= 0; i
< bt_field_class_structure_get_member_count(ir_fc
); i
++) {
602 const bt_field_class_structure_member
*member
;
604 const bt_field_class
*memb_ir_fc
;
606 member
= bt_field_class_structure_borrow_member_by_index_const(ir_fc
, i
);
607 name
= bt_field_class_structure_member_get_name(member
);
608 memb_ir_fc
= bt_field_class_structure_member_borrow_field_class_const(member
);
609 ret
= cur_path_stack_push(ctx
, i
, name
, true, memb_ir_fc
, &struct_fc
->base
);
611 BT_COMP_LOGE("Cannot translate structure field class member: "
617 ret
= translate_field_class(ctx
);
619 BT_COMP_LOGE("Cannot translate structure field class member: "
625 cur_path_stack_pop(ctx
);
632 static inline int translate_structure_field_class(struct ctx
*ctx
)
635 struct fs_sink_ctf_field_class_struct
*fc
= fs_sink_ctf_field_class_struct_create_empty(
636 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
639 append_to_parent_field_class(ctx
, &fc
->base
);
640 ret
= translate_structure_field_class_members(ctx
, fc
, fc
->base
.ir_fc
);
645 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
652 * This function protects a given variant FC option name (with the `_`
653 * prefix) if required. On success, `name_buf->str` contains the variant
654 * FC option name to use (original option name or protected if
657 * One of the goals of `sink.ctf.fs` is to write a CTF trace which is as
658 * close as possible to an original CTF trace as decoded by
661 * This scenario is valid in CTF 1.8:
673 * Once in trace IR, the enumeration FC mapping names and variant FC
674 * option names are kept as is. For this reason, we don't want to
675 * protect the variant FC option names here (by prepending `_`): this
676 * would make the variant FC option name and the enumeration FC mapping
679 * This scenario is also valid in CTF 1.8:
691 * Once in trace IR, the enumeration FC mapping names are kept as is,
692 * but the `_HELLO` variant FC option name becomes `HELLO` (unprotected
693 * for presentation, as recommended by CTF 1.8). When going back to
694 * TSDL, we need to protect `HELLO` so that it becomes `_HELLO` to match
695 * the corresponding enumeration FC mapping name.
697 * This scenario is also valid in CTF 1.8:
709 * Once in trace IR, the enumeration FC mapping names are kept as is,
710 * but the `__HELLO` variant FC option name becomes `_HELLO`
711 * (unprotected). When going back to TSDL, we need to protect `_HELLO`
712 * so that it becomes `__HELLO` to match the corresponding enumeration
715 * `src.ctf.fs` always uses the _same_ integer range sets for a selector
716 * FC mapping and a corresponding variant FC option. We can use that
717 * fact to find the original variant FC option names by matching variant
718 * FC options and enumeration FC mappings by range set.
720 static int maybe_protect_variant_option_name(const bt_field_class
*ir_var_fc
,
721 const bt_field_class
*ir_tag_fc
, uint64_t opt_i
,
726 bt_field_class_type ir_var_fc_type
;
727 const bt_integer_range_set_unsigned
*opt_ranges_unsigned
= NULL
;
728 const bt_integer_range_set_signed
*opt_ranges_signed
= NULL
;
729 const char *mapping_label
= NULL
;
730 const char *ir_opt_name
;
731 const bt_field_class_variant_option
*base_var_opt
;
732 bool force_protect
= false;
734 ir_var_fc_type
= bt_field_class_get_type(ir_var_fc
);
735 base_var_opt
= bt_field_class_variant_borrow_option_by_index_const(ir_var_fc
, opt_i
);
736 BT_ASSERT(base_var_opt
);
737 ir_opt_name
= bt_field_class_variant_option_get_name(base_var_opt
);
738 BT_ASSERT(ir_opt_name
);
741 * Check if the variant FC option name is required to be
742 * protected (reserved TSDL keyword or starts with `_`). In that
743 * case, the name of the selector FC mapping we find must match
744 * exactly the protected name.
746 force_protect
= must_protect_identifier(ir_opt_name
);
748 g_string_assign(name_buf
, "_");
749 g_string_append(name_buf
, ir_opt_name
);
751 g_string_assign(name_buf
, ir_opt_name
);
754 /* Borrow option's ranges */
755 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
) {
756 /* No ranges: we're done */
759 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
760 const bt_field_class_variant_with_selector_field_integer_unsigned_option
*var_opt
=
761 bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const(
763 opt_ranges_unsigned
=
764 bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
767 const bt_field_class_variant_with_selector_field_integer_signed_option
*var_opt
=
768 bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const(
771 bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const(
775 /* Find corresponding mapping by range set in selector FC */
776 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_tag_fc
); i
++) {
777 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
778 const bt_field_class_enumeration_mapping
*mapping_base
;
779 const bt_field_class_enumeration_unsigned_mapping
*mapping
;
780 const bt_integer_range_set_unsigned
*mapping_ranges
;
783 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(ir_tag_fc
, i
);
785 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(mapping
);
787 if (bt_integer_range_set_unsigned_is_equal(opt_ranges_unsigned
, mapping_ranges
)) {
788 /* We have a winner */
790 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(mapping
);
791 mapping_label
= bt_field_class_enumeration_mapping_get_label(mapping_base
);
795 const bt_field_class_enumeration_mapping
*mapping_base
;
796 const bt_field_class_enumeration_signed_mapping
*mapping
;
797 const bt_integer_range_set_signed
*mapping_ranges
;
799 mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(ir_tag_fc
, i
);
800 mapping_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(mapping
);
802 if (bt_integer_range_set_signed_is_equal(opt_ranges_signed
, mapping_ranges
)) {
803 /* We have a winner */
804 mapping_base
= bt_field_class_enumeration_signed_mapping_as_mapping_const(mapping
);
805 mapping_label
= bt_field_class_enumeration_mapping_get_label(mapping_base
);
811 if (!mapping_label
) {
812 /* Range set not found: invalid selector for CTF 1.8 */
818 * If the enumeration FC mapping name is not the same as the
819 * variant FC option name and we didn't protect already, try
820 * protecting the option name and check again.
822 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
828 if (mapping_label
[0] == '\0') {
833 g_string_assign(name_buf
, "_");
834 g_string_append(name_buf
, ir_opt_name
);
836 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
846 static inline int translate_option_field_class(struct ctx
*ctx
)
848 struct fs_sink_ctf_field_class_option
*fc
= fs_sink_ctf_field_class_option_create_empty(
849 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
850 const bt_field_class
*content_ir_fc
=
851 bt_field_class_option_borrow_field_class_const(fc
->base
.ir_fc
);
857 * CTF 1.8 does not support the option field class type. To
858 * write something anyway, this component translates this type
859 * to a variant field class where the options are:
861 * * An empty structure field class.
862 * * The optional field class itself.
864 * The "tag" is always generated/before in that case (an 8-bit
865 * unsigned enumeration field class).
867 append_to_parent_field_class(ctx
, &fc
->base
);
868 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, content_ir_fc
, &fc
->base
);
870 BT_COMP_LOGE_STR("Cannot translate option field class content.");
874 ret
= translate_field_class(ctx
);
876 BT_COMP_LOGE_STR("Cannot translate option field class content.");
880 cur_path_stack_pop(ctx
);
881 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
887 static inline int translate_variant_field_class(struct ctx
*ctx
)
891 struct fs_sink_ctf_field_class_variant
*fc
= fs_sink_ctf_field_class_variant_create_empty(
892 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
893 bt_field_class_type ir_fc_type
;
894 const bt_field_path
*ir_selector_field_path
= NULL
;
895 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
896 GString
*name_buf
= g_string_new(NULL
);
897 bt_value
*prot_opt_names
= bt_value_array_create();
902 BT_ASSERT(prot_opt_names
);
903 ir_fc_type
= bt_field_class_get_type(fc
->base
.ir_fc
);
904 opt_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
906 if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_VARIANT_WITH_SELECTOR_FIELD
)) {
907 ir_selector_field_path
=
908 bt_field_class_variant_with_selector_field_borrow_selector_field_path_const(
910 BT_ASSERT(ir_selector_field_path
);
913 /* Resolve tag field class before appending to parent */
914 resolve_field_class(ctx
, ir_selector_field_path
, fc
->tag_ref
, &fc
->tag_is_before
, &tgt_fc
);
916 if (ir_selector_field_path
&& tgt_fc
) {
917 uint64_t mapping_count
;
918 uint64_t option_count
;
920 /* CTF 1.8: selector FC must be an enumeration FC */
921 bt_field_class_type type
= bt_field_class_get_type(tgt_fc
->ir_fc
);
923 if (!bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
924 fc
->tag_is_before
= true;
929 * Call maybe_protect_variant_option_name() for each
930 * option below. In that case we also want selector FC
931 * to contain as many mappings as the variant FC has
934 mapping_count
= bt_field_class_enumeration_get_mapping_count(tgt_fc
->ir_fc
);
935 option_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
937 if (mapping_count
!= option_count
) {
938 fc
->tag_is_before
= true;
943 * No compatible selector field class for CTF 1.8:
944 * create the appropriate selector field class.
946 fc
->tag_is_before
= true;
952 * First pass: detect any option name clash with option name
953 * protection. In that case, we don't fail: just create the
954 * selector field class before the variant field class.
956 * After this, `prot_opt_names` contains the final option names,
957 * potentially protected if needed. They can still be invalid
958 * TSDL identifiers however; this will be checked by
959 * cur_path_stack_push().
961 for (i
= 0; i
< opt_count
; i
++) {
962 if (!fc
->tag_is_before
) {
963 BT_ASSERT(tgt_fc
->ir_fc
);
964 ret
= maybe_protect_variant_option_name(fc
->base
.ir_fc
, tgt_fc
->ir_fc
, i
, name_buf
);
966 fc
->tag_is_before
= true;
970 ret
= bt_value_array_append_string_element(prot_opt_names
, name_buf
->str
);
976 for (i
= 0; i
< opt_count
; i
++) {
978 const bt_value
*opt_name_a
=
979 bt_value_array_borrow_element_by_index_const(prot_opt_names
, i
);
981 for (j
= 0; j
< opt_count
; j
++) {
982 const bt_value
*opt_name_b
;
988 opt_name_b
= bt_value_array_borrow_element_by_index_const(prot_opt_names
, j
);
989 if (bt_value_is_equal(opt_name_a
, opt_name_b
)) {
991 * Variant FC option names are not
992 * unique when protected.
994 fc
->tag_is_before
= true;
995 goto append_to_parent
;
1001 append_to_parent_field_class(ctx
, &fc
->base
);
1003 for (i
= 0; i
< opt_count
; i
++) {
1004 const bt_field_class_variant_option
*opt
;
1005 const bt_field_class
*opt_ir_fc
;
1006 const bt_value
*prot_opt_name_val
=
1007 bt_value_array_borrow_element_by_index_const(prot_opt_names
, i
);
1008 const char *prot_opt_name
= bt_value_string_get(prot_opt_name_val
);
1010 BT_ASSERT(prot_opt_name
);
1011 opt
= bt_field_class_variant_borrow_option_by_index_const(fc
->base
.ir_fc
, i
);
1012 opt_ir_fc
= bt_field_class_variant_option_borrow_field_class_const(opt
);
1015 * We don't ask cur_path_stack_push() to protect the
1016 * option name because it's already protected at this
1019 ret
= cur_path_stack_push(ctx
, i
, prot_opt_name
, false, opt_ir_fc
, &fc
->base
);
1021 BT_COMP_LOGE("Cannot translate variant field class option: "
1027 ret
= translate_field_class(ctx
);
1029 BT_COMP_LOGE("Cannot translate variant field class option: "
1035 cur_path_stack_pop(ctx
);
1040 g_string_free(name_buf
, TRUE
);
1043 bt_value_put_ref(prot_opt_names
);
1047 static inline int translate_static_array_field_class(struct ctx
*ctx
)
1049 struct fs_sink_ctf_field_class_array
*fc
= fs_sink_ctf_field_class_array_create_empty(
1050 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1051 const bt_field_class
*elem_ir_fc
=
1052 bt_field_class_array_borrow_element_field_class_const(fc
->base
.base
.ir_fc
);
1056 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1057 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
, &fc
->base
.base
);
1059 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1063 ret
= translate_field_class(ctx
);
1065 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1069 cur_path_stack_pop(ctx
);
1070 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1076 static inline int translate_dynamic_array_field_class(struct ctx
*ctx
)
1078 struct fs_sink_ctf_field_class_sequence
*fc
= fs_sink_ctf_field_class_sequence_create_empty(
1079 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1080 const bt_field_class
*elem_ir_fc
=
1081 bt_field_class_array_borrow_element_field_class_const(fc
->base
.base
.ir_fc
);
1086 /* Resolve length field class before appending to parent */
1087 if (bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
) ==
1088 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
) {
1089 resolve_field_class(
1091 bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const(
1092 fc
->base
.base
.ir_fc
),
1093 fc
->length_ref
, &fc
->length_is_before
, NULL
);
1096 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1097 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
, &fc
->base
.base
);
1099 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1103 ret
= translate_field_class(ctx
);
1105 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1109 cur_path_stack_pop(ctx
);
1110 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1116 static inline int translate_bool_field_class(struct ctx
*ctx
)
1118 struct fs_sink_ctf_field_class_bool
*fc
= fs_sink_ctf_field_class_bool_create(
1119 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1122 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1126 static inline int translate_bit_array_field_class(struct ctx
*ctx
)
1128 struct fs_sink_ctf_field_class_bit_array
*fc
= fs_sink_ctf_field_class_bit_array_create(
1129 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1132 append_to_parent_field_class(ctx
, &fc
->base
);
1136 static inline int translate_integer_field_class(struct ctx
*ctx
)
1138 struct fs_sink_ctf_field_class_int
*fc
= fs_sink_ctf_field_class_int_create(
1139 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1142 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1146 static inline int translate_real_field_class(struct ctx
*ctx
)
1148 struct fs_sink_ctf_field_class_float
*fc
= fs_sink_ctf_field_class_float_create(
1149 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1152 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1156 static inline int translate_string_field_class(struct ctx
*ctx
)
1158 struct fs_sink_ctf_field_class_string
*fc
= fs_sink_ctf_field_class_string_create(
1159 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1162 append_to_parent_field_class(ctx
, &fc
->base
);
1167 * Translates a field class, recursively.
1169 * The field class's IR field class, parent field class, and index
1170 * within its parent are in the context's current path's top element
1171 * (cur_path_stack_top()).
1173 static int translate_field_class(struct ctx
*ctx
)
1176 bt_field_class_type ir_fc_type
= bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
);
1178 if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BOOL
) {
1179 ret
= translate_bool_field_class(ctx
);
1180 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BIT_ARRAY
) {
1181 ret
= translate_bit_array_field_class(ctx
);
1182 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_INTEGER
)) {
1183 ret
= translate_integer_field_class(ctx
);
1184 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_REAL
)) {
1185 ret
= translate_real_field_class(ctx
);
1186 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRING
) {
1187 ret
= translate_string_field_class(ctx
);
1188 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRUCTURE
) {
1189 ret
= translate_structure_field_class(ctx
);
1190 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
1191 ret
= translate_static_array_field_class(ctx
);
1192 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
)) {
1193 ret
= translate_dynamic_array_field_class(ctx
);
1194 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_OPTION
)) {
1195 ret
= translate_option_field_class(ctx
);
1196 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_VARIANT
)) {
1197 ret
= translate_variant_field_class(ctx
);
1205 static int set_field_ref(struct fs_sink_ctf_field_class
*fc
, const char *fc_name
,
1206 struct fs_sink_ctf_field_class
*parent_fc
)
1209 GString
*field_ref
= NULL
;
1211 const char *tgt_type
;
1212 struct fs_sink_ctf_field_class_struct
*parent_struct_fc
=
1213 fs_sink_ctf_field_class_as_struct(parent_fc
);
1215 unsigned int suffix
= 0;
1217 if (!fc_name
|| !parent_fc
|| parent_fc
->type
!= FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1224 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1227 * CTF 1.8 does not support the option field class type.
1228 * To write something anyway, this component translates
1229 * this type to a variant field class where the options
1232 * * An empty structure field class.
1233 * * The optional field class itself.
1235 * Because the option field class becomes a CTF variant
1236 * field class, we use the term "tag" too here.
1238 * The "tag" is always generated/before in that case (an
1239 * 8-bit unsigned enumeration field class).
1241 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
1243 field_ref
= opt_fc
->tag_ref
;
1248 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1250 struct fs_sink_ctf_field_class_sequence
*seq_fc
= fs_sink_ctf_field_class_as_sequence(fc
);
1252 field_ref
= seq_fc
->length_ref
;
1253 is_before
= seq_fc
->length_is_before
;
1257 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1259 struct fs_sink_ctf_field_class_variant
*var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
1261 field_ref
= var_fc
->tag_ref
;
1262 is_before
= var_fc
->tag_is_before
;
1270 BT_ASSERT(field_ref
);
1276 /* Initial field ref */
1277 g_string_printf(field_ref
, "__%s_%s", fc_name
, tgt_type
);
1280 * Make sure field ref does not clash with an existing field
1281 * class name within the same parent structure field class.
1284 bool name_ok
= true;
1286 for (i
= 0; i
< parent_struct_fc
->members
->len
; i
++) {
1287 struct fs_sink_ctf_named_field_class
*named_fc
=
1288 fs_sink_ctf_field_class_struct_borrow_member_by_index(parent_struct_fc
, i
);
1290 if (strcmp(field_ref
->str
, named_fc
->name
->str
) == 0) {
1298 /* No clash: we're done */
1302 /* Append suffix and try again */
1303 g_string_printf(field_ref
, "__%s_%s_%u", fc_name
, tgt_type
, suffix
);
1312 * This function recursively sets field refs of sequence and variant
1313 * field classes when they are immediately before, avoiding name clashes
1314 * with existing field class names.
1316 * It can fail at this point if, for example, a sequence field class of
1317 * which to set the length's field ref has something else than a
1318 * structure field class as its parent: in this case, there's no
1319 * location to place the length field class immediately before the
1320 * sequence field class.
1322 static int set_field_refs(struct fs_sink_ctf_field_class
* const fc
, const char *fc_name
,
1323 struct fs_sink_ctf_field_class
*parent_fc
)
1326 enum fs_sink_ctf_field_class_type fc_type
;
1332 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1334 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
1336 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1341 ret
= set_field_refs(opt_fc
->content_fc
, NULL
, fc
);
1348 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
1349 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1353 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
1354 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
1355 struct fs_sink_ctf_named_field_class
*named_fc
;
1357 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1358 struct_fc
= fs_sink_ctf_field_class_as_struct(fc
);
1359 len
= struct_fc
->members
->len
;
1361 var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
1362 len
= var_fc
->options
->len
;
1363 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1369 for (i
= 0; i
< len
; i
++) {
1370 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1371 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
1373 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
1376 ret
= set_field_refs(named_fc
->fc
, named_fc
->name
->str
, fc
);
1384 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
1385 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1387 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
1388 fs_sink_ctf_field_class_as_array_base(fc
);
1390 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
1391 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1397 ret
= set_field_refs(array_base_fc
->elem_fc
, NULL
, fc
);
1413 * This function translates a root scope trace IR field class to
1414 * a CTF IR field class.
1416 * The resulting CTF IR field class is written to `*fc` so that it
1417 * exists as the parent object's (stream class or event class) true root
1418 * field class during the recursive translation for resolving purposes.
1419 * This is also why this function creates the empty structure field
1420 * class and then calls translate_structure_field_class_members() to
1423 static int translate_scope_field_class(struct ctx
*ctx
, bt_field_path_scope scope
,
1424 struct fs_sink_ctf_field_class
**fc
,
1425 const bt_field_class
*ir_fc
)
1433 BT_ASSERT(bt_field_class_get_type(ir_fc
) == BT_FIELD_CLASS_TYPE_STRUCTURE
);
1435 *fc
= &fs_sink_ctf_field_class_struct_create_empty(ir_fc
, UINT64_C(-1))->base
;
1437 ctx
->cur_scope
= scope
;
1438 BT_ASSERT(ctx
->cur_path
->len
== 0);
1439 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, ir_fc
, NULL
);
1441 BT_COMP_LOGE("Cannot translate scope structure field class: "
1448 translate_structure_field_class_members(ctx
, fs_sink_ctf_field_class_as_struct(*fc
), ir_fc
);
1450 BT_COMP_LOGE("Cannot translate scope structure field class: "
1456 cur_path_stack_pop(ctx
);
1458 /* Set field refs for preceding targets */
1459 ret
= set_field_refs(*fc
, NULL
, NULL
);
1465 static inline void ctx_init(struct ctx
*ctx
, struct fs_sink_comp
*fs_sink
)
1467 memset(ctx
, 0, sizeof(struct ctx
));
1468 ctx
->cur_path
= g_array_new(FALSE
, TRUE
, sizeof(struct field_path_elem
));
1469 BT_ASSERT(ctx
->cur_path
);
1470 ctx
->log_level
= fs_sink
->log_level
;
1471 ctx
->self_comp
= fs_sink
->self_comp
;
1474 static inline void ctx_fini(struct ctx
*ctx
)
1476 if (ctx
->cur_path
) {
1477 g_array_free(ctx
->cur_path
, TRUE
);
1478 ctx
->cur_path
= NULL
;
1482 static int translate_event_class(struct fs_sink_comp
*fs_sink
, struct fs_sink_ctf_stream_class
*sc
,
1483 const bt_event_class
*ir_ec
,
1484 struct fs_sink_ctf_event_class
**out_ec
)
1488 struct fs_sink_ctf_event_class
*ec
;
1493 ctx_init(&ctx
, fs_sink
);
1494 ec
= fs_sink_ctf_event_class_create(sc
, ir_ec
);
1498 ret
= translate_scope_field_class(
1499 &ctx
, BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
, &ec
->spec_context_fc
,
1500 bt_event_class_borrow_specific_context_field_class_const(ir_ec
));
1505 ret
= translate_scope_field_class(&ctx
, BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
, &ec
->payload_fc
,
1506 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
);
1649 int try_translate_stream_class_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1650 struct fs_sink_ctf_trace
*trace
,
1651 const bt_stream_class
*ir_sc
,
1652 struct fs_sink_ctf_stream_class
**out_sc
)
1660 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1661 *out_sc
= (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
];
1663 if ((*out_sc
)->ir_sc
== ir_sc
) {
1668 ret
= translate_stream_class(fs_sink
, trace
, ir_sc
, out_sc
);
1674 struct fs_sink_ctf_trace
*translate_trace_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1675 const bt_trace
*ir_trace
)
1679 struct fs_sink_ctf_trace
*trace
= NULL
;
1681 /* Check that trace's environment is TSDL-compatible */
1682 count
= bt_trace_get_environment_entry_count(ir_trace
);
1683 for (i
= 0; i
< count
; i
++) {
1685 const bt_value
*val
;
1687 bt_trace_borrow_environment_entry_by_index_const(ir_trace
, i
, &name
, &val
);
1689 if (!ist_valid_identifier(name
)) {
1690 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
, fs_sink
->self_comp
,
1691 "Unsupported trace class's environment entry name: "
1697 switch (bt_value_get_type(val
)) {
1698 case BT_VALUE_TYPE_SIGNED_INTEGER
:
1699 case BT_VALUE_TYPE_STRING
:
1702 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
, fs_sink
->self_comp
,
1703 "Unsupported trace class's environment entry value type: "
1705 bt_common_value_type_string(bt_value_get_type(val
)));
1710 trace
= fs_sink_ctf_trace_create(ir_trace
);