FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT,
FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY,
FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE,
+ FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION,
FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT,
};
GArray *members;
};
+struct fs_sink_ctf_field_class_option {
+ struct fs_sink_ctf_field_class base;
+ struct fs_sink_ctf_field_class *content_fc;
+ GString *tag_ref;
+};
+
struct fs_sink_ctf_field_class_variant {
struct fs_sink_ctf_field_class base;
GString *tag_ref;
return fc;
}
+static inline
+struct fs_sink_ctf_field_class_option *fs_sink_ctf_field_class_option_create_empty(
+ const bt_field_class *ir_fc, uint64_t index_in_parent)
+{
+ struct fs_sink_ctf_field_class_option *fc =
+ g_new0(struct fs_sink_ctf_field_class_option, 1);
+
+ BT_ASSERT(fc);
+ _fs_sink_ctf_field_class_init((void *) fc,
+ FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION, ir_fc,
+ 1, index_in_parent);
+ fc->tag_ref = g_string_new(NULL);
+ BT_ASSERT(fc->tag_ref);
+ return fc;
+}
+
static inline
struct fs_sink_ctf_field_class_variant *fs_sink_ctf_field_class_variant_create_empty(
const bt_field_class *ir_fc, uint64_t index_in_parent)
g_free(fc);
}
+static inline
+void _fs_sink_ctf_field_class_option_destroy(
+ struct fs_sink_ctf_field_class_option *fc)
+{
+ BT_ASSERT(fc);
+ _fs_sink_ctf_field_class_fini((void *) fc);
+ fs_sink_ctf_field_class_destroy(fc->content_fc);
+
+ if (fc->tag_ref) {
+ g_string_free(fc->tag_ref, TRUE);
+ fc->tag_ref = NULL;
+ }
+
+ g_free(fc);
+}
+
static inline
void _fs_sink_ctf_field_class_variant_destroy(
struct fs_sink_ctf_field_class_variant *fc)
case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
_fs_sink_ctf_field_class_sequence_destroy((void *) fc);
break;
+ case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
+ _fs_sink_ctf_field_class_option_destroy((void *) fc);
+ break;
case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
_fs_sink_ctf_field_class_variant_destroy((void *) fc);
break;
return ret;
}
+static inline
+int write_option_field(struct fs_sink_stream *stream,
+ struct fs_sink_ctf_field_class_option *fc,
+ const bt_field *field)
+{
+ int ret;
+ const bt_field *content_field =
+ bt_field_option_borrow_field_const(field);
+
+ ret = bt_ctfser_write_unsigned_int(&stream->ctfser,
+ content_field ? 1 : 0, 8, 8, BYTE_ORDER);
+ if (G_UNLIKELY(ret)) {
+ goto end;
+ }
+
+ /*
+ * CTF 1.8 has no option field class type, so this component
+ * translates the option field class to a variant field class
+ * where the options are:
+ *
+ * * An empty structure field class (field occupies 0 bits).
+ * * The optional field class itself.
+ *
+ * If `content_field` is `NULL`, do not write anything (empty
+ * structure).
+ */
+ if (content_field) {
+ ret = write_field(stream, fc->content_fc, content_field);
+ }
+
+end:
+ return ret;
+}
+
static inline
int write_variant_field(struct fs_sink_stream *stream,
struct fs_sink_ctf_field_class_variant *fc,
case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
ret = write_sequence_field(stream, (void *) fc, field);
break;
+ case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
+ ret = write_option_field(stream, (void *) fc, field);
+ break;
case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
ret = write_variant_field(stream, (void *) fc, field);
break;
GString *lengths = NULL;
const char *lengths_str = "";
+ BT_ASSERT(fc);
+
while (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY ||
fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
if (!lengths) {
struct_fc, i);
struct fs_sink_ctf_field_class *fc = named_fc->fc;
+ /*
+ * For sequence, option, and variant field classes, if
+ * the length/tag field class is generated before, write
+ * it now before the dependent field class.
+ */
if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
struct fs_sink_ctf_field_class_sequence *seq_fc =
(void *) fc;
BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
NULL, seq_fc->length_ref->str, true);
}
+ } else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION) {
+ struct fs_sink_ctf_field_class_option *opt_fc =
+ (void *) 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_indent(ctx);
+ g_string_append(ctx->tsdl,
+ "/* The enumeration and variant field classes "
+ "below were a trace IR option field class. */\n");
+ append_indent(ctx);
+ g_string_append(ctx->tsdl, "enum : ");
+ append_integer_field_class_from_props(ctx,
+ 8, 8, false,
+ BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
+ NULL, NULL, false);
+ g_string_append(ctx->tsdl, " {\n");
+ ctx->indent_level++;
+ append_indent(ctx);
+ g_string_append(ctx->tsdl, "none = 0,\n");
+ append_indent(ctx);
+ g_string_append(ctx->tsdl, "content = 1,\n");
+ append_end_block(ctx);
+ g_string_append_printf(ctx->tsdl, " %s;\n",
+ opt_fc->tag_ref->str);
} else if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT) {
struct fs_sink_ctf_field_class_variant *var_fc =
(void *) fc;
fc->base.alignment);
}
+static
+void append_option_field_class(struct ctx *ctx,
+ struct fs_sink_ctf_field_class_option *opt_fc)
+{
+ g_string_append_printf(ctx->tsdl, "variant <%s> {\n",
+ opt_fc->tag_ref->str);
+ ctx->indent_level++;
+ append_indent(ctx);
+ g_string_append(ctx->tsdl, "struct { } none;\n");
+ append_indent(ctx);
+ append_member(ctx, "content", opt_fc->content_fc);
+ append_end_block(ctx);
+}
+
static
void append_variant_field_class(struct ctx *ctx,
struct fs_sink_ctf_field_class_variant *var_fc)
case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
append_struct_field_class(ctx, (void *) fc);
break;
+ case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION:
+ append_option_field_class(ctx, (void *) fc);
+ break;
case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
append_variant_field_class(ctx, (void *) fc);
break;
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) ==
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);
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)
{
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:
{