Move to kernel style SPDX license identifiers
[babeltrace.git] / src / plugins / ctf / fs-sink / translate-trace-ir-to-ctf-ir.c
index c7be897e657ce06415b9ed34942b51216d27523e..19ca9dcdbbee3d7194ce2095195ea6bf513ea4b4 100644 (file)
@@ -1,29 +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 "plugins/comp-logging.h"
+#include "logging/comp-logging.h"
+
+#include "translate-trace-ir-to-ctf-ir.h"
 
 #include <babeltrace2/babeltrace.h>
 #include "common/macros.h"
@@ -58,7 +44,7 @@ struct ctx {
        /* 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` */
@@ -152,14 +138,14 @@ bool ist_valid_identifier(const char *name)
        }
 
        /* Make sure the name starts with a letter or `_` */
-       if (!isalpha(name[0]) && name[0] != '_') {
+       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(*at) && *at != '_') {
+               if (!isalnum((unsigned char) *at) && *at != '_') {
                        ist_valid = false;
                        goto end;
                }
@@ -215,7 +201,7 @@ int cur_path_stack_push(struct ctx *ctx,
 
                g_string_append(field_path_elem->name, name);
 
-               if (ctx->cur_scope == BT_SCOPE_PACKET_CONTEXT) {
+               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") ||
@@ -288,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;
@@ -319,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) ==
@@ -346,7 +339,7 @@ int create_relative_field_ref(struct ctx *ctx,
                        break;
                }
                default:
-                       abort();
+                       bt_common_abort();
                }
 
                if (named_fc) {
@@ -363,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;
 
@@ -449,28 +442,28 @@ int create_absolute_field_ref(struct ctx *ctx,
        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);
@@ -504,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);
@@ -535,7 +528,7 @@ void resolve_field_class(struct ctx *ctx,
                struct fs_sink_ctf_field_class **user_tgt_fc)
 {
        int ret;
-       bt_scope tgt_scope;
+       bt_field_path_scope tgt_scope;
 
        *create_before = false;
 
@@ -568,7 +561,6 @@ void resolve_field_class(struct ctx *ctx,
                                tgt_field_ref, user_tgt_fc);
                        if (ret) {
                                *create_before = true;
-                               ret = 0;
                                goto end;
                        }
                }
@@ -599,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);
@@ -615,7 +617,7 @@ void append_to_parent_field_class(struct ctx *ctx,
                break;
        }
        default:
-               abort();
+               bt_common_abort();
        }
 }
 
@@ -709,116 +711,10 @@ end:
 }
 
 /*
- * This function returns whether or not a given field class `tag_fc`
- * is valid as the tag field class of the variant field class `fc`.
- *
- * CTF 1.8 requires that the tag field class be an enumeration field
- * class and that, for each variant field class option's range set, the
- * tag field class contains a mapping which has the option's name and an
- * equal range set.
- */
-static inline
-bool _is_variant_field_class_tag_valid(
-               struct fs_sink_ctf_field_class_variant *fc,
-               struct fs_sink_ctf_field_class *tag_fc)
-{
-       bool is_valid = true;
-       bt_field_class_type ir_tag_fc_type = bt_field_class_get_type(
-               tag_fc->ir_fc);
-       uint64_t i;
-       GString *escaped_opt_name = g_string_new(NULL);
-
-       BT_ASSERT(escaped_opt_name);
-
-       if (ir_tag_fc_type != BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION &&
-                       ir_tag_fc_type != BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION) {
-               is_valid = false;
-               goto end;
-       }
-
-       for (i = 0; i < bt_field_class_variant_get_option_count(
-                       fc->base.ir_fc); i++) {
-               const bt_field_class_variant_option *var_opt_base =
-                       bt_field_class_variant_borrow_option_by_index_const(
-                               fc->base.ir_fc, i);
-               const char *opt_name = bt_field_class_variant_option_get_name(
-                       var_opt_base);
-
-               /*
-                * If the option is named `name` in trace IR, then it
-                * was _possibly_ named `_name` originally if it comes
-                * from `src.ctf.fs`. This means the corresponding
-                * enumeration field class mapping was also named
-                * `_name`, but this one didn't change, as enumeration
-                * FC mapping names are not escaped; they are literal
-                * strings.
-                *
-                * The `sink.ctf.fs` component escapes all the variant
-                * FC option names with `_`. Therefore the
-                * _escaped name_ must match the original enumeration
-                * FC mapping name.
-                */
-               g_string_assign(escaped_opt_name, "_");
-               g_string_append(escaped_opt_name, opt_name);
-
-               if (ir_tag_fc_type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION) {
-                       const bt_field_class_variant_with_unsigned_selector_option *var_opt =
-                               bt_field_class_variant_with_unsigned_selector_borrow_option_by_index_const(
-                                       fc->base.ir_fc, i);
-                       const bt_field_class_unsigned_enumeration_mapping *mapping;
-                       const bt_integer_range_set_unsigned *opt_ranges;
-                       const bt_integer_range_set_unsigned *mapping_ranges;
-
-                       mapping = bt_field_class_unsigned_enumeration_borrow_mapping_by_label_const(
-                               tag_fc->ir_fc, escaped_opt_name->str);
-                       if (!mapping) {
-                               is_valid = false;
-                               goto end;
-                       }
-
-                       opt_ranges = bt_field_class_variant_with_unsigned_selector_option_borrow_ranges_const(
-                               var_opt);
-                       mapping_ranges = bt_field_class_unsigned_enumeration_mapping_borrow_ranges_const(
-                               mapping);
-                       if (!bt_integer_range_set_unsigned_compare(opt_ranges,
-                                       mapping_ranges)) {
-                               is_valid = false;
-                               goto end;
-                       }
-               } else {
-                       const bt_field_class_variant_with_signed_selector_option *var_opt =
-                               bt_field_class_variant_with_signed_selector_borrow_option_by_index_const(
-                                       fc->base.ir_fc, i);
-                       const bt_field_class_signed_enumeration_mapping *mapping;
-                       const bt_integer_range_set_signed *opt_ranges;
-                       const bt_integer_range_set_signed *mapping_ranges;
-
-                       mapping = bt_field_class_signed_enumeration_borrow_mapping_by_label_const(
-                               tag_fc->ir_fc, escaped_opt_name->str);
-                       if (!mapping) {
-                               is_valid = false;
-                               goto end;
-                       }
-
-                       opt_ranges = bt_field_class_variant_with_signed_selector_option_borrow_ranges_const(
-                               var_opt);
-                       mapping_ranges = bt_field_class_signed_enumeration_mapping_borrow_ranges_const(
-                               mapping);
-                       if (!bt_integer_range_set_signed_compare(opt_ranges,
-                                       mapping_ranges)) {
-                               is_valid = false;
-                               goto end;
-                       }
-               }
-       }
-
-end:
-       return is_valid;
-}
-
-/*
- * This function indicates whether or not a given variant FC option name
- * must be protected (with the `_` prefix).
+ * 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
@@ -884,9 +780,9 @@ end:
  * FC options and enumeration FC mappings by range set.
  */
 static
-int must_protect_variant_option_name(const bt_field_class *ir_var_fc,
+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, bool *must_protect)
+               GString *name_buf)
 {
        int ret = 0;
        uint64_t i;
@@ -897,7 +793,6 @@ int must_protect_variant_option_name(const bt_field_class *ir_var_fc,
        const bt_field_class_variant_option *base_var_opt;
        bool force_protect = false;
 
-       *must_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);
@@ -913,7 +808,6 @@ int must_protect_variant_option_name(const bt_field_class *ir_var_fc,
         */
        force_protect = must_protect_identifier(ir_opt_name);
        if (force_protect) {
-               *must_protect = true;
                g_string_assign(name_buf, "_");
                g_string_append(name_buf, ir_opt_name);
        } else {
@@ -921,43 +815,43 @@ int must_protect_variant_option_name(const bt_field_class *ir_var_fc,
        }
 
        /* Borrow option's ranges */
-       if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR) {
+       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_SELECTOR) {
-               const bt_field_class_variant_with_unsigned_selector_option *var_opt =
-                       bt_field_class_variant_with_unsigned_selector_borrow_option_by_index_const(
+       } 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_unsigned_selector_option_borrow_ranges_const(
+                       bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
                                var_opt);
        } else {
-               const bt_field_class_variant_with_signed_selector_option *var_opt =
-                       bt_field_class_variant_with_signed_selector_borrow_option_by_index_const(
+               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_signed_selector_option_borrow_ranges_const(
+                       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_SELECTOR) {
+               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_unsigned_enumeration_mapping *mapping;
+                       const bt_field_class_enumeration_unsigned_mapping *mapping;
                        const bt_integer_range_set_unsigned *mapping_ranges;
 
-                       mapping = bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
+                       mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
                                ir_tag_fc, i);
-                       mapping_ranges = bt_field_class_unsigned_enumeration_mapping_borrow_ranges_const(
+                       mapping_ranges = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
                                mapping);
 
-                       if (bt_integer_range_set_unsigned_compare(opt_ranges,
+                       if (bt_integer_range_set_unsigned_is_equal(opt_ranges,
                                        mapping_ranges)) {
                                /* We have a winner */
                                mapping_base =
-                                       bt_field_class_unsigned_enumeration_mapping_as_mapping_const(
+                                       bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
                                                mapping);
                                mapping_label =
                                        bt_field_class_enumeration_mapping_get_label(
@@ -966,19 +860,19 @@ int must_protect_variant_option_name(const bt_field_class *ir_var_fc,
                        }
                } else {
                        const bt_field_class_enumeration_mapping *mapping_base;
-                       const bt_field_class_signed_enumeration_mapping *mapping;
+                       const bt_field_class_enumeration_signed_mapping *mapping;
                        const bt_integer_range_set_signed *mapping_ranges;
 
-                       mapping = bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
+                       mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
                                ir_tag_fc, i);
-                       mapping_ranges = bt_field_class_signed_enumeration_mapping_borrow_ranges_const(
+                       mapping_ranges = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
                                mapping);
 
-                       if (bt_integer_range_set_signed_compare(opt_ranges,
+                       if (bt_integer_range_set_signed_is_equal(opt_ranges,
                                        mapping_ranges)) {
                                /* We have a winner */
                                mapping_base =
-                                       bt_field_class_signed_enumeration_mapping_as_mapping_const(
+                                       bt_field_class_enumeration_signed_mapping_as_mapping_const(
                                                mapping);
                                mapping_label =
                                        bt_field_class_enumeration_mapping_get_label(
@@ -1017,15 +911,53 @@ int must_protect_variant_option_name(const bt_field_class *ir_var_fc,
                        ret = -1;
                        goto end;
                }
+       }
 
-               /*
-                * If this comes from a `src.ctf.fs` source, it looks
-                * like the variant FC option name was initially
-                * protected: protect it again when going back to TSDL.
-                */
-               *must_protect = true;
+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;
 }
@@ -1052,9 +984,9 @@ int translate_variant_field_class(struct ctx *ctx)
        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 (ir_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR ||
-                       ir_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR) {
-               ir_selector_field_path = bt_field_class_variant_with_selector_borrow_selector_field_path_const(
+       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);
        }
@@ -1071,14 +1003,14 @@ int translate_variant_field_class(struct ctx *ctx)
                bt_field_class_type type = bt_field_class_get_type(
                        tgt_fc->ir_fc);
 
-               if (type != BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION &&
-                               type != BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION) {
+               if (!bt_field_class_type_is(type,
+                               BT_FIELD_CLASS_TYPE_ENUMERATION)) {
                        fc->tag_is_before = true;
                        goto validate_opts;
                }
 
                /*
-                * Call must_protect_variant_option_name() for each
+                * 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.
@@ -1098,6 +1030,7 @@ int translate_variant_field_class(struct ctx *ctx)
                 * create the appropriate selector field class.
                 */
                fc->tag_is_before = true;
+               goto validate_opts;
        }
 
 validate_opts:
@@ -1112,12 +1045,13 @@ validate_opts:
         * cur_path_stack_push().
         */
        for (i = 0; i < opt_count; i++) {
-               bool must_protect = false;
-
-               ret = must_protect_variant_option_name(fc->base.ir_fc,
-                       tgt_fc->ir_fc, i, name_buf, &must_protect);
-               if (ret) {
-                       fc->tag_is_before = true;
+               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,
@@ -1143,7 +1077,7 @@ validate_opts:
                        opt_name_b =
                                bt_value_array_borrow_element_by_index_const(
                                        prot_opt_names, j);
-                       if (bt_value_compare(opt_name_a, opt_name_b)) {
+                       if (bt_value_is_equal(opt_name_a, opt_name_b)) {
                                /*
                                 * Variant FC option names are not
                                 * unique when protected.
@@ -1253,10 +1187,13 @@ 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, NULL);
+       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, false, elem_ir_fc,
@@ -1279,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)
 {
@@ -1329,36 +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_WITHOUT_SELECTOR:
-       case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
-       case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
+       } 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;
@@ -1385,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;
@@ -1404,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);
@@ -1472,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;
 
@@ -1551,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)
 {
@@ -1630,7 +1633,7 @@ int translate_event_class(struct fs_sink_comp *fs_sink,
        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));
@@ -1638,7 +1641,7 @@ int translate_event_class(struct fs_sink_comp *fs_sink,
                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) {
@@ -1675,6 +1678,7 @@ end:
        return ret;
 }
 
+static
 bool default_clock_class_name_exists(struct fs_sink_ctf_trace *trace,
                const char *name)
 {
@@ -1754,7 +1758,6 @@ int translate_stream_class(struct fs_sink_comp *fs_sink,
                                        (*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 */
@@ -1763,7 +1766,7 @@ int translate_stream_class(struct fs_sink_comp *fs_sink,
        }
 
        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) {
@@ -1780,7 +1783,7 @@ int translate_stream_class(struct fs_sink_comp *fs_sink,
                        (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));
This page took 0.035931 seconds and 4 git commands to generate.