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) ==
/* 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;
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);
}
/*
- * 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
* 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;
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);
*/
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 {
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;
}
}
/*
- * 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.
* create the appropriate selector field class.
*/
fc->tag_is_before = true;
+ goto validate_opts;
}
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,
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)
{
int ret;
switch (bt_field_class_get_type(cur_path_stack_top(ctx)->ir_fc)) {
+ case BT_FIELD_CLASS_TYPE_BOOL:
+ ret = translate_bool_field_class(ctx);
+ break;
+ case BT_FIELD_CLASS_TYPE_BIT_ARRAY:
+ ret = translate_bit_array_field_class(ctx);
+ break;
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:
ret = translate_integer_field_class(ctx);
break;
- case BT_FIELD_CLASS_TYPE_REAL:
+ case BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL:
+ case BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL:
ret = translate_real_field_class(ctx);
break;
case BT_FIELD_CLASS_TYPE_STRING:
case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
ret = translate_dynamic_array_field_class(ctx);
break;
+ case BT_FIELD_CLASS_TYPE_OPTION:
+ ret = translate_option_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:
}
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;
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;