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_LOG_TAG "PLUGIN-CTF-FS-SINK-TRANSLATE-TRACE-IR-TO-CTF-IR"
26 #include <babeltrace/babeltrace.h>
27 #include <babeltrace/babeltrace-internal.h>
28 #include <babeltrace/common-internal.h>
29 #include <babeltrace/assert-internal.h>
35 #include "fs-sink-ctf-meta.h"
37 struct field_path_elem
{
38 uint64_t index_in_parent
;
42 const bt_field_class
*ir_fc
;
45 struct fs_sink_ctf_field_class
*parent_fc
;
50 struct fs_sink_ctf_stream_class
*cur_sc
;
53 struct fs_sink_ctf_event_class
*cur_ec
;
58 * Array of `struct field_path_elem` */
63 struct field_path_elem
*cur_path_stack_at(struct ctx
*ctx
, uint64_t i
)
65 BT_ASSERT(i
< ctx
->cur_path
->len
);
66 return &g_array_index(ctx
->cur_path
, struct field_path_elem
, i
);
70 struct field_path_elem
*cur_path_stack_top(struct ctx
*ctx
)
72 BT_ASSERT(ctx
->cur_path
->len
> 0);
73 return cur_path_stack_at(ctx
, ctx
->cur_path
->len
- 1);
77 bool is_reserved_member_name(const char *name
, const char *reserved_name
)
79 bool is_reserved
= false;
81 if (strcmp(name
, reserved_name
) == 0) {
86 if (name
[0] == '_' && strcmp(&name
[1], reserved_name
) == 0) {
96 int cur_path_stack_push(struct ctx
*ctx
,
97 uint64_t index_in_parent
, const char *ir_name
,
98 const bt_field_class
*ir_fc
,
99 struct fs_sink_ctf_field_class
*parent_fc
)
102 struct field_path_elem
*field_path_elem
;
104 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
+ 1);
105 field_path_elem
= cur_path_stack_top(ctx
);
106 field_path_elem
->index_in_parent
= index_in_parent
;
107 field_path_elem
->name
= g_string_new(ir_name
);
110 if (ctx
->cur_scope
== BT_SCOPE_PACKET_CONTEXT
) {
111 if (is_reserved_member_name(ir_name
, "packet_size") ||
112 is_reserved_member_name(ir_name
, "content_size") ||
113 is_reserved_member_name(ir_name
, "timestamp_begin") ||
114 is_reserved_member_name(ir_name
, "timestamp_end") ||
115 is_reserved_member_name(ir_name
, "events_discarded") ||
116 is_reserved_member_name(ir_name
, "packet_seq_num")) {
117 BT_LOGE("Unsupported reserved TSDL structure field class member "
118 "or variant field class option name: name=\"%s\"",
125 ret
= fs_sink_ctf_protect_name(field_path_elem
->name
);
127 BT_LOGE("Unsupported non-TSDL structure field class member "
128 "or variant field class option name: name=\"%s\"",
134 field_path_elem
->ir_fc
= ir_fc
;
135 field_path_elem
->parent_fc
= parent_fc
;
142 void cur_path_stack_pop(struct ctx
*ctx
)
144 struct field_path_elem
*field_path_elem
;
146 BT_ASSERT(ctx
->cur_path
->len
> 0);
147 field_path_elem
= cur_path_stack_top(ctx
);
149 if (field_path_elem
->name
) {
150 g_string_free(field_path_elem
->name
, TRUE
);
151 field_path_elem
->name
= NULL
;
154 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
- 1);
158 * Creates a relative field ref (a single name) from IR field path
159 * `tgt_ir_field_path`.
161 * This function tries to locate the target field class recursively from
162 * the top to the bottom of the context's current path using only the
163 * target field class's own name. This is because many CTF reading tools
164 * do not support a relative field ref with more than one element, for
165 * example `prev_struct.len`.
167 * Returns a negative value if this resolving operation failed.
170 int create_relative_field_ref(struct ctx
*ctx
,
171 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
)
174 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
175 enum fs_sink_ctf_field_class_type tgt_fc_type
;
178 const char *tgt_fc_name
= NULL
;
179 struct field_path_elem
*field_path_elem
;
181 /* Get target field class's name */
182 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
183 case BT_SCOPE_PACKET_CONTEXT
:
184 BT_ASSERT(ctx
->cur_sc
);
185 tgt_fc
= ctx
->cur_sc
->packet_context_fc
;
187 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
188 BT_ASSERT(ctx
->cur_sc
);
189 tgt_fc
= ctx
->cur_sc
->event_common_context_fc
;
191 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
192 BT_ASSERT(ctx
->cur_ec
);
193 tgt_fc
= ctx
->cur_ec
->spec_context_fc
;
195 case BT_SCOPE_EVENT_PAYLOAD
:
196 BT_ASSERT(ctx
->cur_ec
);
197 tgt_fc
= ctx
->cur_ec
->payload_fc
;
204 tgt_fc_type
= tgt_fc
->type
;
206 while (i
< bt_field_path_get_item_count(tgt_ir_field_path
)) {
207 const bt_field_path_item
*fp_item
=
208 bt_field_path_borrow_item_by_index_const(
209 tgt_ir_field_path
, i
);
210 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
215 switch (tgt_fc_type
) {
216 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
217 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
218 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
219 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
221 bt_field_path_item_index_get_index(fp_item
));
223 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
224 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
225 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
226 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
228 bt_field_path_item_index_get_index(fp_item
));
230 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
231 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
233 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
236 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
237 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
);
238 tgt_fc
= array_base_fc
->elem_fc
;
246 tgt_fc
= named_fc
->fc
;
247 tgt_fc_name
= named_fc
->name
->str
;
253 BT_ASSERT(tgt_fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_INT
);
254 BT_ASSERT(tgt_fc_name
);
256 /* Find target field class having this name in current context */
257 for (si
= ctx
->cur_path
->len
- 1; si
>= 0; si
--) {
258 struct fs_sink_ctf_field_class
*fc
;
259 struct fs_sink_ctf_field_class_struct
*struct_fc
;
260 struct fs_sink_ctf_field_class_variant
*var_fc
;
261 struct fs_sink_ctf_named_field_class
*named_fc
;
264 field_path_elem
= cur_path_stack_at(ctx
, (uint64_t) si
);
265 fc
= field_path_elem
->parent_fc
;
267 /* Reached stack's bottom */
273 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
274 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
276 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
277 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
280 /* Not supported by TSDL 1.8 */
285 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
286 struct_fc
= (void *) fc
;
287 len
= struct_fc
->members
->len
;
289 var_fc
= (void *) fc
;
290 len
= var_fc
->options
->len
;
293 for (i
= 0; i
< len
; i
++) {
294 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
295 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
298 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
302 if (strcmp(named_fc
->name
->str
, tgt_fc_name
) == 0) {
303 if (named_fc
->fc
== tgt_fc
) {
304 g_string_assign(tgt_field_ref
,
308 * Using only the target field
309 * class's name, we're not
310 * reaching the target field
311 * class. This is not supported
327 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
329 * Returns a negative value if this resolving operation failed.
332 int create_absolute_field_ref(struct ctx
*ctx
,
333 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
)
336 struct fs_sink_ctf_field_class
*fc
= NULL
;
339 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
340 case BT_SCOPE_PACKET_CONTEXT
:
341 BT_ASSERT(ctx
->cur_sc
);
342 fc
= ctx
->cur_sc
->packet_context_fc
;
343 g_string_assign(tgt_field_ref
, "stream.packet.context");
345 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
346 BT_ASSERT(ctx
->cur_sc
);
347 fc
= ctx
->cur_sc
->event_common_context_fc
;
348 g_string_assign(tgt_field_ref
, "stream.event.context");
350 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
351 BT_ASSERT(ctx
->cur_ec
);
352 fc
= ctx
->cur_ec
->spec_context_fc
;
353 g_string_assign(tgt_field_ref
, "event.context");
355 case BT_SCOPE_EVENT_PAYLOAD
:
356 BT_ASSERT(ctx
->cur_ec
);
357 fc
= ctx
->cur_ec
->payload_fc
;
358 g_string_assign(tgt_field_ref
, "event.fields");
366 for (i
= 0; i
< bt_field_path_get_item_count(tgt_ir_field_path
); i
++) {
367 const bt_field_path_item
*fp_item
=
368 bt_field_path_borrow_item_by_index_const(
369 tgt_ir_field_path
, i
);
370 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
372 if (bt_field_path_item_get_type(fp_item
) !=
373 BT_FIELD_PATH_ITEM_TYPE_INDEX
) {
374 /* Not supported by TSDL 1.8 */
380 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
381 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
382 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
383 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
385 bt_field_path_item_index_get_index(fp_item
));
387 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
388 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
389 BT_FIELD_PATH_ITEM_TYPE_INDEX
);
390 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
392 bt_field_path_item_index_get_index(fp_item
));
399 g_string_append_c(tgt_field_ref
, '.');
400 g_string_append(tgt_field_ref
, named_fc
->name
->str
);
409 * Resolves a target field class located at `tgt_ir_field_path`, writing
410 * the resolved field ref to `tgt_field_ref` and setting
411 * `*create_before` according to whether or not the target field must be
412 * created immediately before (in which case `tgt_field_ref` is
416 void resolve_field_class(struct ctx
*ctx
,
417 const bt_field_path
*tgt_ir_field_path
,
418 GString
*tgt_field_ref
, bool *create_before
)
423 *create_before
= false;
425 if (!tgt_ir_field_path
) {
426 *create_before
= true;
430 tgt_scope
= bt_field_path_get_root_scope(tgt_ir_field_path
);
432 if (tgt_scope
== ctx
->cur_scope
) {
434 * Try, in this order:
436 * 1. Use a relative path, using only the target field
437 * class's name. This is what is the most commonly
438 * supported by popular CTF reading tools.
440 * 2. Use an absolute path. This could fail if there's
441 * an array field class from the current root's field
442 * class to the target field class.
444 * 3. Create the target field class before the
445 * requesting field class (fallback).
447 ret
= create_relative_field_ref(ctx
, tgt_ir_field_path
,
450 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
,
453 *create_before
= true;
459 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
,
462 /* It must always work in previous scopes */
471 int translate_field_class(struct ctx
*ctx
);
474 void append_to_parent_field_class(struct ctx
*ctx
,
475 struct fs_sink_ctf_field_class
*fc
)
477 struct fs_sink_ctf_field_class
*parent_fc
=
478 cur_path_stack_top(ctx
)->parent_fc
;
480 switch (parent_fc
->type
) {
481 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
482 fs_sink_ctf_field_class_struct_append_member((void *) parent_fc
,
483 cur_path_stack_top(ctx
)->name
->str
, fc
);
485 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
486 fs_sink_ctf_field_class_variant_append_option((void *) parent_fc
,
487 cur_path_stack_top(ctx
)->name
->str
, fc
);
489 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
490 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
492 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
495 BT_ASSERT(!array_base_fc
->elem_fc
);
496 array_base_fc
->elem_fc
= fc
;
497 array_base_fc
->base
.alignment
= fc
->alignment
;
506 void update_parent_field_class_alignment(struct ctx
*ctx
,
507 unsigned int alignment
)
509 struct fs_sink_ctf_field_class
*parent_fc
=
510 cur_path_stack_top(ctx
)->parent_fc
;
512 switch (parent_fc
->type
) {
513 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
514 fs_sink_ctf_field_class_struct_align_at_least(
515 (void *) parent_fc
, alignment
);
517 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
518 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
520 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
523 array_base_fc
->base
.alignment
= alignment
;
532 int translate_structure_field_class_members(struct ctx
*ctx
,
533 struct fs_sink_ctf_field_class_struct
*struct_fc
,
534 const bt_field_class
*ir_fc
)
539 for (i
= 0; i
< bt_field_class_structure_get_member_count(ir_fc
); i
++) {
540 const bt_field_class_structure_member
*member
;
542 const bt_field_class
*memb_ir_fc
;
545 bt_field_class_structure_borrow_member_by_index_const(
547 name
= bt_field_class_structure_member_get_name(member
);
548 memb_ir_fc
= bt_field_class_structure_member_borrow_field_class_const(
550 ret
= cur_path_stack_push(ctx
, i
, name
, memb_ir_fc
,
553 BT_LOGE("Cannot translate structure field class member: "
554 "name=\"%s\"", name
);
558 ret
= translate_field_class(ctx
);
560 BT_LOGE("Cannot translate structure field class member: "
561 "name=\"%s\"", name
);
565 cur_path_stack_pop(ctx
);
573 int translate_structure_field_class(struct ctx
*ctx
)
576 struct fs_sink_ctf_field_class_struct
*fc
=
577 fs_sink_ctf_field_class_struct_create_empty(
578 cur_path_stack_top(ctx
)->ir_fc
,
579 cur_path_stack_top(ctx
)->index_in_parent
);
582 append_to_parent_field_class(ctx
, (void *) fc
);
583 ret
= translate_structure_field_class_members(ctx
, fc
, fc
->base
.ir_fc
);
588 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
595 int translate_variant_field_class(struct ctx
*ctx
)
599 struct fs_sink_ctf_field_class_variant
*fc
=
600 fs_sink_ctf_field_class_variant_create_empty(
601 cur_path_stack_top(ctx
)->ir_fc
,
602 cur_path_stack_top(ctx
)->index_in_parent
);
606 /* Resolve tag field class before appending to parent */
607 resolve_field_class(ctx
,
608 bt_field_class_variant_borrow_selector_field_path_const(
609 fc
->base
.ir_fc
), fc
->tag_ref
, &fc
->tag_is_before
);
611 append_to_parent_field_class(ctx
, (void *) fc
);
613 for (i
= 0; i
< bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
615 const bt_field_class_variant_option
*opt
;
617 const bt_field_class
*opt_ir_fc
;
619 opt
= bt_field_class_variant_borrow_option_by_index_const(
621 name
= bt_field_class_variant_option_get_name(opt
);
622 opt_ir_fc
= bt_field_class_variant_option_borrow_field_class_const(
624 ret
= cur_path_stack_push(ctx
, i
, name
, opt_ir_fc
, (void *) fc
);
626 BT_LOGE("Cannot translate variant field class option: "
627 "name=\"%s\"", name
);
631 ret
= translate_field_class(ctx
);
633 BT_LOGE("Cannot translate variant field class option: "
634 "name=\"%s\"", name
);
638 cur_path_stack_pop(ctx
);
646 int translate_static_array_field_class(struct ctx
*ctx
)
648 struct fs_sink_ctf_field_class_array
*fc
=
649 fs_sink_ctf_field_class_array_create_empty(
650 cur_path_stack_top(ctx
)->ir_fc
,
651 cur_path_stack_top(ctx
)->index_in_parent
);
652 const bt_field_class
*elem_ir_fc
=
653 bt_field_class_array_borrow_element_field_class_const(
654 fc
->base
.base
.ir_fc
);
658 append_to_parent_field_class(ctx
, (void *) fc
);
659 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, elem_ir_fc
,
662 BT_LOGE_STR("Cannot translate static array field class element.");
666 ret
= translate_field_class(ctx
);
668 BT_LOGE_STR("Cannot translate static array field class element.");
672 cur_path_stack_pop(ctx
);
673 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
680 int translate_dynamic_array_field_class(struct ctx
*ctx
)
682 struct fs_sink_ctf_field_class_sequence
*fc
=
683 fs_sink_ctf_field_class_sequence_create_empty(
684 cur_path_stack_top(ctx
)->ir_fc
,
685 cur_path_stack_top(ctx
)->index_in_parent
);
686 const bt_field_class
*elem_ir_fc
=
687 bt_field_class_array_borrow_element_field_class_const(
688 fc
->base
.base
.ir_fc
);
693 /* Resolve length field class before appending to parent */
694 resolve_field_class(ctx
,
695 bt_field_class_dynamic_array_borrow_length_field_path_const(
696 fc
->base
.base
.ir_fc
),
697 fc
->length_ref
, &fc
->length_is_before
);
699 append_to_parent_field_class(ctx
, (void *) fc
);
700 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, elem_ir_fc
,
703 BT_LOGE_STR("Cannot translate dynamic array field class element.");
707 ret
= translate_field_class(ctx
);
709 BT_LOGE_STR("Cannot translate dynamic array field class element.");
713 cur_path_stack_pop(ctx
);
714 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
721 int translate_integer_field_class(struct ctx
*ctx
)
723 struct fs_sink_ctf_field_class_int
*fc
=
724 fs_sink_ctf_field_class_int_create(
725 cur_path_stack_top(ctx
)->ir_fc
,
726 cur_path_stack_top(ctx
)->index_in_parent
);
729 append_to_parent_field_class(ctx
, (void *) fc
);
734 int translate_real_field_class(struct ctx
*ctx
)
736 struct fs_sink_ctf_field_class_float
*fc
=
737 fs_sink_ctf_field_class_float_create(
738 cur_path_stack_top(ctx
)->ir_fc
,
739 cur_path_stack_top(ctx
)->index_in_parent
);
742 append_to_parent_field_class(ctx
, (void *) fc
);
747 int translate_string_field_class(struct ctx
*ctx
)
749 struct fs_sink_ctf_field_class_string
*fc
=
750 fs_sink_ctf_field_class_string_create(
751 cur_path_stack_top(ctx
)->ir_fc
,
752 cur_path_stack_top(ctx
)->index_in_parent
);
755 append_to_parent_field_class(ctx
, (void *) fc
);
760 * Translates a field class, recursively.
762 * The field class's IR field class, parent field class, and index
763 * within its parent are in the context's current path's top element
764 * (cur_path_stack_top()).
767 int translate_field_class(struct ctx
*ctx
)
771 switch (bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
)) {
772 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
773 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
774 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
775 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
776 ret
= translate_integer_field_class(ctx
);
778 case BT_FIELD_CLASS_TYPE_REAL
:
779 ret
= translate_real_field_class(ctx
);
781 case BT_FIELD_CLASS_TYPE_STRING
:
782 ret
= translate_string_field_class(ctx
);
784 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
785 ret
= translate_structure_field_class(ctx
);
787 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
788 ret
= translate_static_array_field_class(ctx
);
790 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
791 ret
= translate_dynamic_array_field_class(ctx
);
793 case BT_FIELD_CLASS_TYPE_VARIANT
:
794 ret
= translate_variant_field_class(ctx
);
804 int set_field_ref(struct fs_sink_ctf_field_class
*fc
, const char *fc_name
,
805 struct fs_sink_ctf_field_class
*parent_fc
)
808 GString
*field_ref
= NULL
;
810 const char *tgt_type
;
811 struct fs_sink_ctf_field_class_struct
*parent_struct_fc
=
814 unsigned int suffix
= 0;
816 if (!fc_name
|| !parent_fc
||
817 parent_fc
->type
!= FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
824 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
826 struct fs_sink_ctf_field_class_sequence
*seq_fc
= (void *) fc
;
828 field_ref
= seq_fc
->length_ref
;
829 is_before
= seq_fc
->length_is_before
;
833 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
835 struct fs_sink_ctf_field_class_variant
*var_fc
= (void *) fc
;
837 field_ref
= var_fc
->tag_ref
;
838 is_before
= var_fc
->tag_is_before
;
846 BT_ASSERT(field_ref
);
852 /* Initial field ref */
853 g_string_printf(field_ref
, "__%s_%s", fc_name
, tgt_type
);
856 * Make sure field ref does not clash with an existing field
857 * class name within the same parent structure field class.
862 for (i
= 0; i
< parent_struct_fc
->members
->len
; i
++) {
863 struct fs_sink_ctf_named_field_class
*named_fc
=
864 fs_sink_ctf_field_class_struct_borrow_member_by_index(
865 parent_struct_fc
, i
);
867 if (strcmp(field_ref
->str
, named_fc
->name
->str
) == 0) {
875 /* No clash: we're done */
879 /* Append suffix and try again */
880 g_string_printf(field_ref
, "__%s_%s_%u", fc_name
, tgt_type
,
890 * This function recursively sets field refs of sequence and variant
891 * field classes when they are immediately before, avoiding name clashes
892 * with existing field class names.
894 * It can fail at this point if, for example, a sequence field class of
895 * which to set the length's field ref has something else than a
896 * structure field class as its parent: in this case, there's no
897 * location to place the length field class immediately before the
898 * sequence field class.
901 int set_field_refs(struct fs_sink_ctf_field_class
*fc
, const char *fc_name
,
902 struct fs_sink_ctf_field_class
*parent_fc
)
905 enum fs_sink_ctf_field_class_type fc_type
;
911 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
912 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
916 struct fs_sink_ctf_field_class_struct
*struct_fc
;
917 struct fs_sink_ctf_field_class_variant
*var_fc
;
918 struct fs_sink_ctf_named_field_class
*named_fc
;
920 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
921 struct_fc
= (void *) fc
;
922 len
= struct_fc
->members
->len
;
924 var_fc
= (void *) fc
;
925 len
= var_fc
->options
->len
;
926 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
932 for (i
= 0; i
< len
; i
++) {
933 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
934 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
937 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
941 ret
= set_field_refs(named_fc
->fc
, named_fc
->name
->str
,
950 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
951 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
953 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
956 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
957 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
963 ret
= set_field_refs(array_base_fc
->elem_fc
, NULL
, fc
);
979 * This function translates a root scope trace IR field class to
980 * a CTF IR field class.
982 * The resulting CTF IR field class is written to `*fc` so that it
983 * exists as the parent object's (stream class or event class) true root
984 * field class during the recursive translation for resolving purposes.
985 * This is also why this function creates the empty structure field
986 * class and then calls translate_structure_field_class_members() to
990 int translate_scope_field_class(struct ctx
*ctx
, bt_scope scope
,
991 struct fs_sink_ctf_field_class
**fc
,
992 const bt_field_class
*ir_fc
)
1000 BT_ASSERT(bt_field_class_get_type(ir_fc
) ==
1001 BT_FIELD_CLASS_TYPE_STRUCTURE
);
1003 *fc
= (void *) fs_sink_ctf_field_class_struct_create_empty(
1004 ir_fc
, UINT64_C(-1));
1006 ctx
->cur_scope
= scope
;
1007 BT_ASSERT(ctx
->cur_path
->len
== 0);
1008 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, ir_fc
, NULL
);
1010 BT_LOGE("Cannot translate scope structure field class: "
1015 ret
= translate_structure_field_class_members(ctx
, (void *) *fc
, ir_fc
);
1017 BT_LOGE("Cannot translate scope structure field class: "
1022 cur_path_stack_pop(ctx
);
1024 /* Set field refs for preceding targets */
1025 ret
= set_field_refs(*fc
, NULL
, NULL
);
1032 void ctx_init(struct ctx
*ctx
)
1034 memset(ctx
, 0, sizeof(struct ctx
));
1035 ctx
->cur_path
= g_array_new(FALSE
, TRUE
,
1036 sizeof(struct field_path_elem
));
1037 BT_ASSERT(ctx
->cur_path
);
1041 void ctx_fini(struct ctx
*ctx
)
1043 if (ctx
->cur_path
) {
1044 g_array_free(ctx
->cur_path
, TRUE
);
1045 ctx
->cur_path
= NULL
;
1050 int translate_event_class(struct fs_sink_ctf_stream_class
*sc
,
1051 const bt_event_class
*ir_ec
,
1052 struct fs_sink_ctf_event_class
**out_ec
)
1056 struct fs_sink_ctf_event_class
*ec
;
1062 ec
= fs_sink_ctf_event_class_create(sc
, ir_ec
);
1066 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_EVENT_SPECIFIC_CONTEXT
,
1067 &ec
->spec_context_fc
,
1068 bt_event_class_borrow_specific_context_field_class_const(
1074 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_EVENT_PAYLOAD
,
1076 bt_event_class_borrow_payload_field_class_const(ir_ec
));
1088 int try_translate_event_class_trace_ir_to_ctf_ir(
1089 struct fs_sink_ctf_stream_class
*sc
,
1090 const bt_event_class
*ir_ec
,
1091 struct fs_sink_ctf_event_class
**out_ec
)
1098 /* Check in hash table first */
1099 *out_ec
= g_hash_table_lookup(sc
->event_classes_from_ir
, ir_ec
);
1100 if (likely(*out_ec
)) {
1104 ret
= translate_event_class(sc
, ir_ec
, out_ec
);
1110 bool default_clock_class_name_exists(struct fs_sink_ctf_trace_class
*tc
,
1113 bool exists
= false;
1116 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
1117 struct fs_sink_ctf_stream_class
*sc
=
1118 tc
->stream_classes
->pdata
[i
];
1120 if (sc
->default_clock_class_name
->len
== 0) {
1121 /* No default clock class */
1125 if (strcmp(sc
->default_clock_class_name
->str
, name
) == 0) {
1136 void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class
*sc
)
1138 unsigned int suffix
= 0;
1141 g_string_assign(sc
->default_clock_class_name
, "");
1142 sprintf(buf
, "default");
1144 while (default_clock_class_name_exists(sc
->tc
, buf
)) {
1145 sprintf(buf
, "default%u", suffix
);
1149 g_string_assign(sc
->default_clock_class_name
, buf
);
1153 int translate_stream_class(struct fs_sink_ctf_trace_class
*tc
,
1154 const bt_stream_class
*ir_sc
,
1155 struct fs_sink_ctf_stream_class
**out_sc
)
1163 *out_sc
= fs_sink_ctf_stream_class_create(tc
, ir_sc
);
1166 /* Set default clock class's protected name, if any */
1167 if ((*out_sc
)->default_clock_class
) {
1168 const char *name
= bt_clock_class_get_name(
1169 (*out_sc
)->default_clock_class
);
1171 if (!bt_stream_class_default_clock_is_always_known(ir_sc
)) {
1172 BT_LOGE("Unsupported stream clock which can have an unknown value: "
1174 bt_stream_class_get_name(ir_sc
));
1179 /* Try original name, protected */
1180 g_string_assign((*out_sc
)->default_clock_class_name
,
1182 ret
= fs_sink_ctf_protect_name(
1183 (*out_sc
)->default_clock_class_name
);
1185 /* Invalid: create a new name */
1186 make_unique_default_clock_class_name(*out_sc
);
1190 /* No name: create a name */
1191 make_unique_default_clock_class_name(*out_sc
);
1195 ctx
.cur_sc
= *out_sc
;
1196 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_PACKET_CONTEXT
,
1197 &(*out_sc
)->packet_context_fc
,
1198 bt_stream_class_borrow_packet_context_field_class_const(ir_sc
));
1203 if ((*out_sc
)->packet_context_fc
) {
1205 * Make sure the structure field class's alignment is
1206 * enough: 8 is what we use for our own special members
1207 * in the packet context.
1209 fs_sink_ctf_field_class_struct_align_at_least(
1210 (void *) (*out_sc
)->packet_context_fc
, 8);
1213 ret
= translate_scope_field_class(&ctx
, BT_SCOPE_EVENT_COMMON_CONTEXT
,
1214 &(*out_sc
)->event_common_context_fc
,
1215 bt_stream_class_borrow_event_common_context_field_class_const(
1224 fs_sink_ctf_stream_class_destroy(*out_sc
);
1233 int try_translate_stream_class_trace_ir_to_ctf_ir(
1234 struct fs_sink_ctf_trace_class
*tc
,
1235 const bt_stream_class
*ir_sc
,
1236 struct fs_sink_ctf_stream_class
**out_sc
)
1244 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
1245 *out_sc
= tc
->stream_classes
->pdata
[i
];
1247 if ((*out_sc
)->ir_sc
== ir_sc
) {
1252 ret
= translate_stream_class(tc
, ir_sc
, out_sc
);
1259 struct fs_sink_ctf_trace_class
*translate_trace_class_trace_ir_to_ctf_ir(
1260 const bt_trace_class
*ir_tc
)
1264 struct fs_sink_ctf_trace_class
*tc
= NULL
;
1266 /* Check that trace class's environment is TSDL-compatible */
1267 count
= bt_trace_class_get_environment_entry_count(ir_tc
);
1268 for (i
= 0; i
< count
; i
++) {
1270 const bt_value
*val
;
1272 bt_trace_class_borrow_environment_entry_by_index_const(
1273 ir_tc
, i
, &name
, &val
);
1275 if (!fs_sink_ctf_ist_valid_identifier(name
)) {
1276 BT_LOGE("Unsupported trace class's environment entry name: "
1277 "name=\"%s\"", name
);
1281 switch (bt_value_get_type(val
)) {
1282 case BT_VALUE_TYPE_INTEGER
:
1283 case BT_VALUE_TYPE_STRING
:
1286 BT_LOGE("Unsupported trace class's environment entry value type: "
1288 bt_common_value_type_string(
1289 bt_value_get_type(val
)));
1294 tc
= fs_sink_ctf_trace_class_create(ir_tc
);