Move to kernel style SPDX license identifiers
[babeltrace.git] / src / plugins / ctf / fs-sink / translate-trace-ir-to-ctf-ir.c
index 7bd9423b032790cba022387a180ab4b22cf6bca8..19ca9dcdbbee3d7194ce2095195ea6bf513ea4b4 100644 (file)
@@ -1,27 +1,15 @@
 /*
- * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
+ * SPDX-License-Identifier: MIT
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
  */
 
+#define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
+#define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
 #define BT_LOG_TAG "PLUGIN/SINK.CTF.FS/TRANSLATE-TRACE-IR-TO-CTF-IR"
-#include "logging.h"
+#include "logging/comp-logging.h"
+
+#include "translate-trace-ir-to-ctf-ir.h"
 
 #include <babeltrace2/babeltrace.h>
 #include "common/macros.h"
@@ -32,6 +20,7 @@
 #include <string.h>
 #include <glib.h>
 
+#include "fs-sink.h"
 #include "fs-sink-ctf-meta.h"
 
 struct field_path_elem {
@@ -46,13 +35,16 @@ struct field_path_elem {
 };
 
 struct ctx {
+       bt_logging_level log_level;
+       bt_self_component *self_comp;
+
        /* Weak */
        struct fs_sink_ctf_stream_class *cur_sc;
 
        /* Weak */
        struct fs_sink_ctf_event_class *cur_ec;
 
-       bt_scope cur_scope;
+       bt_field_path_scope cur_scope;
 
        /*
         * Array of `struct field_path_elem` */
@@ -92,10 +84,106 @@ end:
        return is_reserved;
 }
 
+static const char *reserved_tsdl_keywords[] = {
+       "align",
+       "callsite",
+       "const",
+       "char",
+       "clock",
+       "double",
+       "enum",
+       "env",
+       "event",
+       "floating_point",
+       "float",
+       "integer",
+       "int",
+       "long",
+       "short",
+       "signed",
+       "stream",
+       "string",
+       "struct",
+       "trace",
+       "typealias",
+       "typedef",
+       "unsigned",
+       "variant",
+       "void",
+       "_Bool",
+       "_Complex",
+       "_Imaginary",
+};
+
+static inline
+bool ist_valid_identifier(const char *name)
+{
+       const char *at;
+       uint64_t i;
+       bool ist_valid = true;
+
+       /* Make sure the name is not a reserved keyword */
+       for (i = 0; i < sizeof(reserved_tsdl_keywords) / sizeof(*reserved_tsdl_keywords);
+                       i++) {
+               if (strcmp(name, reserved_tsdl_keywords[i]) == 0) {
+                       ist_valid = false;
+                       goto end;
+               }
+       }
+
+       /* Make sure the name is not an empty string */
+       if (strlen(name) == 0) {
+               ist_valid = false;
+               goto end;
+       }
+
+       /* Make sure the name starts with a letter or `_` */
+       if (!isalpha((unsigned char) name[0]) && name[0] != '_') {
+               ist_valid = false;
+               goto end;
+       }
+
+       /* Make sure the name only contains letters, digits, and `_` */
+       for (at = name; *at != '\0'; at++) {
+               if (!isalnum((unsigned char) *at) && *at != '_') {
+                       ist_valid = false;
+                       goto end;
+               }
+       }
+
+end:
+       return ist_valid;
+}
+
+static inline
+bool must_protect_identifier(const char *name)
+{
+       uint64_t i;
+       bool must_protect = false;
+
+       /* Protect a reserved keyword */
+       for (i = 0; i < sizeof(reserved_tsdl_keywords) / sizeof(*reserved_tsdl_keywords);
+                       i++) {
+               if (strcmp(name, reserved_tsdl_keywords[i]) == 0) {
+                       must_protect = true;
+                       goto end;
+               }
+       }
+
+       /* Protect an identifier which already starts with `_` */
+       if (name[0] == '_') {
+               must_protect = true;
+               goto end;
+       }
+
+end:
+       return must_protect;
+}
+
 static inline
 int cur_path_stack_push(struct ctx *ctx,
-               uint64_t index_in_parent, const char *ir_name,
-               const bt_field_class *ir_fc,
+               uint64_t index_in_parent, const char *name,
+               bool force_protect_name, const bt_field_class *ir_fc,
                struct fs_sink_ctf_field_class *parent_fc)
 {
        int ret = 0;
@@ -104,29 +192,35 @@ int cur_path_stack_push(struct ctx *ctx,
        g_array_set_size(ctx->cur_path, ctx->cur_path->len + 1);
        field_path_elem = cur_path_stack_top(ctx);
        field_path_elem->index_in_parent = index_in_parent;
-       field_path_elem->name = g_string_new(ir_name);
-
-       if (ir_name) {
-               if (ctx->cur_scope == BT_SCOPE_PACKET_CONTEXT) {
-                       if (is_reserved_member_name(ir_name, "packet_size") ||
-                                       is_reserved_member_name(ir_name, "content_size") ||
-                                       is_reserved_member_name(ir_name, "timestamp_begin") ||
-                                       is_reserved_member_name(ir_name, "timestamp_end") ||
-                                       is_reserved_member_name(ir_name, "events_discarded") ||
-                                       is_reserved_member_name(ir_name, "packet_seq_num")) {
-                               BT_LOGE("Unsupported reserved TSDL structure field class member "
+       field_path_elem->name = g_string_new(NULL);
+
+       if (name) {
+               if (force_protect_name) {
+                       g_string_assign(field_path_elem->name, "_");
+               }
+
+               g_string_append(field_path_elem->name, name);
+
+               if (ctx->cur_scope == BT_FIELD_PATH_SCOPE_PACKET_CONTEXT) {
+                       if (is_reserved_member_name(name, "packet_size") ||
+                                       is_reserved_member_name(name, "content_size") ||
+                                       is_reserved_member_name(name, "timestamp_begin") ||
+                                       is_reserved_member_name(name, "timestamp_end") ||
+                                       is_reserved_member_name(name, "events_discarded") ||
+                                       is_reserved_member_name(name, "packet_seq_num")) {
+                               BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
                                        "or variant field class option name: name=\"%s\"",
-                                       ir_name);
+                                       name);
                                ret = -1;
                                goto end;
                        }
                }
 
-               ret = fs_sink_ctf_protect_name(field_path_elem->name);
-               if (ret) {
-                       BT_LOGE("Unsupported non-TSDL structure field class member "
+               if (!ist_valid_identifier(field_path_elem->name->str)) {
+                       ret = -1;
+                       BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
                                "or variant field class option name: name=\"%s\"",
-                               ir_name);
+                               field_path_elem->name->str);
                        goto end;
                }
        }
@@ -168,7 +262,8 @@ void cur_path_stack_pop(struct ctx *ctx)
  */
 static
 int create_relative_field_ref(struct ctx *ctx,
-               const bt_field_path *tgt_ir_field_path, GString *tgt_field_ref)
+               const bt_field_path *tgt_ir_field_path, GString *tgt_field_ref,
+               struct fs_sink_ctf_field_class **user_tgt_fc)
 {
        int ret = 0;
        struct fs_sink_ctf_field_class *tgt_fc = NULL;
@@ -179,24 +274,24 @@ int create_relative_field_ref(struct ctx *ctx,
 
        /* Get target field class's name */
        switch (bt_field_path_get_root_scope(tgt_ir_field_path)) {
-       case BT_SCOPE_PACKET_CONTEXT:
+       case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT:
                BT_ASSERT(ctx->cur_sc);
                tgt_fc = ctx->cur_sc->packet_context_fc;
                break;
-       case BT_SCOPE_EVENT_COMMON_CONTEXT:
+       case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT:
                BT_ASSERT(ctx->cur_sc);
                tgt_fc = ctx->cur_sc->event_common_context_fc;
                break;
-       case BT_SCOPE_EVENT_SPECIFIC_CONTEXT:
+       case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT:
                BT_ASSERT(ctx->cur_ec);
                tgt_fc = ctx->cur_ec->spec_context_fc;
                break;
-       case BT_SCOPE_EVENT_PAYLOAD:
+       case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD:
                BT_ASSERT(ctx->cur_ec);
                tgt_fc = ctx->cur_ec->payload_fc;
                break;
        default:
-               abort();
+               bt_common_abort();
        }
 
        i = 0;
@@ -210,6 +305,13 @@ int create_relative_field_ref(struct ctx *ctx,
                BT_ASSERT(tgt_fc);
                BT_ASSERT(fp_item);
 
+               if (bt_field_path_item_get_type(fp_item) ==
+                               BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT) {
+                       /* Not supported by CTF 1.8 */
+                       ret = -1;
+                       goto end;
+               }
+
                switch (tgt_fc->type) {
                case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
                        BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
@@ -237,7 +339,7 @@ int create_relative_field_ref(struct ctx *ctx,
                        break;
                }
                default:
-                       abort();
+                       bt_common_abort();
                }
 
                if (named_fc) {
@@ -254,8 +356,8 @@ int create_relative_field_ref(struct ctx *ctx,
        /* Find target field class having this name in current context */
        for (si = ctx->cur_path->len - 1; si >= 0; si--) {
                struct fs_sink_ctf_field_class *fc;
-               struct fs_sink_ctf_field_class_struct *struct_fc;
-               struct fs_sink_ctf_field_class_variant *var_fc;
+               struct fs_sink_ctf_field_class_struct *struct_fc = NULL;
+               struct fs_sink_ctf_field_class_variant *var_fc = NULL;
                struct fs_sink_ctf_named_field_class *named_fc;
                uint64_t len;
 
@@ -301,6 +403,10 @@ int create_relative_field_ref(struct ctx *ctx,
                                if (named_fc->fc == tgt_fc) {
                                        g_string_assign(tgt_field_ref,
                                                tgt_fc_name);
+
+                                       if (user_tgt_fc) {
+                                               *user_tgt_fc = tgt_fc;
+                                       }
                                } else {
                                        /*
                                         * Using only the target field
@@ -328,35 +434,36 @@ end:
  */
 static
 int create_absolute_field_ref(struct ctx *ctx,
-               const bt_field_path *tgt_ir_field_path, GString *tgt_field_ref)
+               const bt_field_path *tgt_ir_field_path, GString *tgt_field_ref,
+               struct fs_sink_ctf_field_class **user_tgt_fc)
 {
        int ret = 0;
        struct fs_sink_ctf_field_class *fc = NULL;
        uint64_t i;
 
        switch (bt_field_path_get_root_scope(tgt_ir_field_path)) {
-       case BT_SCOPE_PACKET_CONTEXT:
+       case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT:
                BT_ASSERT(ctx->cur_sc);
                fc = ctx->cur_sc->packet_context_fc;
                g_string_assign(tgt_field_ref, "stream.packet.context");
                break;
-       case BT_SCOPE_EVENT_COMMON_CONTEXT:
+       case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT:
                BT_ASSERT(ctx->cur_sc);
                fc = ctx->cur_sc->event_common_context_fc;
                g_string_assign(tgt_field_ref, "stream.event.context");
                break;
-       case BT_SCOPE_EVENT_SPECIFIC_CONTEXT:
+       case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT:
                BT_ASSERT(ctx->cur_ec);
                fc = ctx->cur_ec->spec_context_fc;
                g_string_assign(tgt_field_ref, "event.context");
                break;
-       case BT_SCOPE_EVENT_PAYLOAD:
+       case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD:
                BT_ASSERT(ctx->cur_ec);
                fc = ctx->cur_ec->payload_fc;
                g_string_assign(tgt_field_ref, "event.fields");
                break;
        default:
-               abort();
+               bt_common_abort();
        }
 
        BT_ASSERT(fc);
@@ -390,7 +497,7 @@ int create_absolute_field_ref(struct ctx *ctx,
                                bt_field_path_item_index_get_index(fp_item));
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
 
                BT_ASSERT(named_fc);
@@ -399,6 +506,10 @@ int create_absolute_field_ref(struct ctx *ctx,
                fc = named_fc->fc;
        }
 
+       if (user_tgt_fc) {
+               *user_tgt_fc = fc;
+       }
+
 end:
        return ret;
 }
@@ -413,10 +524,11 @@ end:
 static
 void resolve_field_class(struct ctx *ctx,
                const bt_field_path *tgt_ir_field_path,
-               GString *tgt_field_ref, bool *create_before)
+               GString *tgt_field_ref, bool *create_before,
+               struct fs_sink_ctf_field_class **user_tgt_fc)
 {
        int ret;
-       bt_scope tgt_scope;
+       bt_field_path_scope tgt_scope;
 
        *create_before = false;
 
@@ -443,19 +555,18 @@ void resolve_field_class(struct ctx *ctx,
                 *    requesting field class (fallback).
                 */
                ret = create_relative_field_ref(ctx, tgt_ir_field_path,
-                       tgt_field_ref);
+                       tgt_field_ref, user_tgt_fc);
                if (ret) {
                        ret = create_absolute_field_ref(ctx, tgt_ir_field_path,
-                               tgt_field_ref);
+                               tgt_field_ref, user_tgt_fc);
                        if (ret) {
                                *create_before = true;
-                               ret = 0;
                                goto end;
                        }
                }
        } else {
                ret = create_absolute_field_ref(ctx, tgt_ir_field_path,
-                       tgt_field_ref);
+                       tgt_field_ref, user_tgt_fc);
 
                /* It must always work in previous scopes */
                BT_ASSERT(ret == 0);
@@ -480,6 +591,16 @@ void append_to_parent_field_class(struct ctx *ctx,
                fs_sink_ctf_field_class_struct_append_member((void *) parent_fc,
                        cur_path_stack_top(ctx)->name->str, fc);
                break;
+       case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
+       {
+               struct fs_sink_ctf_field_class_option *opt_fc =
+                       (void *) parent_fc;
+
+               BT_ASSERT(!opt_fc->content_fc);
+               opt_fc->content_fc = fc;
+               opt_fc->base.alignment = fc->alignment;
+               break;
+       }
        case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
                fs_sink_ctf_field_class_variant_append_option((void *) parent_fc,
                        cur_path_stack_top(ctx)->name->str, fc);
@@ -496,7 +617,7 @@ void append_to_parent_field_class(struct ctx *ctx,
                break;
        }
        default:
-               abort();
+               bt_common_abort();
        }
 }
 
@@ -545,17 +666,17 @@ int translate_structure_field_class_members(struct ctx *ctx,
                name = bt_field_class_structure_member_get_name(member);
                memb_ir_fc = bt_field_class_structure_member_borrow_field_class_const(
                        member);
-               ret = cur_path_stack_push(ctx, i, name, memb_ir_fc,
+               ret = cur_path_stack_push(ctx, i, name, true, memb_ir_fc,
                        (void *) struct_fc);
                if (ret) {
-                       BT_LOGE("Cannot translate structure field class member: "
+                       BT_COMP_LOGE("Cannot translate structure field class member: "
                                "name=\"%s\"", name);
                        goto end;
                }
 
                ret = translate_field_class(ctx);
                if (ret) {
-                       BT_LOGE("Cannot translate structure field class member: "
+                       BT_COMP_LOGE("Cannot translate structure field class member: "
                                "name=\"%s\"", name);
                        goto end;
                }
@@ -589,6 +710,258 @@ end:
        return ret;
 }
 
+/*
+ * This function protects a given variant FC option name (with the `_`
+ * prefix) if required. On success, `name_buf->str` contains the variant
+ * FC option name to use (original option name or protected if
+ * required).
+ *
+ * One of the goals of `sink.ctf.fs` is to write a CTF trace which is as
+ * close as possible to an original CTF trace as decoded by
+ * `src.ctf.fs`.
+ *
+ * This scenario is valid in CTF 1.8:
+ *
+ *     enum {
+ *         HELLO,
+ *         MEOW
+ *     } tag;
+ *
+ *     variant <tag> {
+ *         int HELLO;
+ *         string MEOW;
+ *     };
+ *
+ * Once in trace IR, the enumeration FC mapping names and variant FC
+ * option names are kept as is. For this reason, we don't want to
+ * protect the variant FC option names here (by prepending `_`): this
+ * would make the variant FC option name and the enumeration FC mapping
+ * name not match.
+ *
+ * This scenario is also valid in CTF 1.8:
+ *
+ *     enum {
+ *         _HELLO,
+ *         MEOW
+ *     } tag;
+ *
+ *     variant <tag> {
+ *         int _HELLO;
+ *         string MEOW;
+ *     };
+ *
+ * Once in trace IR, the enumeration FC mapping names are kept as is,
+ * but the `_HELLO` variant FC option name becomes `HELLO` (unprotected
+ * for presentation, as recommended by CTF 1.8). When going back to
+ * TSDL, we need to protect `HELLO` so that it becomes `_HELLO` to match
+ * the corresponding enumeration FC mapping name.
+ *
+ * This scenario is also valid in CTF 1.8:
+ *
+ *     enum {
+ *         __HELLO,
+ *         MEOW
+ *     } tag;
+ *
+ *     variant <tag> {
+ *         int __HELLO;
+ *         string MEOW;
+ *     };
+ *
+ * Once in trace IR, the enumeration FC mapping names are kept as is,
+ * but the `__HELLO` variant FC option name becomes `_HELLO`
+ * (unprotected). When going back to TSDL, we need to protect `_HELLO`
+ * so that it becomes `__HELLO` to match the corresponding enumeration
+ * FC mapping name.
+ *
+ * `src.ctf.fs` always uses the _same_ integer range sets for a selector
+ * FC mapping and a corresponding variant FC option. We can use that
+ * fact to find the original variant FC option names by matching variant
+ * FC options and enumeration FC mappings by range set.
+ */
+static
+int maybe_protect_variant_option_name(const bt_field_class *ir_var_fc,
+               const bt_field_class *ir_tag_fc, uint64_t opt_i,
+               GString *name_buf)
+{
+       int ret = 0;
+       uint64_t i;
+       bt_field_class_type ir_var_fc_type;
+       const void *opt_ranges = NULL;
+       const char *mapping_label = NULL;
+       const char *ir_opt_name;
+       const bt_field_class_variant_option *base_var_opt;
+       bool force_protect = false;
+
+       ir_var_fc_type = bt_field_class_get_type(ir_var_fc);
+       base_var_opt = bt_field_class_variant_borrow_option_by_index_const(
+               ir_var_fc, opt_i);
+       BT_ASSERT(base_var_opt);
+       ir_opt_name = bt_field_class_variant_option_get_name(base_var_opt);
+       BT_ASSERT(ir_opt_name);
+
+       /*
+        * Check if the variant FC option name is required to be
+        * protected (reserved TSDL keyword or starts with `_`). In that
+        * case, the name of the selector FC mapping we find must match
+        * exactly the protected name.
+        */
+       force_protect = must_protect_identifier(ir_opt_name);
+       if (force_protect) {
+               g_string_assign(name_buf, "_");
+               g_string_append(name_buf, ir_opt_name);
+       } else {
+               g_string_assign(name_buf, ir_opt_name);
+       }
+
+       /* Borrow option's ranges */
+       if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD) {
+               /* No ranges: we're done */
+               goto end;
+       } if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD) {
+               const bt_field_class_variant_with_selector_field_integer_unsigned_option *var_opt =
+                       bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const(
+                               ir_var_fc, opt_i);
+               opt_ranges =
+                       bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
+                               var_opt);
+       } else {
+               const bt_field_class_variant_with_selector_field_integer_signed_option *var_opt =
+                       bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const(
+                               ir_var_fc, opt_i);
+               opt_ranges =
+                       bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const(
+                               var_opt);
+       }
+
+       /* Find corresponding mapping by range set in selector FC */
+       for (i = 0; i < bt_field_class_enumeration_get_mapping_count(ir_tag_fc);
+                       i++) {
+               if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD) {
+                       const bt_field_class_enumeration_mapping *mapping_base;
+                       const bt_field_class_enumeration_unsigned_mapping *mapping;
+                       const bt_integer_range_set_unsigned *mapping_ranges;
+
+                       mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
+                               ir_tag_fc, i);
+                       mapping_ranges = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
+                               mapping);
+
+                       if (bt_integer_range_set_unsigned_is_equal(opt_ranges,
+                                       mapping_ranges)) {
+                               /* We have a winner */
+                               mapping_base =
+                                       bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
+                                               mapping);
+                               mapping_label =
+                                       bt_field_class_enumeration_mapping_get_label(
+                                               mapping_base);
+                               break;
+                       }
+               } else {
+                       const bt_field_class_enumeration_mapping *mapping_base;
+                       const bt_field_class_enumeration_signed_mapping *mapping;
+                       const bt_integer_range_set_signed *mapping_ranges;
+
+                       mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
+                               ir_tag_fc, i);
+                       mapping_ranges = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
+                               mapping);
+
+                       if (bt_integer_range_set_signed_is_equal(opt_ranges,
+                                       mapping_ranges)) {
+                               /* We have a winner */
+                               mapping_base =
+                                       bt_field_class_enumeration_signed_mapping_as_mapping_const(
+                                               mapping);
+                               mapping_label =
+                                       bt_field_class_enumeration_mapping_get_label(
+                                               mapping_base);
+                               break;
+                       }
+               }
+       }
+
+       if (!mapping_label) {
+               /* Range set not found: invalid selector for CTF 1.8 */
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * If the enumeration FC mapping name is not the same as the
+        * variant FC option name and we didn't protect already, try
+        * protecting the option name and check again.
+        */
+       if (strcmp(mapping_label, name_buf->str) != 0) {
+               if (force_protect) {
+                       ret = -1;
+                       goto end;
+               }
+
+               if (mapping_label[0] == '\0') {
+                       ret = -1;
+                       goto end;
+               }
+
+               g_string_assign(name_buf, "_");
+               g_string_append(name_buf, ir_opt_name);
+
+               if (strcmp(mapping_label, name_buf->str) != 0) {
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+static inline
+int translate_option_field_class(struct ctx *ctx)
+{
+       struct fs_sink_ctf_field_class_option *fc =
+               fs_sink_ctf_field_class_option_create_empty(
+                       cur_path_stack_top(ctx)->ir_fc,
+                       cur_path_stack_top(ctx)->index_in_parent);
+       const bt_field_class *content_ir_fc =
+               bt_field_class_option_borrow_field_class_const(fc->base.ir_fc);
+       int ret;
+
+       BT_ASSERT(fc);
+
+       /*
+        * CTF 1.8 does not support the option field class type. To
+        * write something anyway, this component translates this type
+        * to a variant field class where the options are:
+        *
+        * * An empty structure field class.
+        * * The optional field class itself.
+        *
+        * The "tag" is always generated/before in that case (an 8-bit
+        * unsigned enumeration field class).
+        */
+       append_to_parent_field_class(ctx, (void *) fc);
+       ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, content_ir_fc,
+               (void *) fc);
+       if (ret) {
+               BT_COMP_LOGE_STR("Cannot translate option field class content.");
+               goto end;
+       }
+
+       ret = translate_field_class(ctx);
+       if (ret) {
+               BT_COMP_LOGE_STR("Cannot translate option field class content.");
+               goto end;
+       }
+
+       cur_path_stack_pop(ctx);
+       update_parent_field_class_alignment(ctx, fc->base.alignment);
+
+end:
+       return ret;
+}
+
 static inline
 int translate_variant_field_class(struct ctx *ctx)
 {
@@ -598,38 +971,158 @@ int translate_variant_field_class(struct ctx *ctx)
                fs_sink_ctf_field_class_variant_create_empty(
                        cur_path_stack_top(ctx)->ir_fc,
                        cur_path_stack_top(ctx)->index_in_parent);
+       bt_field_class_type ir_fc_type;
+       const bt_field_path *ir_selector_field_path = NULL;
+       struct fs_sink_ctf_field_class *tgt_fc = NULL;
+       GString *name_buf = g_string_new(NULL);
+       bt_value *prot_opt_names = bt_value_array_create();
+       uint64_t opt_count;
 
        BT_ASSERT(fc);
+       BT_ASSERT(name_buf);
+       BT_ASSERT(prot_opt_names);
+       ir_fc_type = bt_field_class_get_type(fc->base.ir_fc);
+       opt_count = bt_field_class_variant_get_option_count(fc->base.ir_fc);
+
+       if (bt_field_class_type_is(ir_fc_type,
+                       BT_FIELD_CLASS_TYPE_VARIANT_WITH_SELECTOR_FIELD)) {
+               ir_selector_field_path = bt_field_class_variant_with_selector_field_borrow_selector_field_path_const(
+                       fc->base.ir_fc);
+               BT_ASSERT(ir_selector_field_path);
+       }
 
        /* Resolve tag field class before appending to parent */
-       resolve_field_class(ctx,
-               bt_field_class_variant_borrow_selector_field_path_const(
-                       fc->base.ir_fc), fc->tag_ref, &fc->tag_is_before);
+       resolve_field_class(ctx, ir_selector_field_path, fc->tag_ref,
+               &fc->tag_is_before, &tgt_fc);
+
+       if (ir_selector_field_path && tgt_fc) {
+               uint64_t mapping_count;
+               uint64_t option_count;
+
+               /* CTF 1.8: selector FC must be an enumeration FC */
+               bt_field_class_type type = bt_field_class_get_type(
+                       tgt_fc->ir_fc);
+
+               if (!bt_field_class_type_is(type,
+                               BT_FIELD_CLASS_TYPE_ENUMERATION)) {
+                       fc->tag_is_before = true;
+                       goto validate_opts;
+               }
 
+               /*
+                * Call maybe_protect_variant_option_name() for each
+                * option below. In that case we also want selector FC
+                * to contain as many mappings as the variant FC has
+                * options.
+                */
+               mapping_count = bt_field_class_enumeration_get_mapping_count(
+                       tgt_fc->ir_fc);
+               option_count = bt_field_class_variant_get_option_count(
+                       fc->base.ir_fc);
+
+               if (mapping_count != option_count) {
+                       fc->tag_is_before = true;
+                       goto validate_opts;
+               }
+       } else {
+               /*
+                * No compatible selector field class for CTF 1.8:
+                * create the appropriate selector field class.
+                */
+               fc->tag_is_before = true;
+               goto validate_opts;
+       }
+
+validate_opts:
+       /*
+        * First pass: detect any option name clash with option name
+        * protection. In that case, we don't fail: just create the
+        * selector field class before the variant field class.
+        *
+        * After this, `prot_opt_names` contains the final option names,
+        * potentially protected if needed. They can still be invalid
+        * TSDL identifiers however; this will be checked by
+        * cur_path_stack_push().
+        */
+       for (i = 0; i < opt_count; i++) {
+               if (!fc->tag_is_before) {
+                       BT_ASSERT(tgt_fc->ir_fc);
+                       ret = maybe_protect_variant_option_name(fc->base.ir_fc,
+                               tgt_fc->ir_fc, i, name_buf);
+                       if (ret) {
+                               fc->tag_is_before = true;
+                       }
+               }
+
+               ret = bt_value_array_append_string_element(prot_opt_names,
+                       name_buf->str);
+               if (ret) {
+                       goto end;
+               }
+       }
+
+       for (i = 0; i < opt_count; i++) {
+               uint64_t j;
+               const bt_value *opt_name_a =
+                       bt_value_array_borrow_element_by_index_const(
+                               prot_opt_names, i);
+
+               for (j = 0; j < opt_count; j++) {
+                       const bt_value *opt_name_b;
+
+                       if (i == j) {
+                               continue;
+                       }
+
+                       opt_name_b =
+                               bt_value_array_borrow_element_by_index_const(
+                                       prot_opt_names, j);
+                       if (bt_value_is_equal(opt_name_a, opt_name_b)) {
+                               /*
+                                * Variant FC option names are not
+                                * unique when protected.
+                                */
+                               fc->tag_is_before = true;
+                               goto append_to_parent;
+                       }
+               }
+       }
+
+append_to_parent:
        append_to_parent_field_class(ctx, (void *) fc);
 
-       for (i = 0; i < bt_field_class_variant_get_option_count(fc->base.ir_fc);
-                       i++) {
+       for (i = 0; i < opt_count; i++) {
                const bt_field_class_variant_option *opt;
-               const char *name;
                const bt_field_class *opt_ir_fc;
+               const bt_value *prot_opt_name_val =
+                       bt_value_array_borrow_element_by_index_const(
+                               prot_opt_names, i);
+               const char *prot_opt_name = bt_value_string_get(
+                       prot_opt_name_val);
 
+               BT_ASSERT(prot_opt_name);
                opt = bt_field_class_variant_borrow_option_by_index_const(
                        fc->base.ir_fc, i);
-               name = bt_field_class_variant_option_get_name(opt);
                opt_ir_fc = bt_field_class_variant_option_borrow_field_class_const(
                        opt);
-               ret = cur_path_stack_push(ctx, i, name, opt_ir_fc, (void *) fc);
+
+               /*
+                * We don't ask cur_path_stack_push() to protect the
+                * option name because it's already protected at this
+                * point.
+                */
+               ret = cur_path_stack_push(ctx, i, prot_opt_name, false,
+                       opt_ir_fc, (void *) fc);
                if (ret) {
-                       BT_LOGE("Cannot translate variant field class option: "
-                               "name=\"%s\"", name);
+                       BT_COMP_LOGE("Cannot translate variant field class option: "
+                               "name=\"%s\"", prot_opt_name);
                        goto end;
                }
 
                ret = translate_field_class(ctx);
                if (ret) {
-                       BT_LOGE("Cannot translate variant field class option: "
-                               "name=\"%s\"", name);
+                       BT_COMP_LOGE("Cannot translate variant field class option: "
+                               "name=\"%s\"", prot_opt_name);
                        goto end;
                }
 
@@ -637,6 +1130,11 @@ int translate_variant_field_class(struct ctx *ctx)
        }
 
 end:
+       if (name_buf) {
+               g_string_free(name_buf, TRUE);
+       }
+
+       bt_value_put_ref(prot_opt_names);
        return ret;
 }
 
@@ -654,16 +1152,16 @@ int translate_static_array_field_class(struct ctx *ctx)
 
        BT_ASSERT(fc);
        append_to_parent_field_class(ctx, (void *) fc);
-       ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, elem_ir_fc,
+       ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, elem_ir_fc,
                (void *) fc);
        if (ret) {
-               BT_LOGE_STR("Cannot translate static array field class element.");
+               BT_COMP_LOGE_STR("Cannot translate static array field class element.");
                goto end;
        }
 
        ret = translate_field_class(ctx);
        if (ret) {
-               BT_LOGE_STR("Cannot translate static array field class element.");
+               BT_COMP_LOGE_STR("Cannot translate static array field class element.");
                goto end;
        }
 
@@ -689,22 +1187,25 @@ int translate_dynamic_array_field_class(struct ctx *ctx)
        BT_ASSERT(fc);
 
        /* Resolve length field class before appending to parent */
-       resolve_field_class(ctx,
-               bt_field_class_dynamic_array_borrow_length_field_path_const(
-                       fc->base.base.ir_fc),
-               fc->length_ref, &fc->length_is_before);
+       if (bt_field_class_get_type(cur_path_stack_top(ctx)->ir_fc) ==
+                       BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD) {
+               resolve_field_class(ctx,
+                       bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const(
+                               fc->base.base.ir_fc),
+                       fc->length_ref, &fc->length_is_before, NULL);
+       }
 
        append_to_parent_field_class(ctx, (void *) fc);
-       ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, elem_ir_fc,
+       ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, elem_ir_fc,
                (void *) fc);
        if (ret) {
-               BT_LOGE_STR("Cannot translate dynamic array field class element.");
+               BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
                goto end;
        }
 
        ret = translate_field_class(ctx);
        if (ret) {
-               BT_LOGE_STR("Cannot translate dynamic array field class element.");
+               BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
                goto end;
        }
 
@@ -715,6 +1216,32 @@ end:
        return ret;
 }
 
+static inline
+int translate_bool_field_class(struct ctx *ctx)
+{
+       struct fs_sink_ctf_field_class_bool *fc =
+               fs_sink_ctf_field_class_bool_create(
+                       cur_path_stack_top(ctx)->ir_fc,
+                       cur_path_stack_top(ctx)->index_in_parent);
+
+       BT_ASSERT(fc);
+       append_to_parent_field_class(ctx, (void *) fc);
+       return 0;
+}
+
+static inline
+int translate_bit_array_field_class(struct ctx *ctx)
+{
+       struct fs_sink_ctf_field_class_bit_array *fc =
+               fs_sink_ctf_field_class_bit_array_create(
+                       cur_path_stack_top(ctx)->ir_fc,
+                       cur_path_stack_top(ctx)->index_in_parent);
+
+       BT_ASSERT(fc);
+       append_to_parent_field_class(ctx, (void *) fc);
+       return 0;
+}
+
 static inline
 int translate_integer_field_class(struct ctx *ctx)
 {
@@ -765,34 +1292,36 @@ static
 int translate_field_class(struct ctx *ctx)
 {
        int ret;
-
-       switch (bt_field_class_get_type(cur_path_stack_top(ctx)->ir_fc)) {
-       case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER:
-       case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER:
-       case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
-       case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
+       bt_field_class_type ir_fc_type =
+               bt_field_class_get_type(cur_path_stack_top(ctx)->ir_fc);
+
+       if (ir_fc_type == BT_FIELD_CLASS_TYPE_BOOL) {
+               ret = translate_bool_field_class(ctx);
+       } else if (ir_fc_type == BT_FIELD_CLASS_TYPE_BIT_ARRAY) {
+               ret = translate_bit_array_field_class(ctx);
+       } else if (bt_field_class_type_is(ir_fc_type,
+                       BT_FIELD_CLASS_TYPE_INTEGER)) {
                ret = translate_integer_field_class(ctx);
-               break;
-       case BT_FIELD_CLASS_TYPE_REAL:
+       } else if (bt_field_class_type_is(ir_fc_type,
+                       BT_FIELD_CLASS_TYPE_REAL)) {
                ret = translate_real_field_class(ctx);
-               break;
-       case BT_FIELD_CLASS_TYPE_STRING:
+       } else if (ir_fc_type == BT_FIELD_CLASS_TYPE_STRING) {
                ret = translate_string_field_class(ctx);
-               break;
-       case BT_FIELD_CLASS_TYPE_STRUCTURE:
+       } else if (ir_fc_type == BT_FIELD_CLASS_TYPE_STRUCTURE) {
                ret = translate_structure_field_class(ctx);
-               break;
-       case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
+       } else if (ir_fc_type == BT_FIELD_CLASS_TYPE_STATIC_ARRAY) {
                ret = translate_static_array_field_class(ctx);
-               break;
-       case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
+       } else if (bt_field_class_type_is(ir_fc_type,
+                       BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY)) {
                ret = translate_dynamic_array_field_class(ctx);
-               break;
-       case BT_FIELD_CLASS_TYPE_VARIANT:
+       } else if (bt_field_class_type_is(ir_fc_type,
+                       BT_FIELD_CLASS_TYPE_OPTION)) {
+               ret = translate_option_field_class(ctx);
+       } else if (bt_field_class_type_is(ir_fc_type,
+                       BT_FIELD_CLASS_TYPE_VARIANT)) {
                ret = translate_variant_field_class(ctx);
-               break;
-       default:
-               abort();
+       } else {
+               bt_common_abort();
        }
 
        return ret;
@@ -819,6 +1348,30 @@ int set_field_ref(struct fs_sink_ctf_field_class *fc, const char *fc_name,
        }
 
        switch (fc->type) {
+       case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
+       {
+               /*
+                * CTF 1.8 does not support the option field class type.
+                * To write something anyway, this component translates
+                * this type to a variant field class where the options
+                * are:
+                *
+                * * An empty structure field class.
+                * * The optional field class itself.
+                *
+                * Because the option field class becomes a CTF variant
+                * field class, we use the term "tag" too here.
+                *
+                * The "tag" is always generated/before in that case (an
+                * 8-bit unsigned enumeration field class).
+                */
+               struct fs_sink_ctf_field_class_option *opt_fc = (void *) fc;
+
+               field_ref = opt_fc->tag_ref;
+               is_before = true;
+               tgt_type = "tag";
+               break;
+       }
        case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
        {
                struct fs_sink_ctf_field_class_sequence *seq_fc = (void *) fc;
@@ -838,7 +1391,7 @@ int set_field_ref(struct fs_sink_ctf_field_class *fc, const char *fc_name,
                break;
        }
        default:
-               abort();
+               bt_common_abort();
        }
 
        BT_ASSERT(field_ref);
@@ -906,12 +1459,28 @@ int set_field_refs(struct fs_sink_ctf_field_class * const fc,
        fc_type = fc->type;
 
        switch (fc_type) {
+       case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
+       {
+               struct fs_sink_ctf_field_class_option *opt_fc = (void *) fc;
+
+               ret = set_field_ref(fc, fc_name, parent_fc);
+               if (ret) {
+                       goto end;
+               }
+
+               ret = set_field_refs(opt_fc->content_fc, NULL, fc);
+               if (ret) {
+                       goto end;
+               }
+
+               break;
+       }
        case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
        case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
        {
                uint64_t i;
                uint64_t len;
-               struct fs_sink_ctf_field_class_struct *struct_fc;
+               struct fs_sink_ctf_field_class_struct *struct_fc = NULL;
                struct fs_sink_ctf_field_class_variant *var_fc = NULL;
                struct fs_sink_ctf_named_field_class *named_fc;
 
@@ -985,7 +1554,7 @@ end:
  * fill it.
  */
 static
-int translate_scope_field_class(struct ctx *ctx, bt_scope scope,
+int translate_scope_field_class(struct ctx *ctx, bt_field_path_scope scope,
                struct fs_sink_ctf_field_class **fc,
                const bt_field_class *ir_fc)
 {
@@ -1003,16 +1572,16 @@ int translate_scope_field_class(struct ctx *ctx, bt_scope scope,
        BT_ASSERT(*fc);
        ctx->cur_scope = scope;
        BT_ASSERT(ctx->cur_path->len == 0);
-       ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, ir_fc, NULL);
+       ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, ir_fc, NULL);
        if (ret) {
-               BT_LOGE("Cannot translate scope structure field class: "
+               BT_COMP_LOGE("Cannot translate scope structure field class: "
                        "scope=%d", scope);
                goto end;
        }
 
        ret = translate_structure_field_class_members(ctx, (void *) *fc, ir_fc);
        if (ret) {
-               BT_LOGE("Cannot translate scope structure field class: "
+               BT_COMP_LOGE("Cannot translate scope structure field class: "
                        "scope=%d", scope);
                goto end;
        }
@@ -1027,12 +1596,14 @@ end:
 }
 
 static inline
-void ctx_init(struct ctx *ctx)
+void ctx_init(struct ctx *ctx, struct fs_sink_comp *fs_sink)
 {
        memset(ctx, 0, sizeof(struct ctx));
        ctx->cur_path = g_array_new(FALSE, TRUE,
                sizeof(struct field_path_elem));
        BT_ASSERT(ctx->cur_path);
+       ctx->log_level = fs_sink->log_level;
+       ctx->self_comp = fs_sink->self_comp;
 }
 
 static inline
@@ -1045,7 +1616,8 @@ void ctx_fini(struct ctx *ctx)
 }
 
 static
-int translate_event_class(struct fs_sink_ctf_stream_class *sc,
+int translate_event_class(struct fs_sink_comp *fs_sink,
+               struct fs_sink_ctf_stream_class *sc,
                const bt_event_class *ir_ec,
                struct fs_sink_ctf_event_class **out_ec)
 {
@@ -1056,12 +1628,12 @@ int translate_event_class(struct fs_sink_ctf_stream_class *sc,
        BT_ASSERT(sc);
        BT_ASSERT(ir_ec);
 
-       ctx_init(&ctx);
+       ctx_init(&ctx, fs_sink);
        ec = fs_sink_ctf_event_class_create(sc, ir_ec);
        BT_ASSERT(ec);
        ctx.cur_sc = sc;
        ctx.cur_ec = ec;
-       ret = translate_scope_field_class(&ctx, BT_SCOPE_EVENT_SPECIFIC_CONTEXT,
+       ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT,
                &ec->spec_context_fc,
                bt_event_class_borrow_specific_context_field_class_const(
                        ir_ec));
@@ -1069,7 +1641,7 @@ int translate_event_class(struct fs_sink_ctf_stream_class *sc,
                goto end;
        }
 
-       ret = translate_scope_field_class(&ctx, BT_SCOPE_EVENT_PAYLOAD,
+       ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD,
                &ec->payload_fc,
                bt_event_class_borrow_payload_field_class_const(ir_ec));
        if (ret) {
@@ -1084,6 +1656,7 @@ end:
 
 BT_HIDDEN
 int try_translate_event_class_trace_ir_to_ctf_ir(
+               struct fs_sink_comp *fs_sink,
                struct fs_sink_ctf_stream_class *sc,
                const bt_event_class *ir_ec,
                struct fs_sink_ctf_event_class **out_ec)
@@ -1099,21 +1672,22 @@ int try_translate_event_class_trace_ir_to_ctf_ir(
                goto end;
        }
 
-       ret = translate_event_class(sc, ir_ec, out_ec);
+       ret = translate_event_class(fs_sink, sc, ir_ec, out_ec);
 
 end:
        return ret;
 }
 
-bool default_clock_class_name_exists(struct fs_sink_ctf_trace_class *tc,
+static
+bool default_clock_class_name_exists(struct fs_sink_ctf_trace *trace,
                const char *name)
 {
        bool exists = false;
        uint64_t i;
 
-       for (i = 0; i < tc->stream_classes->len; i++) {
+       for (i = 0; i < trace->stream_classes->len; i++) {
                struct fs_sink_ctf_stream_class *sc =
-                       tc->stream_classes->pdata[i];
+                       trace->stream_classes->pdata[i];
 
                if (sc->default_clock_class_name->len == 0) {
                        /* No default clock class */
@@ -1139,7 +1713,7 @@ void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class *sc)
        g_string_assign(sc->default_clock_class_name, "");
        sprintf(buf, "default");
 
-       while (default_clock_class_name_exists(sc->tc, buf)) {
+       while (default_clock_class_name_exists(sc->trace, buf)) {
                sprintf(buf, "default%u", suffix);
                suffix++;
        }
@@ -1148,17 +1722,18 @@ void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class *sc)
 }
 
 static
-int translate_stream_class(struct fs_sink_ctf_trace_class *tc,
+int translate_stream_class(struct fs_sink_comp *fs_sink,
+               struct fs_sink_ctf_trace *trace,
                const bt_stream_class *ir_sc,
                struct fs_sink_ctf_stream_class **out_sc)
 {
        int ret = 0;
        struct ctx ctx;
 
-       BT_ASSERT(tc);
+       BT_ASSERT(trace);
        BT_ASSERT(ir_sc);
-       ctx_init(&ctx);
-       *out_sc = fs_sink_ctf_stream_class_create(tc, ir_sc);
+       ctx_init(&ctx, fs_sink);
+       *out_sc = fs_sink_ctf_stream_class_create(trace, ir_sc);
        BT_ASSERT(*out_sc);
 
        /* Set default clock class's protected name, if any */
@@ -1168,14 +1743,21 @@ int translate_stream_class(struct fs_sink_ctf_trace_class *tc,
 
                if (name) {
                        /* Try original name, protected */
+                       g_string_assign((*out_sc)->default_clock_class_name,
+                               "");
+
+                       if (must_protect_identifier(name)) {
+                               g_string_assign(
+                                       (*out_sc)->default_clock_class_name,
+                                       "_");
+                       }
+
                        g_string_assign((*out_sc)->default_clock_class_name,
                                name);
-                       ret = fs_sink_ctf_protect_name(
-                               (*out_sc)->default_clock_class_name);
-                       if (ret) {
+                       if (!ist_valid_identifier(
+                                       (*out_sc)->default_clock_class_name->str)) {
                                /* Invalid: create a new name */
                                make_unique_default_clock_class_name(*out_sc);
-                               ret = 0;
                        }
                } else {
                        /* No name: create a name */
@@ -1184,7 +1766,7 @@ int translate_stream_class(struct fs_sink_ctf_trace_class *tc,
        }
 
        ctx.cur_sc = *out_sc;
-       ret = translate_scope_field_class(&ctx, BT_SCOPE_PACKET_CONTEXT,
+       ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_PACKET_CONTEXT,
                &(*out_sc)->packet_context_fc,
                bt_stream_class_borrow_packet_context_field_class_const(ir_sc));
        if (ret) {
@@ -1201,7 +1783,7 @@ int translate_stream_class(struct fs_sink_ctf_trace_class *tc,
                        (void *) (*out_sc)->packet_context_fc, 8);
        }
 
-       ret = translate_scope_field_class(&ctx, BT_SCOPE_EVENT_COMMON_CONTEXT,
+       ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT,
                &(*out_sc)->event_common_context_fc,
                bt_stream_class_borrow_event_common_context_field_class_const(
                        ir_sc));
@@ -1222,49 +1804,52 @@ end:
 
 BT_HIDDEN
 int try_translate_stream_class_trace_ir_to_ctf_ir(
-               struct fs_sink_ctf_trace_class *tc,
+               struct fs_sink_comp *fs_sink,
+               struct fs_sink_ctf_trace *trace,
                const bt_stream_class *ir_sc,
                struct fs_sink_ctf_stream_class **out_sc)
 {
        int ret = 0;
        uint64_t i;
 
-       BT_ASSERT(tc);
+       BT_ASSERT(trace);
        BT_ASSERT(ir_sc);
 
-       for (i = 0; i < tc->stream_classes->len; i++) {
-               *out_sc = tc->stream_classes->pdata[i];
+       for (i = 0; i < trace->stream_classes->len; i++) {
+               *out_sc = trace->stream_classes->pdata[i];
 
                if ((*out_sc)->ir_sc == ir_sc) {
                        goto end;
                }
        }
 
-       ret = translate_stream_class(tc, ir_sc, out_sc);
+       ret = translate_stream_class(fs_sink, trace, ir_sc, out_sc);
 
 end:
        return ret;
 }
 
 BT_HIDDEN
-struct fs_sink_ctf_trace_class *translate_trace_class_trace_ir_to_ctf_ir(
-               const bt_trace_class *ir_tc)
+struct fs_sink_ctf_trace *translate_trace_trace_ir_to_ctf_ir(
+               struct fs_sink_comp *fs_sink, const bt_trace *ir_trace)
 {
        uint64_t count;
        uint64_t i;
-       struct fs_sink_ctf_trace_class *tc = NULL;
+       struct fs_sink_ctf_trace *trace = NULL;
 
-       /* Check that trace class's environment is TSDL-compatible */
-       count = bt_trace_class_get_environment_entry_count(ir_tc);
+       /* Check that trace's environment is TSDL-compatible */
+       count = bt_trace_get_environment_entry_count(ir_trace);
        for (i = 0; i < count; i++) {
                const char *name;
                const bt_value *val;
 
-               bt_trace_class_borrow_environment_entry_by_index_const(
-                       ir_tc, i, &name, &val);
+               bt_trace_borrow_environment_entry_by_index_const(
+                       ir_trace, i, &name, &val);
 
-               if (!fs_sink_ctf_ist_valid_identifier(name)) {
-                       BT_LOGE("Unsupported trace class's environment entry name: "
+               if (!ist_valid_identifier(name)) {
+                       BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, fs_sink->log_level,
+                               fs_sink->self_comp,
+                               "Unsupported trace class's environment entry name: "
                                "name=\"%s\"", name);
                        goto end;
                }
@@ -1274,7 +1859,9 @@ struct fs_sink_ctf_trace_class *translate_trace_class_trace_ir_to_ctf_ir(
                case BT_VALUE_TYPE_STRING:
                        break;
                default:
-                       BT_LOGE("Unsupported trace class's environment entry value type: "
+                       BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, fs_sink->log_level,
+                               fs_sink->self_comp,
+                               "Unsupported trace class's environment entry value type: "
                                "type=%s",
                                bt_common_value_type_string(
                                        bt_value_get_type(val)));
@@ -1282,9 +1869,9 @@ struct fs_sink_ctf_trace_class *translate_trace_class_trace_ir_to_ctf_ir(
                }
        }
 
-       tc = fs_sink_ctf_trace_class_create(ir_tc);
-       BT_ASSERT(tc);
+       trace = fs_sink_ctf_trace_create(ir_trace);
+       BT_ASSERT(trace);
 
 end:
-       return tc;
+       return trace;
 }
This page took 0.043165 seconds and 4 git commands to generate.