X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fplugins%2Fctf%2Fcommon%2Fmetadata%2Fvisitor-generate-ir.cpp;h=50d8d441fe7ed312a16b0ab99762950bc8a332b6;hb=4164020e790f;hp=970b838cf43ac352a765295a972822d0d3b3f2ce;hpb=087cd0f57f0f7d815a609a4e041d1200f380e4aa;p=babeltrace.git diff --git a/src/plugins/ctf/common/metadata/visitor-generate-ir.cpp b/src/plugins/ctf/common/metadata/visitor-generate-ir.cpp index 970b838c..50d8d441 100644 --- a/src/plugins/ctf/common/metadata/visitor-generate-ir.cpp +++ b/src/plugins/ctf/common/metadata/visitor-generate-ir.cpp @@ -7,10 +7,10 @@ * Common Trace Format metadata visitor (generates CTF IR objects). */ -#define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp) +#define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp) #define BT_COMP_LOG_SELF_COMP_CLASS (ctx->log_cfg.self_comp_class) -#define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level) -#define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR" +#define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level) +#define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR" #include "logging/comp-logging.h" #include @@ -36,168 +36,173 @@ #include "ctf-meta-visitors.hpp" /* Bit value (left shift) */ -#define _BV(_val) (1 << (_val)) +#define _BV(_val) (1 << (_val)) /* Bit is set in a set of bits */ -#define _IS_SET(_set, _mask) (*(_set) & (_mask)) +#define _IS_SET(_set, _mask) (*(_set) & (_mask)) /* Set bit in a set of bits */ -#define _SET(_set, _mask) (*(_set) |= (_mask)) +#define _SET(_set, _mask) (*(_set) |= (_mask)) /* Try to push scope, or go to the `error` label */ -#define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \ - do { \ - ret = ctx_push_scope(ctx); \ - if (ret) { \ - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \ - goto error; \ - } \ - } while (0) +#define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \ + do { \ + ret = ctx_push_scope(ctx); \ + if (ret) { \ + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \ + goto error; \ + } \ + } while (0) /* Bits for verifying existing attributes in various declarations */ -enum { - _CLOCK_NAME_SET = _BV(0), - _CLOCK_UUID_SET = _BV(1), - _CLOCK_FREQ_SET = _BV(2), - _CLOCK_PRECISION_SET = _BV(3), - _CLOCK_OFFSET_S_SET = _BV(4), - _CLOCK_OFFSET_SET = _BV(5), - _CLOCK_ABSOLUTE_SET = _BV(6), - _CLOCK_DESCRIPTION_SET = _BV(7), +enum +{ + _CLOCK_NAME_SET = _BV(0), + _CLOCK_UUID_SET = _BV(1), + _CLOCK_FREQ_SET = _BV(2), + _CLOCK_PRECISION_SET = _BV(3), + _CLOCK_OFFSET_S_SET = _BV(4), + _CLOCK_OFFSET_SET = _BV(5), + _CLOCK_ABSOLUTE_SET = _BV(6), + _CLOCK_DESCRIPTION_SET = _BV(7), }; -enum { - _INTEGER_ALIGN_SET = _BV(0), - _INTEGER_SIZE_SET = _BV(1), - _INTEGER_BASE_SET = _BV(2), - _INTEGER_ENCODING_SET = _BV(3), - _INTEGER_BYTE_ORDER_SET = _BV(4), - _INTEGER_SIGNED_SET = _BV(5), - _INTEGER_MAP_SET = _BV(6), +enum +{ + _INTEGER_ALIGN_SET = _BV(0), + _INTEGER_SIZE_SET = _BV(1), + _INTEGER_BASE_SET = _BV(2), + _INTEGER_ENCODING_SET = _BV(3), + _INTEGER_BYTE_ORDER_SET = _BV(4), + _INTEGER_SIGNED_SET = _BV(5), + _INTEGER_MAP_SET = _BV(6), }; -enum { - _FLOAT_ALIGN_SET = _BV(0), - _FLOAT_MANT_DIG_SET = _BV(1), - _FLOAT_EXP_DIG_SET = _BV(2), - _FLOAT_BYTE_ORDER_SET = _BV(3), +enum +{ + _FLOAT_ALIGN_SET = _BV(0), + _FLOAT_MANT_DIG_SET = _BV(1), + _FLOAT_EXP_DIG_SET = _BV(2), + _FLOAT_BYTE_ORDER_SET = _BV(3), }; -enum { - _STRING_ENCODING_SET = _BV(0), +enum +{ + _STRING_ENCODING_SET = _BV(0), }; -enum { - _TRACE_MINOR_SET = _BV(0), - _TRACE_MAJOR_SET = _BV(1), - _TRACE_BYTE_ORDER_SET = _BV(2), - _TRACE_UUID_SET = _BV(3), - _TRACE_PACKET_HEADER_SET = _BV(4), +enum +{ + _TRACE_MINOR_SET = _BV(0), + _TRACE_MAJOR_SET = _BV(1), + _TRACE_BYTE_ORDER_SET = _BV(2), + _TRACE_UUID_SET = _BV(3), + _TRACE_PACKET_HEADER_SET = _BV(4), }; -enum { - _STREAM_ID_SET = _BV(0), - _STREAM_PACKET_CONTEXT_SET = _BV(1), - _STREAM_EVENT_HEADER_SET = _BV(2), - _STREAM_EVENT_CONTEXT_SET = _BV(3), +enum +{ + _STREAM_ID_SET = _BV(0), + _STREAM_PACKET_CONTEXT_SET = _BV(1), + _STREAM_EVENT_HEADER_SET = _BV(2), + _STREAM_EVENT_CONTEXT_SET = _BV(3), }; -enum { - _EVENT_NAME_SET = _BV(0), - _EVENT_ID_SET = _BV(1), - _EVENT_MODEL_EMF_URI_SET = _BV(2), - _EVENT_STREAM_ID_SET = _BV(3), - _EVENT_LOG_LEVEL_SET = _BV(4), - _EVENT_CONTEXT_SET = _BV(5), - _EVENT_FIELDS_SET = _BV(6), +enum +{ + _EVENT_NAME_SET = _BV(0), + _EVENT_ID_SET = _BV(1), + _EVENT_MODEL_EMF_URI_SET = _BV(2), + _EVENT_STREAM_ID_SET = _BV(3), + _EVENT_LOG_LEVEL_SET = _BV(4), + _EVENT_CONTEXT_SET = _BV(5), + _EVENT_FIELDS_SET = _BV(6), }; -enum loglevel { - LOG_LEVEL_EMERG = 0, - LOG_LEVEL_ALERT = 1, - LOG_LEVEL_CRIT = 2, - LOG_LEVEL_ERR = 3, - LOG_LEVEL_WARNING = 4, - LOG_LEVEL_NOTICE = 5, - LOG_LEVEL_INFO = 6, - LOG_LEVEL_DEBUG_SYSTEM = 7, - LOG_LEVEL_DEBUG_PROGRAM = 8, - LOG_LEVEL_DEBUG_PROCESS = 9, - LOG_LEVEL_DEBUG_MODULE = 10, - LOG_LEVEL_DEBUG_UNIT = 11, - LOG_LEVEL_DEBUG_FUNCTION = 12, - LOG_LEVEL_DEBUG_LINE = 13, - LOG_LEVEL_DEBUG = 14, - _NR_LOGLEVELS = 15, +enum loglevel +{ + LOG_LEVEL_EMERG = 0, + LOG_LEVEL_ALERT = 1, + LOG_LEVEL_CRIT = 2, + LOG_LEVEL_ERR = 3, + LOG_LEVEL_WARNING = 4, + LOG_LEVEL_NOTICE = 5, + LOG_LEVEL_INFO = 6, + LOG_LEVEL_DEBUG_SYSTEM = 7, + LOG_LEVEL_DEBUG_PROGRAM = 8, + LOG_LEVEL_DEBUG_PROCESS = 9, + LOG_LEVEL_DEBUG_MODULE = 10, + LOG_LEVEL_DEBUG_UNIT = 11, + LOG_LEVEL_DEBUG_FUNCTION = 12, + LOG_LEVEL_DEBUG_LINE = 13, + LOG_LEVEL_DEBUG = 14, + _NR_LOGLEVELS = 15, }; /* Prefixes of class aliases */ -#define _PREFIX_ALIAS 'a' -#define _PREFIX_ENUM 'e' -#define _PREFIX_STRUCT 's' -#define _PREFIX_VARIANT 'v' +#define _PREFIX_ALIAS 'a' +#define _PREFIX_ENUM 'e' +#define _PREFIX_STRUCT 's' +#define _PREFIX_VARIANT 'v' /* First entry in a BT list */ -#define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) \ - bt_list_entry((_ptr)->next, _class, _member) +#define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member) -#define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \ - _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, \ - "Duplicate attribute in %s: attr-name=\"%s\"", \ - _entity, _attr) +#define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \ + _BT_COMP_LOGE_APPEND_CAUSE_LINENO( \ + (_node)->lineno, "Duplicate attribute in %s: attr-name=\"%s\"", _entity, _attr) -#define _BT_COMP_LOGE_NODE(_node, _msg, args...) \ - _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ## args) +#define _BT_COMP_LOGE_NODE(_node, _msg, args...) _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ##args) -#define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \ - _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ## args) +#define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \ + _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ##args) -#define _BT_COMP_LOGW_NODE(_node, _msg, args...) \ - _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ## args) +#define _BT_COMP_LOGW_NODE(_node, _msg, args...) _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ##args) -#define _BT_COMP_LOGT_NODE(_node, _msg, args...) \ - _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ## args) +#define _BT_COMP_LOGT_NODE(_node, _msg, args...) _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ##args) /* * Declaration scope of a visitor context. This represents a TSDL * lexical scope, so that aliases and named structures, variants, * and enumerations may be registered and looked up hierarchically. */ -struct ctx_decl_scope { - /* - * Alias name to field class. - * - * GQuark -> struct ctf_field_class * (owned by this) - */ - GHashTable *decl_map; - - /* Parent scope; NULL if this is the root declaration scope */ - struct ctx_decl_scope *parent_scope; +struct ctx_decl_scope +{ + /* + * Alias name to field class. + * + * GQuark -> struct ctf_field_class * (owned by this) + */ + GHashTable *decl_map; + + /* Parent scope; NULL if this is the root declaration scope */ + struct ctx_decl_scope *parent_scope; }; /* * Visitor context (private). */ -struct ctf_visitor_generate_ir { - struct meta_log_config log_cfg; +struct ctf_visitor_generate_ir +{ + struct meta_log_config log_cfg; - /* Trace IR trace class being filled (owned by this) */ - bt_trace_class *trace_class; + /* Trace IR trace class being filled (owned by this) */ + bt_trace_class *trace_class; - /* CTF meta trace being filled (owned by this) */ - struct ctf_trace_class *ctf_tc; + /* CTF meta trace being filled (owned by this) */ + struct ctf_trace_class *ctf_tc; - /* Current declaration scope (top of the stack) (owned by this) */ - struct ctx_decl_scope *current_scope; + /* Current declaration scope (top of the stack) (owned by this) */ + struct ctx_decl_scope *current_scope; - /* True if trace declaration is visited */ - bool is_trace_visited; + /* True if trace declaration is visited */ + bool is_trace_visited; - /* True if this is an LTTng trace */ - bool is_lttng; + /* True if this is an LTTng trace */ + bool is_lttng; - /* Config passed by the user */ - struct ctf_metadata_decoder_config decoder_config; + /* Config passed by the user */ + struct ctf_metadata_decoder_config decoder_config; }; /* @@ -211,24 +216,23 @@ struct ctf_visitor_generate_ir; * @param par_scope Parent scope (NULL if creating a root scope) * @returns New declaration scope, or NULL on error */ -static -struct ctx_decl_scope *ctx_decl_scope_create(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *par_scope) +static struct ctx_decl_scope *ctx_decl_scope_create(struct ctf_visitor_generate_ir *ctx, + struct ctx_decl_scope *par_scope) { - struct ctx_decl_scope *scope; + struct ctx_decl_scope *scope; - scope = g_new(struct ctx_decl_scope, 1); - if (!scope) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope."); - goto end; - } + scope = g_new(struct ctx_decl_scope, 1); + if (!scope) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope."); + goto end; + } - scope->decl_map = g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify) ctf_field_class_destroy); - scope->parent_scope = par_scope; + scope->decl_map = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, + (GDestroyNotify) ctf_field_class_destroy); + scope->parent_scope = par_scope; end: - return scope; + return scope; } /** @@ -238,18 +242,17 @@ end: * * @param scope Scope to destroy */ -static -void ctx_decl_scope_destroy(struct ctx_decl_scope *scope) +static void ctx_decl_scope_destroy(struct ctx_decl_scope *scope) { - if (!scope) { - goto end; - } + if (!scope) { + goto end; + } - g_hash_table_destroy(scope->decl_map); - g_free(scope); + g_hash_table_destroy(scope->decl_map); + g_free(scope); end: - return; + return; } /** @@ -259,27 +262,26 @@ end: * @param name Name * @returns Associated GQuark, or 0 on error */ -static -GQuark get_prefixed_named_quark(struct ctf_visitor_generate_ir *ctx, char prefix, - const char *name) +static GQuark get_prefixed_named_quark(struct ctf_visitor_generate_ir *ctx, char prefix, + const char *name) { - GQuark qname = 0; + GQuark qname = 0; - BT_ASSERT(name); + BT_ASSERT(name); - /* Prefix character + original string + '\0' */ - char *prname = g_new(char, strlen(name) + 2); - if (!prname) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate a string."); - goto end; - } + /* Prefix character + original string + '\0' */ + char *prname = g_new(char, strlen(name) + 2); + if (!prname) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate a string."); + goto end; + } - sprintf(prname, "%c%s", prefix, name); - qname = g_quark_from_string(prname); - g_free(prname); + sprintf(prname, "%c%s", prefix, name); + qname = g_quark_from_string(prname); + g_free(prname); end: - return qname; + return qname; } /** @@ -293,46 +295,46 @@ end: * @returns Declaration (owned by caller if \p copy is true), * or NULL if not found */ -static -struct ctf_field_class *ctx_decl_scope_lookup_prefix_alias( - struct ctf_visitor_generate_ir *ctx, struct ctx_decl_scope *scope, char prefix, - const char *name, int levels, bool copy) +static struct ctf_field_class * +ctx_decl_scope_lookup_prefix_alias(struct ctf_visitor_generate_ir *ctx, + struct ctx_decl_scope *scope, char prefix, const char *name, + int levels, bool copy) { - GQuark qname = 0; - int cur_levels = 0; - struct ctf_field_class *decl = NULL; - struct ctx_decl_scope *cur_scope = scope; - - BT_ASSERT(scope); - BT_ASSERT(name); - qname = get_prefixed_named_quark(ctx, prefix, name); - if (!qname) { - goto end; - } - - if (levels < 0) { - levels = INT_MAX; - } - - while (cur_scope && cur_levels < levels) { - decl = (ctf_field_class *) g_hash_table_lookup(cur_scope->decl_map, - (gconstpointer) GUINT_TO_POINTER(qname)); - if (decl) { - /* Caller's reference */ - if (copy) { - decl = ctf_field_class_copy(decl); - BT_ASSERT(decl); - } - - goto end; - } - - cur_scope = cur_scope->parent_scope; - cur_levels++; - } + GQuark qname = 0; + int cur_levels = 0; + struct ctf_field_class *decl = NULL; + struct ctx_decl_scope *cur_scope = scope; + + BT_ASSERT(scope); + BT_ASSERT(name); + qname = get_prefixed_named_quark(ctx, prefix, name); + if (!qname) { + goto end; + } + + if (levels < 0) { + levels = INT_MAX; + } + + while (cur_scope && cur_levels < levels) { + decl = (ctf_field_class *) g_hash_table_lookup(cur_scope->decl_map, + (gconstpointer) GUINT_TO_POINTER(qname)); + if (decl) { + /* Caller's reference */ + if (copy) { + decl = ctf_field_class_copy(decl); + BT_ASSERT(decl); + } + + goto end; + } + + cur_scope = cur_scope->parent_scope; + cur_levels++; + } end: - return decl; + return decl; } /** @@ -345,13 +347,11 @@ end: * @returns Declaration (owned by caller if \p copy is true), * or NULL if not found */ -static -struct ctf_field_class *ctx_decl_scope_lookup_alias(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *scope, const char *name, int levels, - bool copy) +static struct ctf_field_class *ctx_decl_scope_lookup_alias(struct ctf_visitor_generate_ir *ctx, + struct ctx_decl_scope *scope, + const char *name, int levels, bool copy) { - return ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_ALIAS, - name, levels, copy); + return ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_ALIAS, name, levels, copy); } /** @@ -364,13 +364,13 @@ struct ctf_field_class *ctx_decl_scope_lookup_alias(struct ctf_visitor_generate_ * @returns Declaration (owned by caller if \p copy is true), * or NULL if not found */ -static -struct ctf_field_class_enum *ctx_decl_scope_lookup_enum(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *scope, const char *name, int levels, - bool copy) +static struct ctf_field_class_enum *ctx_decl_scope_lookup_enum(struct ctf_visitor_generate_ir *ctx, + struct ctx_decl_scope *scope, + const char *name, int levels, + bool copy) { - return ctf_field_class_as_enum(ctx_decl_scope_lookup_prefix_alias(ctx, scope, - _PREFIX_ENUM, name, levels, copy)); + return ctf_field_class_as_enum( + ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_ENUM, name, levels, copy)); } /** @@ -383,13 +383,12 @@ struct ctf_field_class_enum *ctx_decl_scope_lookup_enum(struct ctf_visitor_gener * @returns Declaration (owned by caller if \p copy is true), * or NULL if not found */ -static -struct ctf_field_class_struct *ctx_decl_scope_lookup_struct(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *scope, const char *name, int levels, - bool copy) +static struct ctf_field_class_struct * +ctx_decl_scope_lookup_struct(struct ctf_visitor_generate_ir *ctx, struct ctx_decl_scope *scope, + const char *name, int levels, bool copy) { - return ctf_field_class_as_struct(ctx_decl_scope_lookup_prefix_alias(ctx, scope, - _PREFIX_STRUCT, name, levels, copy)); + return ctf_field_class_as_struct( + ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_STRUCT, name, levels, copy)); } /** @@ -402,13 +401,12 @@ struct ctf_field_class_struct *ctx_decl_scope_lookup_struct(struct ctf_visitor_g * @returns Declaration (owned by caller if \p copy is true), * or NULL if not found */ -static -struct ctf_field_class_variant *ctx_decl_scope_lookup_variant(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *scope, const char *name, int levels, - bool copy) +static struct ctf_field_class_variant * +ctx_decl_scope_lookup_variant(struct ctf_visitor_generate_ir *ctx, struct ctx_decl_scope *scope, + const char *name, int levels, bool copy) { - return ctf_field_class_as_variant(ctx_decl_scope_lookup_prefix_alias(ctx, scope, - _PREFIX_VARIANT, name, levels, copy)); + return ctf_field_class_as_variant( + ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_VARIANT, name, levels, copy)); } /** @@ -420,36 +418,34 @@ struct ctf_field_class_variant *ctx_decl_scope_lookup_variant(struct ctf_visitor * @param decl Field class to register (copied) * @returns 0 if registration went okay, negative value otherwise */ -static -int ctx_decl_scope_register_prefix_alias(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *scope, char prefix, const char *name, - struct ctf_field_class *decl) +static int ctx_decl_scope_register_prefix_alias(struct ctf_visitor_generate_ir *ctx, + struct ctx_decl_scope *scope, char prefix, + const char *name, struct ctf_field_class *decl) { - int ret = 0; - GQuark qname = 0; - - BT_ASSERT(scope); - BT_ASSERT(name); - BT_ASSERT(decl); - qname = get_prefixed_named_quark(ctx, prefix, name); - if (!qname) { - ret = -ENOMEM; - goto end; - } - - /* Make sure alias does not exist in local scope */ - if (ctx_decl_scope_lookup_prefix_alias(ctx, scope, prefix, name, 1, - false)) { - ret = -EEXIST; - goto end; - } - - decl = ctf_field_class_copy(decl); - BT_ASSERT(decl); - g_hash_table_insert(scope->decl_map, GUINT_TO_POINTER(qname), decl); + int ret = 0; + GQuark qname = 0; + + BT_ASSERT(scope); + BT_ASSERT(name); + BT_ASSERT(decl); + qname = get_prefixed_named_quark(ctx, prefix, name); + if (!qname) { + ret = -ENOMEM; + goto end; + } + + /* Make sure alias does not exist in local scope */ + if (ctx_decl_scope_lookup_prefix_alias(ctx, scope, prefix, name, 1, false)) { + ret = -EEXIST; + goto end; + } + + decl = ctf_field_class_copy(decl); + BT_ASSERT(decl); + g_hash_table_insert(scope->decl_map, GUINT_TO_POINTER(qname), decl); end: - return ret; + return ret; } /** @@ -460,12 +456,11 @@ end: * @param decl Field class to register (copied) * @returns 0 if registration went okay, negative value otherwise */ -static -int ctx_decl_scope_register_alias(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *scope, const char *name, struct ctf_field_class *decl) +static int ctx_decl_scope_register_alias(struct ctf_visitor_generate_ir *ctx, + struct ctx_decl_scope *scope, const char *name, + struct ctf_field_class *decl) { - return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_ALIAS, - name, decl); + return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_ALIAS, name, decl); } /** @@ -476,13 +471,12 @@ int ctx_decl_scope_register_alias(struct ctf_visitor_generate_ir *ctx, * @param decl Enumeration field class to register (copied) * @returns 0 if registration went okay, negative value otherwise */ -static -int ctx_decl_scope_register_enum(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *scope, const char *name, - struct ctf_field_class_enum *decl) +static int ctx_decl_scope_register_enum(struct ctf_visitor_generate_ir *ctx, + struct ctx_decl_scope *scope, const char *name, + struct ctf_field_class_enum *decl) { - return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_ENUM, - name, &decl->base.base.base); + return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_ENUM, name, + &decl->base.base.base); } /** @@ -493,13 +487,11 @@ int ctx_decl_scope_register_enum(struct ctf_visitor_generate_ir *ctx, * @param decl Structure field class to register (copied) * @returns 0 if registration went okay, negative value otherwise */ -static -int ctx_decl_scope_register_struct(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *scope, const char *name, - struct ctf_field_class_struct *decl) +static int ctx_decl_scope_register_struct(struct ctf_visitor_generate_ir *ctx, + struct ctx_decl_scope *scope, const char *name, + struct ctf_field_class_struct *decl) { - return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_STRUCT, - name, &decl->base); + return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_STRUCT, name, &decl->base); } /** @@ -510,13 +502,11 @@ int ctx_decl_scope_register_struct(struct ctf_visitor_generate_ir *ctx, * @param decl Variant field class to register * @returns 0 if registration went okay, negative value otherwise */ -static -int ctx_decl_scope_register_variant(struct ctf_visitor_generate_ir *ctx, - struct ctx_decl_scope *scope, const char *name, - struct ctf_field_class_variant *decl) +static int ctx_decl_scope_register_variant(struct ctf_visitor_generate_ir *ctx, + struct ctx_decl_scope *scope, const char *name, + struct ctf_field_class_variant *decl) { - return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_VARIANT, - name, &decl->base); + return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_VARIANT, name, &decl->base); } /** @@ -524,37 +514,36 @@ int ctx_decl_scope_register_variant(struct ctf_visitor_generate_ir *ctx, * * @param ctx Visitor context to destroy */ -static -void ctx_destroy(struct ctf_visitor_generate_ir *ctx) +static void ctx_destroy(struct ctf_visitor_generate_ir *ctx) { - struct ctx_decl_scope *scope; + struct ctx_decl_scope *scope; - if (!ctx) { - goto end; - } + if (!ctx) { + goto end; + } - scope = ctx->current_scope; + scope = ctx->current_scope; - /* - * Destroy all scopes, from current one to the root scope. - */ - while (scope) { - struct ctx_decl_scope *parent_scope = scope->parent_scope; + /* + * Destroy all scopes, from current one to the root scope. + */ + while (scope) { + struct ctx_decl_scope *parent_scope = scope->parent_scope; - ctx_decl_scope_destroy(scope); - scope = parent_scope; - } + ctx_decl_scope_destroy(scope); + scope = parent_scope; + } - bt_trace_class_put_ref(ctx->trace_class); + bt_trace_class_put_ref(ctx->trace_class); - if (ctx->ctf_tc) { - ctf_trace_class_destroy(ctx->ctf_tc); - } + if (ctx->ctf_tc) { + ctf_trace_class_destroy(ctx->ctf_tc); + } - g_free(ctx); + g_free(ctx); end: - return; + return; } /** @@ -563,57 +552,54 @@ end: * @param trace Associated trace * @returns New visitor context, or NULL on error */ -static -struct ctf_visitor_generate_ir *ctx_create( - const struct ctf_metadata_decoder_config *decoder_config) +static struct ctf_visitor_generate_ir * +ctx_create(const struct ctf_metadata_decoder_config *decoder_config) { - struct ctf_visitor_generate_ir *ctx = NULL; - - BT_ASSERT(decoder_config); - - ctx = g_new0(struct ctf_visitor_generate_ir, 1); - if (!ctx) { - BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, decoder_config->log_level, - decoder_config->self_comp, - "Failed to allocate one visitor context."); - goto error; - } - - ctx->log_cfg.log_level = decoder_config->log_level; - ctx->log_cfg.self_comp = decoder_config->self_comp; - ctx->log_cfg.self_comp_class = decoder_config->self_comp_class; - - if (decoder_config->self_comp) { - ctx->trace_class = bt_trace_class_create( - decoder_config->self_comp); - if (!ctx->trace_class) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class."); - goto error; - } - } - - ctx->ctf_tc = ctf_trace_class_create(); - if (!ctx->ctf_tc) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class."); - goto error; - } - - /* Root declaration scope */ - ctx->current_scope = ctx_decl_scope_create(ctx, NULL); - if (!ctx->current_scope) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope."); - goto error; - } - - ctx->decoder_config = *decoder_config; - goto end; + struct ctf_visitor_generate_ir *ctx = NULL; + + BT_ASSERT(decoder_config); + + ctx = g_new0(struct ctf_visitor_generate_ir, 1); + if (!ctx) { + BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, decoder_config->log_level, decoder_config->self_comp, + "Failed to allocate one visitor context."); + goto error; + } + + ctx->log_cfg.log_level = decoder_config->log_level; + ctx->log_cfg.self_comp = decoder_config->self_comp; + ctx->log_cfg.self_comp_class = decoder_config->self_comp_class; + + if (decoder_config->self_comp) { + ctx->trace_class = bt_trace_class_create(decoder_config->self_comp); + if (!ctx->trace_class) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class."); + goto error; + } + } + + ctx->ctf_tc = ctf_trace_class_create(); + if (!ctx->ctf_tc) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class."); + goto error; + } + + /* Root declaration scope */ + ctx->current_scope = ctx_decl_scope_create(ctx, NULL); + if (!ctx->current_scope) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope."); + goto error; + } + + ctx->decoder_config = *decoder_config; + goto end; error: - ctx_destroy(ctx); - ctx = NULL; + ctx_destroy(ctx); + ctx = NULL; end: - return ctx; + return ctx; } /** @@ -623,4361 +609,4177 @@ end: * @param ctx Visitor context * @returns 0 on success, or a negative value on error */ -static -int ctx_push_scope(struct ctf_visitor_generate_ir *ctx) +static int ctx_push_scope(struct ctf_visitor_generate_ir *ctx) { - int ret = 0; - struct ctx_decl_scope *new_scope; + int ret = 0; + struct ctx_decl_scope *new_scope; - BT_ASSERT(ctx); - new_scope = ctx_decl_scope_create(ctx, ctx->current_scope); - if (!new_scope) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope."); - ret = -ENOMEM; - goto end; - } + BT_ASSERT(ctx); + new_scope = ctx_decl_scope_create(ctx, ctx->current_scope); + if (!new_scope) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope."); + ret = -ENOMEM; + goto end; + } - ctx->current_scope = new_scope; + ctx->current_scope = new_scope; end: - return ret; + return ret; } -static -void ctx_pop_scope(struct ctf_visitor_generate_ir *ctx) +static void ctx_pop_scope(struct ctf_visitor_generate_ir *ctx) { - struct ctx_decl_scope *parent_scope = NULL; + struct ctx_decl_scope *parent_scope = NULL; - BT_ASSERT(ctx); + BT_ASSERT(ctx); - if (!ctx->current_scope) { - goto end; - } + if (!ctx->current_scope) { + goto end; + } - parent_scope = ctx->current_scope->parent_scope; - ctx_decl_scope_destroy(ctx->current_scope); - ctx->current_scope = parent_scope; + parent_scope = ctx->current_scope->parent_scope; + ctx_decl_scope_destroy(ctx->current_scope); + ctx->current_scope = parent_scope; end: - return; + return; } -static -int visit_field_class_specifier_list(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *ts_list, struct ctf_field_class **decl); +static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *ts_list, + struct ctf_field_class **decl); -static -int is_unary_string(struct bt_list_head *head) +static int is_unary_string(struct bt_list_head *head) { - int ret = TRUE; - struct ctf_node *node; + int ret = TRUE; + struct ctf_node *node; - bt_list_for_each_entry(node, head, siblings) { - if (node->type != NODE_UNARY_EXPRESSION) { - ret = FALSE; - } + bt_list_for_each_entry (node, head, siblings) { + if (node->type != NODE_UNARY_EXPRESSION) { + ret = FALSE; + } - if (node->u.unary_expression.type != UNARY_STRING) { - ret = FALSE; - } - } + if (node->u.unary_expression.type != UNARY_STRING) { + ret = FALSE; + } + } - return ret; + return ret; } -static -const char *get_map_clock_name_value(struct bt_list_head *head) +static const char *get_map_clock_name_value(struct bt_list_head *head) { - int i = 0; - struct ctf_node *node; - const char *name = NULL; - - bt_list_for_each_entry(node, head, siblings) { - char *src_string; - int uexpr_type = node->u.unary_expression.type; - int uexpr_link = node->u.unary_expression.link; - int cond = node->type != NODE_UNARY_EXPRESSION || - uexpr_type != UNARY_STRING || - !((uexpr_link != UNARY_LINK_UNKNOWN) ^ (i == 0)); - if (cond) { - goto error; - } - - /* Needs to be chained with . */ - switch (node->u.unary_expression.link) { - case UNARY_DOTLINK: - break; - case UNARY_ARROWLINK: - case UNARY_DOTDOTDOT: - goto error; - default: - break; - } - - src_string = node->u.unary_expression.u.string; - - switch (i) { - case 0: - if (strcmp("clock", src_string)) { - goto error; - } - break; - case 1: - name = src_string; - break; - case 2: - if (strcmp("value", src_string)) { - goto error; - } - break; - default: - /* Extra identifier, unknown */ - goto error; - } - - i++; - } - - return name; + int i = 0; + struct ctf_node *node; + const char *name = NULL; + + bt_list_for_each_entry (node, head, siblings) { + char *src_string; + int uexpr_type = node->u.unary_expression.type; + int uexpr_link = node->u.unary_expression.link; + int cond = node->type != NODE_UNARY_EXPRESSION || uexpr_type != UNARY_STRING || + !((uexpr_link != UNARY_LINK_UNKNOWN) ^ (i == 0)); + if (cond) { + goto error; + } + + /* Needs to be chained with . */ + switch (node->u.unary_expression.link) { + case UNARY_DOTLINK: + break; + case UNARY_ARROWLINK: + case UNARY_DOTDOTDOT: + goto error; + default: + break; + } + + src_string = node->u.unary_expression.u.string; + + switch (i) { + case 0: + if (strcmp("clock", src_string)) { + goto error; + } + break; + case 1: + name = src_string; + break; + case 2: + if (strcmp("value", src_string)) { + goto error; + } + break; + default: + /* Extra identifier, unknown */ + goto error; + } + + i++; + } + + return name; error: - return NULL; + return NULL; } -static -int is_unary_unsigned(struct bt_list_head *head) +static int is_unary_unsigned(struct bt_list_head *head) { - int ret = TRUE; - struct ctf_node *node; + int ret = TRUE; + struct ctf_node *node; - bt_list_for_each_entry(node, head, siblings) { - if (node->type != NODE_UNARY_EXPRESSION) { - ret = FALSE; - } + bt_list_for_each_entry (node, head, siblings) { + if (node->type != NODE_UNARY_EXPRESSION) { + ret = FALSE; + } - if (node->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { - ret = FALSE; - } - } + if (node->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + ret = FALSE; + } + } - return ret; + return ret; } -static -int get_unary_unsigned(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *head, - uint64_t *value) +static int get_unary_unsigned(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *head, + uint64_t *value) { - int i = 0; - int ret = 0; - struct ctf_node *node; - - *value = 0; - - if (bt_list_empty(head)) { - ret = -1; - goto end; - } - - bt_list_for_each_entry(node, head, siblings) { - int uexpr_type = node->u.unary_expression.type; - int uexpr_link = node->u.unary_expression.link; - int cond = node->type != NODE_UNARY_EXPRESSION || - uexpr_type != UNARY_UNSIGNED_CONSTANT || - uexpr_link != UNARY_LINK_UNKNOWN || i != 0; - if (cond) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Invalid constant unsigned integer."); - ret = -EINVAL; - goto end; - } - - *value = node->u.unary_expression.u.unsigned_constant; - i++; - } + int i = 0; + int ret = 0; + struct ctf_node *node; + + *value = 0; + + if (bt_list_empty(head)) { + ret = -1; + goto end; + } + + bt_list_for_each_entry (node, head, siblings) { + int uexpr_type = node->u.unary_expression.type; + int uexpr_link = node->u.unary_expression.link; + int cond = node->type != NODE_UNARY_EXPRESSION || uexpr_type != UNARY_UNSIGNED_CONSTANT || + uexpr_link != UNARY_LINK_UNKNOWN || i != 0; + if (cond) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Invalid constant unsigned integer."); + ret = -EINVAL; + goto end; + } + + *value = node->u.unary_expression.u.unsigned_constant; + i++; + } end: - return ret; + return ret; } -static -int is_unary_signed(struct bt_list_head *head) +static int is_unary_signed(struct bt_list_head *head) { - int ret = TRUE; - struct ctf_node *node; + int ret = TRUE; + struct ctf_node *node; - bt_list_for_each_entry(node, head, siblings) { - if (node->type != NODE_UNARY_EXPRESSION) { - ret = FALSE; - } + bt_list_for_each_entry (node, head, siblings) { + if (node->type != NODE_UNARY_EXPRESSION) { + ret = FALSE; + } - if (node->u.unary_expression.type != UNARY_SIGNED_CONSTANT) { - ret = FALSE; - } - } + if (node->u.unary_expression.type != UNARY_SIGNED_CONSTANT) { + ret = FALSE; + } + } - return ret; + return ret; } -static -int get_unary_signed(struct bt_list_head *head, int64_t *value) +static int get_unary_signed(struct bt_list_head *head, int64_t *value) { - int i = 0; - int ret = 0; - struct ctf_node *node; - - bt_list_for_each_entry(node, head, siblings) { - int uexpr_type = node->u.unary_expression.type; - int uexpr_link = node->u.unary_expression.link; - int cond = node->type != NODE_UNARY_EXPRESSION || - (uexpr_type != UNARY_UNSIGNED_CONSTANT && - uexpr_type != UNARY_SIGNED_CONSTANT) || - uexpr_link != UNARY_LINK_UNKNOWN || i != 0; - if (cond) { - ret = -EINVAL; - goto end; - } - - switch (uexpr_type) { - case UNARY_UNSIGNED_CONSTANT: - *value = (int64_t) - node->u.unary_expression.u.unsigned_constant; - break; - case UNARY_SIGNED_CONSTANT: - *value = node->u.unary_expression.u.signed_constant; - break; - default: - ret = -EINVAL; - goto end; - } - - i++; - } + int i = 0; + int ret = 0; + struct ctf_node *node; + + bt_list_for_each_entry (node, head, siblings) { + int uexpr_type = node->u.unary_expression.type; + int uexpr_link = node->u.unary_expression.link; + int cond = node->type != NODE_UNARY_EXPRESSION || + (uexpr_type != UNARY_UNSIGNED_CONSTANT && uexpr_type != UNARY_SIGNED_CONSTANT) || + uexpr_link != UNARY_LINK_UNKNOWN || i != 0; + if (cond) { + ret = -EINVAL; + goto end; + } + + switch (uexpr_type) { + case UNARY_UNSIGNED_CONSTANT: + *value = (int64_t) node->u.unary_expression.u.unsigned_constant; + break; + case UNARY_SIGNED_CONSTANT: + *value = node->u.unary_expression.u.signed_constant; + break; + default: + ret = -EINVAL; + goto end; + } + + i++; + } end: - return ret; + return ret; } -static -int get_unary_uuid(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *head, - bt_uuid_t uuid) +static int get_unary_uuid(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *head, + bt_uuid_t uuid) { - return ctf_ast_get_unary_uuid(head, uuid, ctx->log_cfg.log_level, - ctx->log_cfg.self_comp); + return ctf_ast_get_unary_uuid(head, uuid, ctx->log_cfg.log_level, ctx->log_cfg.self_comp); } -static -int get_boolean(struct ctf_visitor_generate_ir *ctx, struct ctf_node *unary_expr) +static int get_boolean(struct ctf_visitor_generate_ir *ctx, struct ctf_node *unary_expr) { - int ret = 0; - - if (unary_expr->type != NODE_UNARY_EXPRESSION) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, - "Expecting unary expression: node-type=%d", - unary_expr->type); - ret = -EINVAL; - goto end; - } - - switch (unary_expr->u.unary_expression.type) { - case UNARY_UNSIGNED_CONSTANT: - ret = (unary_expr->u.unary_expression.u.unsigned_constant != 0); - break; - case UNARY_SIGNED_CONSTANT: - ret = (unary_expr->u.unary_expression.u.signed_constant != 0); - break; - case UNARY_STRING: - { - const char *str = unary_expr->u.unary_expression.u.string; - - if (strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0) { - ret = TRUE; - } else if (strcmp(str, "false") == 0 || strcmp(str, "FALSE") == 0) { - ret = FALSE; - } else { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, - "Unexpected boolean value: value=\"%s\"", str); - ret = -EINVAL; - goto end; - } - break; - } - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, - "Unexpected unary expression type: node-type=%d", - unary_expr->u.unary_expression.type); - ret = -EINVAL; - goto end; - } + int ret = 0; + + if (unary_expr->type != NODE_UNARY_EXPRESSION) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, "Expecting unary expression: node-type=%d", + unary_expr->type); + ret = -EINVAL; + goto end; + } + + switch (unary_expr->u.unary_expression.type) { + case UNARY_UNSIGNED_CONSTANT: + ret = (unary_expr->u.unary_expression.u.unsigned_constant != 0); + break; + case UNARY_SIGNED_CONSTANT: + ret = (unary_expr->u.unary_expression.u.signed_constant != 0); + break; + case UNARY_STRING: + { + const char *str = unary_expr->u.unary_expression.u.string; + + if (strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0) { + ret = TRUE; + } else if (strcmp(str, "false") == 0 || strcmp(str, "FALSE") == 0) { + ret = FALSE; + } else { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, "Unexpected boolean value: value=\"%s\"", + str); + ret = -EINVAL; + goto end; + } + break; + } + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, + "Unexpected unary expression type: node-type=%d", + unary_expr->u.unary_expression.type); + ret = -EINVAL; + goto end; + } end: - return ret; + return ret; } -static -enum ctf_byte_order byte_order_from_unary_expr(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *unary_expr) +static enum ctf_byte_order byte_order_from_unary_expr(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *unary_expr) { - const char *str; - enum ctf_byte_order bo = CTF_BYTE_ORDER_UNKNOWN; - - if (unary_expr->u.unary_expression.type != UNARY_STRING) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, - "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`."); - goto end; - } - - str = unary_expr->u.unary_expression.u.string; - - if (strcmp(str, "be") == 0 || strcmp(str, "network") == 0) { - bo = CTF_BYTE_ORDER_BIG; - } else if (strcmp(str, "le") == 0) { - bo = CTF_BYTE_ORDER_LITTLE; - } else if (strcmp(str, "native") == 0) { - bo = CTF_BYTE_ORDER_DEFAULT; - } else { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, - "Unexpected \"byte_order\" attribute value: " - "expecting `be`, `le`, `network`, or `native`: value=\"%s\"", - str); - goto end; - } + const char *str; + enum ctf_byte_order bo = CTF_BYTE_ORDER_UNKNOWN; + + if (unary_expr->u.unary_expression.type != UNARY_STRING) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + unary_expr, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`."); + goto end; + } + + str = unary_expr->u.unary_expression.u.string; + + if (strcmp(str, "be") == 0 || strcmp(str, "network") == 0) { + bo = CTF_BYTE_ORDER_BIG; + } else if (strcmp(str, "le") == 0) { + bo = CTF_BYTE_ORDER_LITTLE; + } else if (strcmp(str, "native") == 0) { + bo = CTF_BYTE_ORDER_DEFAULT; + } else { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + unary_expr, + "Unexpected \"byte_order\" attribute value: " + "expecting `be`, `le`, `network`, or `native`: value=\"%s\"", + str); + goto end; + } end: - return bo; + return bo; } -static -enum ctf_byte_order get_real_byte_order(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *uexpr) +static enum ctf_byte_order get_real_byte_order(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *uexpr) { - enum ctf_byte_order bo = byte_order_from_unary_expr(ctx, uexpr); + enum ctf_byte_order bo = byte_order_from_unary_expr(ctx, uexpr); - if (bo == CTF_BYTE_ORDER_DEFAULT) { - bo = ctx->ctf_tc->default_byte_order; - } + if (bo == CTF_BYTE_ORDER_DEFAULT) { + bo = ctx->ctf_tc->default_byte_order; + } - return bo; + return bo; } -static -int is_align_valid(uint64_t align) +static int is_align_valid(uint64_t align) { - return (align != 0) && !(align & (align - UINT64_C(1))); + return (align != 0) && !(align & (align - UINT64_C(1))); } -static -int get_class_specifier_name(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *cls_specifier, GString *str) +static int get_class_specifier_name(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *cls_specifier, GString *str) { - int ret = 0; - - if (cls_specifier->type != NODE_TYPE_SPECIFIER) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier, - "Unexpected node type: node-type=%d", - cls_specifier->type); - ret = -EINVAL; - goto end; - } - - switch (cls_specifier->u.field_class_specifier.type) { - case TYPESPEC_VOID: - g_string_append(str, "void"); - break; - case TYPESPEC_CHAR: - g_string_append(str, "char"); - break; - case TYPESPEC_SHORT: - g_string_append(str, "short"); - break; - case TYPESPEC_INT: - g_string_append(str, "int"); - break; - case TYPESPEC_LONG: - g_string_append(str, "long"); - break; - case TYPESPEC_FLOAT: - g_string_append(str, "float"); - break; - case TYPESPEC_DOUBLE: - g_string_append(str, "double"); - break; - case TYPESPEC_SIGNED: - g_string_append(str, "signed"); - break; - case TYPESPEC_UNSIGNED: - g_string_append(str, "unsigned"); - break; - case TYPESPEC_BOOL: - g_string_append(str, "bool"); - break; - case TYPESPEC_COMPLEX: - g_string_append(str, "_Complex"); - break; - case TYPESPEC_IMAGINARY: - g_string_append(str, "_Imaginary"); - break; - case TYPESPEC_CONST: - g_string_append(str, "const"); - break; - case TYPESPEC_ID_TYPE: - if (cls_specifier->u.field_class_specifier.id_type) { - g_string_append(str, - cls_specifier->u.field_class_specifier.id_type); - } - break; - case TYPESPEC_STRUCT: - { - struct ctf_node *node = cls_specifier->u.field_class_specifier.node; - - if (!node->u._struct.name) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected empty structure field class name."); - ret = -EINVAL; - goto end; - } - - g_string_append(str, "struct "); - g_string_append(str, node->u._struct.name); - break; - } - case TYPESPEC_VARIANT: - { - struct ctf_node *node = cls_specifier->u.field_class_specifier.node; - - if (!node->u.variant.name) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected empty variant field class name."); - ret = -EINVAL; - goto end; - } - - g_string_append(str, "variant "); - g_string_append(str, node->u.variant.name); - break; - } - case TYPESPEC_ENUM: - { - struct ctf_node *node = cls_specifier->u.field_class_specifier.node; - - if (!node->u._enum.enum_id) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Unexpected empty enumeration field class (`enum`) name."); - ret = -EINVAL; - goto end; - } - - g_string_append(str, "enum "); - g_string_append(str, node->u._enum.enum_id); - break; - } - case TYPESPEC_FLOATING_POINT: - case TYPESPEC_INTEGER: - case TYPESPEC_STRING: - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier->u.field_class_specifier.node, - "Unexpected field class specifier type: %d", - cls_specifier->u.field_class_specifier.type); - ret = -EINVAL; - goto end; - } + int ret = 0; + + if (cls_specifier->type != NODE_TYPE_SPECIFIER) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier, "Unexpected node type: node-type=%d", + cls_specifier->type); + ret = -EINVAL; + goto end; + } + + switch (cls_specifier->u.field_class_specifier.type) { + case TYPESPEC_VOID: + g_string_append(str, "void"); + break; + case TYPESPEC_CHAR: + g_string_append(str, "char"); + break; + case TYPESPEC_SHORT: + g_string_append(str, "short"); + break; + case TYPESPEC_INT: + g_string_append(str, "int"); + break; + case TYPESPEC_LONG: + g_string_append(str, "long"); + break; + case TYPESPEC_FLOAT: + g_string_append(str, "float"); + break; + case TYPESPEC_DOUBLE: + g_string_append(str, "double"); + break; + case TYPESPEC_SIGNED: + g_string_append(str, "signed"); + break; + case TYPESPEC_UNSIGNED: + g_string_append(str, "unsigned"); + break; + case TYPESPEC_BOOL: + g_string_append(str, "bool"); + break; + case TYPESPEC_COMPLEX: + g_string_append(str, "_Complex"); + break; + case TYPESPEC_IMAGINARY: + g_string_append(str, "_Imaginary"); + break; + case TYPESPEC_CONST: + g_string_append(str, "const"); + break; + case TYPESPEC_ID_TYPE: + if (cls_specifier->u.field_class_specifier.id_type) { + g_string_append(str, cls_specifier->u.field_class_specifier.id_type); + } + break; + case TYPESPEC_STRUCT: + { + struct ctf_node *node = cls_specifier->u.field_class_specifier.node; + + if (!node->u._struct.name) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected empty structure field class name."); + ret = -EINVAL; + goto end; + } + + g_string_append(str, "struct "); + g_string_append(str, node->u._struct.name); + break; + } + case TYPESPEC_VARIANT: + { + struct ctf_node *node = cls_specifier->u.field_class_specifier.node; + + if (!node->u.variant.name) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected empty variant field class name."); + ret = -EINVAL; + goto end; + } + + g_string_append(str, "variant "); + g_string_append(str, node->u.variant.name); + break; + } + case TYPESPEC_ENUM: + { + struct ctf_node *node = cls_specifier->u.field_class_specifier.node; + + if (!node->u._enum.enum_id) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Unexpected empty enumeration field class (`enum`) name."); + ret = -EINVAL; + goto end; + } + + g_string_append(str, "enum "); + g_string_append(str, node->u._enum.enum_id); + break; + } + case TYPESPEC_FLOATING_POINT: + case TYPESPEC_INTEGER: + case TYPESPEC_STRING: + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier->u.field_class_specifier.node, + "Unexpected field class specifier type: %d", + cls_specifier->u.field_class_specifier.type); + ret = -EINVAL; + goto end; + } end: - return ret; + return ret; } -static -int get_class_specifier_list_name(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *cls_specifier_list, GString *str) +static int get_class_specifier_list_name(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *cls_specifier_list, GString *str) { - int ret = 0; - struct ctf_node *iter; - int alias_item_nr = 0; - struct bt_list_head *head = - &cls_specifier_list->u.field_class_specifier_list.head; - - bt_list_for_each_entry(iter, head, siblings) { - if (alias_item_nr != 0) { - g_string_append(str, " "); - } - - alias_item_nr++; - ret = get_class_specifier_name(ctx, iter, str); - if (ret) { - goto end; - } - } + int ret = 0; + struct ctf_node *iter; + int alias_item_nr = 0; + struct bt_list_head *head = &cls_specifier_list->u.field_class_specifier_list.head; + + bt_list_for_each_entry (iter, head, siblings) { + if (alias_item_nr != 0) { + g_string_append(str, " "); + } + + alias_item_nr++; + ret = get_class_specifier_name(ctx, iter, str); + if (ret) { + goto end; + } + } end: - return ret; + return ret; } -static -GQuark create_class_alias_identifier(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *cls_specifier_list, - struct ctf_node *node_field_class_declarator) +static GQuark create_class_alias_identifier(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *cls_specifier_list, + struct ctf_node *node_field_class_declarator) { - int ret; - char *str_c; - GString *str; - GQuark qalias = 0; - struct ctf_node *iter; - struct bt_list_head *pointers = - &node_field_class_declarator->u.field_class_declarator.pointers; - - str = g_string_new(""); - ret = get_class_specifier_list_name(ctx, cls_specifier_list, str); - if (ret) { - g_string_free(str, TRUE); - goto end; - } - - bt_list_for_each_entry(iter, pointers, siblings) { - g_string_append(str, " *"); - - if (iter->u.pointer.const_qualifier) { - g_string_append(str, " const"); - } - } - - str_c = g_string_free(str, FALSE); - qalias = g_quark_from_string(str_c); - g_free(str_c); + int ret; + char *str_c; + GString *str; + GQuark qalias = 0; + struct ctf_node *iter; + struct bt_list_head *pointers = &node_field_class_declarator->u.field_class_declarator.pointers; + + str = g_string_new(""); + ret = get_class_specifier_list_name(ctx, cls_specifier_list, str); + if (ret) { + g_string_free(str, TRUE); + goto end; + } + + bt_list_for_each_entry (iter, pointers, siblings) { + g_string_append(str, " *"); + + if (iter->u.pointer.const_qualifier) { + g_string_append(str, " const"); + } + } + + str_c = g_string_free(str, FALSE); + qalias = g_quark_from_string(str_c); + g_free(str_c); end: - return qalias; + return qalias; } -static -int visit_field_class_declarator(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *cls_specifier_list, - GQuark *field_name, struct ctf_node *node_field_class_declarator, - struct ctf_field_class **field_decl, - struct ctf_field_class *nested_decl) +static int visit_field_class_declarator(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *cls_specifier_list, GQuark *field_name, + struct ctf_node *node_field_class_declarator, + struct ctf_field_class **field_decl, + struct ctf_field_class *nested_decl) { - /* - * During this whole function, nested_decl is always OURS, - * whereas field_decl is an output which we create, but - * belongs to the caller (it is moved). - */ - int ret = 0; - *field_decl = NULL; - - /* Validate field class declarator node */ - if (node_field_class_declarator) { - if (node_field_class_declarator->u.field_class_declarator.type == - TYPEDEC_UNKNOWN) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, - "Unexpected field class declarator type: type=%d", - node_field_class_declarator->u.field_class_declarator.type); - ret = -EINVAL; - goto error; - } - - /* TODO: GCC bitfields not supported yet */ - if (node_field_class_declarator->u.field_class_declarator.bitfield_len != - NULL) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, - "GCC bitfields are not supported as of this version."); - ret = -EPERM; - goto error; - } - } - - /* Find the right nested declaration if not provided */ - if (!nested_decl) { - struct bt_list_head *pointers = - &node_field_class_declarator->u.field_class_declarator.pointers; - - if (node_field_class_declarator && !bt_list_empty(pointers)) { - GQuark qalias; - - /* - * If we have a pointer declarator, it HAS to + /* + * During this whole function, nested_decl is always OURS, + * whereas field_decl is an output which we create, but + * belongs to the caller (it is moved). + */ + int ret = 0; + *field_decl = NULL; + + /* Validate field class declarator node */ + if (node_field_class_declarator) { + if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_UNKNOWN) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node_field_class_declarator, "Unexpected field class declarator type: type=%d", + node_field_class_declarator->u.field_class_declarator.type); + ret = -EINVAL; + goto error; + } + + /* TODO: GCC bitfields not supported yet */ + if (node_field_class_declarator->u.field_class_declarator.bitfield_len != NULL) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, + "GCC bitfields are not supported as of this version."); + ret = -EPERM; + goto error; + } + } + + /* Find the right nested declaration if not provided */ + if (!nested_decl) { + struct bt_list_head *pointers = + &node_field_class_declarator->u.field_class_declarator.pointers; + + if (node_field_class_declarator && !bt_list_empty(pointers)) { + GQuark qalias; + + /* + * If we have a pointer declarator, it HAS to * be present in the field class aliases (else * fail). - */ - qalias = create_class_alias_identifier(ctx, - cls_specifier_list, node_field_class_declarator); - nested_decl = - ctx_decl_scope_lookup_alias(ctx, - ctx->current_scope, - g_quark_to_string(qalias), -1, true); - if (!nested_decl) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, - "Cannot find class alias: name=\"%s\"", - g_quark_to_string(qalias)); - ret = -EINVAL; - goto error; - } - - if (nested_decl->type == CTF_FIELD_CLASS_TYPE_INT) { - /* Pointer: force integer's base to 16 */ - struct ctf_field_class_int *int_fc = - ctf_field_class_as_int(nested_decl); - - int_fc->disp_base = - BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL; - } - } else { - ret = visit_field_class_specifier_list(ctx, - cls_specifier_list, &nested_decl); - if (ret) { - BT_ASSERT(!nested_decl); - goto error; - } - } - } - - BT_ASSERT(nested_decl); - - if (!node_field_class_declarator) { - *field_decl = nested_decl; - nested_decl = NULL; - goto end; - } - - if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_ID) { - if (node_field_class_declarator->u.field_class_declarator.u.id) { - const char *id = - node_field_class_declarator->u.field_class_declarator.u.id; - - *field_name = g_quark_from_string(id); - } else { - *field_name = 0; - } - - *field_decl = nested_decl; - nested_decl = NULL; - goto end; - } else { - struct ctf_node *first; - struct ctf_field_class *decl = NULL; - struct ctf_field_class *outer_field_decl = NULL; - struct bt_list_head *length = - &node_field_class_declarator-> - u.field_class_declarator.u.nested.length; - - /* Create array/sequence, pass nested_decl as child */ - if (bt_list_empty(length)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, - "Expecting length field reference or value."); - ret = -EINVAL; - goto error; - } - - first = _BT_LIST_FIRST_ENTRY(length, struct ctf_node, siblings); - if (first->type != NODE_UNARY_EXPRESSION) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, - "Unexpected node type: node-type=%d", - first->type); - ret = -EINVAL; - goto error; - } - - switch (first->u.unary_expression.type) { - case UNARY_UNSIGNED_CONSTANT: - { - struct ctf_field_class_array *array_decl = NULL; - - array_decl = ctf_field_class_array_create(); - BT_ASSERT(array_decl); - array_decl->length = - first->u.unary_expression.u.unsigned_constant; - array_decl->base.elem_fc = nested_decl; - nested_decl = NULL; - decl = &array_decl->base.base; - break; - } - case UNARY_STRING: - { - /* Lookup unsigned integer definition, create seq. */ - struct ctf_field_class_sequence *seq_decl = NULL; - char *length_name = ctf_ast_concatenate_unary_strings(length); - - if (!length_name) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, - "Cannot concatenate unary strings."); - ret = -EINVAL; - goto error; - } - - if (strncmp(length_name, "env.", 4) == 0) { - /* This is, in fact, an array */ - const char *env_entry_name = &length_name[4]; - struct ctf_trace_class_env_entry *env_entry = - ctf_trace_class_borrow_env_entry_by_name( - ctx->ctf_tc, env_entry_name); - struct ctf_field_class_array *array_decl; - - if (!env_entry) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, - "Cannot find environment entry: " - "name=\"%s\"", env_entry_name); - ret = -EINVAL; - goto error; - } - - if (env_entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, - "Wrong environment entry type " - "(expecting integer): " - "name=\"%s\"", env_entry_name); - ret = -EINVAL; - goto error; - } - - if (env_entry->value.i < 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, - "Invalid, negative array length: " - "env-entry-name=\"%s\", " - "value=%" PRId64, - env_entry_name, - env_entry->value.i); - ret = -EINVAL; - goto error; - } - - array_decl = ctf_field_class_array_create(); - BT_ASSERT(array_decl); - array_decl->length = - (uint64_t) env_entry->value.i; - array_decl->base.elem_fc = nested_decl; - nested_decl = NULL; - decl = &array_decl->base.base; - } else { - seq_decl = ctf_field_class_sequence_create(); - BT_ASSERT(seq_decl); - seq_decl->base.elem_fc = nested_decl; - nested_decl = NULL; - g_string_assign(seq_decl->length_ref, - length_name); - decl = &seq_decl->base.base; - } - - g_free(length_name); - break; - } - default: - ret = -EINVAL; - goto error; - } - - BT_ASSERT(!nested_decl); - BT_ASSERT(decl); - BT_ASSERT(!*field_decl); - - /* - * At this point, we found the next nested declaration. - * We currently own this (and lost the ownership of - * nested_decl in the meantime). Pass this next - * nested declaration as the content of the outer - * container, MOVING its ownership. - */ - ret = visit_field_class_declarator(ctx, cls_specifier_list, - field_name, - node_field_class_declarator-> - u.field_class_declarator.u.nested.field_class_declarator, - &outer_field_decl, decl); - decl = NULL; - if (ret) { - BT_ASSERT(!outer_field_decl); - ret = -EINVAL; - goto error; - } - - BT_ASSERT(outer_field_decl); - *field_decl = outer_field_decl; - outer_field_decl = NULL; - } - - BT_ASSERT(*field_decl); - goto end; + */ + qalias = + create_class_alias_identifier(ctx, cls_specifier_list, node_field_class_declarator); + nested_decl = ctx_decl_scope_lookup_alias(ctx, ctx->current_scope, + g_quark_to_string(qalias), -1, true); + if (!nested_decl) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, + "Cannot find class alias: name=\"%s\"", + g_quark_to_string(qalias)); + ret = -EINVAL; + goto error; + } + + if (nested_decl->type == CTF_FIELD_CLASS_TYPE_INT) { + /* Pointer: force integer's base to 16 */ + struct ctf_field_class_int *int_fc = ctf_field_class_as_int(nested_decl); + + int_fc->disp_base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL; + } + } else { + ret = visit_field_class_specifier_list(ctx, cls_specifier_list, &nested_decl); + if (ret) { + BT_ASSERT(!nested_decl); + goto error; + } + } + } + + BT_ASSERT(nested_decl); + + if (!node_field_class_declarator) { + *field_decl = nested_decl; + nested_decl = NULL; + goto end; + } + + if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_ID) { + if (node_field_class_declarator->u.field_class_declarator.u.id) { + const char *id = node_field_class_declarator->u.field_class_declarator.u.id; + + *field_name = g_quark_from_string(id); + } else { + *field_name = 0; + } + + *field_decl = nested_decl; + nested_decl = NULL; + goto end; + } else { + struct ctf_node *first; + struct ctf_field_class *decl = NULL; + struct ctf_field_class *outer_field_decl = NULL; + struct bt_list_head *length = + &node_field_class_declarator->u.field_class_declarator.u.nested.length; + + /* Create array/sequence, pass nested_decl as child */ + if (bt_list_empty(length)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, + "Expecting length field reference or value."); + ret = -EINVAL; + goto error; + } + + first = _BT_LIST_FIRST_ENTRY(length, struct ctf_node, siblings); + if (first->type != NODE_UNARY_EXPRESSION) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, "Unexpected node type: node-type=%d", + first->type); + ret = -EINVAL; + goto error; + } + + switch (first->u.unary_expression.type) { + case UNARY_UNSIGNED_CONSTANT: + { + struct ctf_field_class_array *array_decl = NULL; + + array_decl = ctf_field_class_array_create(); + BT_ASSERT(array_decl); + array_decl->length = first->u.unary_expression.u.unsigned_constant; + array_decl->base.elem_fc = nested_decl; + nested_decl = NULL; + decl = &array_decl->base.base; + break; + } + case UNARY_STRING: + { + /* Lookup unsigned integer definition, create seq. */ + struct ctf_field_class_sequence *seq_decl = NULL; + char *length_name = ctf_ast_concatenate_unary_strings(length); + + if (!length_name) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, + "Cannot concatenate unary strings."); + ret = -EINVAL; + goto error; + } + + if (strncmp(length_name, "env.", 4) == 0) { + /* This is, in fact, an array */ + const char *env_entry_name = &length_name[4]; + struct ctf_trace_class_env_entry *env_entry = + ctf_trace_class_borrow_env_entry_by_name(ctx->ctf_tc, env_entry_name); + struct ctf_field_class_array *array_decl; + + if (!env_entry) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, + "Cannot find environment entry: " + "name=\"%s\"", + env_entry_name); + ret = -EINVAL; + goto error; + } + + if (env_entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, + "Wrong environment entry type " + "(expecting integer): " + "name=\"%s\"", + env_entry_name); + ret = -EINVAL; + goto error; + } + + if (env_entry->value.i < 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator, + "Invalid, negative array length: " + "env-entry-name=\"%s\", " + "value=%" PRId64, + env_entry_name, env_entry->value.i); + ret = -EINVAL; + goto error; + } + + array_decl = ctf_field_class_array_create(); + BT_ASSERT(array_decl); + array_decl->length = (uint64_t) env_entry->value.i; + array_decl->base.elem_fc = nested_decl; + nested_decl = NULL; + decl = &array_decl->base.base; + } else { + seq_decl = ctf_field_class_sequence_create(); + BT_ASSERT(seq_decl); + seq_decl->base.elem_fc = nested_decl; + nested_decl = NULL; + g_string_assign(seq_decl->length_ref, length_name); + decl = &seq_decl->base.base; + } + + g_free(length_name); + break; + } + default: + ret = -EINVAL; + goto error; + } + + BT_ASSERT(!nested_decl); + BT_ASSERT(decl); + BT_ASSERT(!*field_decl); + + /* + * At this point, we found the next nested declaration. + * We currently own this (and lost the ownership of + * nested_decl in the meantime). Pass this next + * nested declaration as the content of the outer + * container, MOVING its ownership. + */ + ret = visit_field_class_declarator( + ctx, cls_specifier_list, field_name, + node_field_class_declarator->u.field_class_declarator.u.nested.field_class_declarator, + &outer_field_decl, decl); + decl = NULL; + if (ret) { + BT_ASSERT(!outer_field_decl); + ret = -EINVAL; + goto error; + } + + BT_ASSERT(outer_field_decl); + *field_decl = outer_field_decl; + outer_field_decl = NULL; + } + + BT_ASSERT(*field_decl); + goto end; error: - ctf_field_class_destroy(*field_decl); - *field_decl = NULL; + ctf_field_class_destroy(*field_decl); + *field_decl = NULL; - if (ret >= 0) { - ret = -1; - } + if (ret >= 0) { + ret = -1; + } end: - ctf_field_class_destroy(nested_decl); - nested_decl = NULL; - return ret; + ctf_field_class_destroy(nested_decl); + nested_decl = NULL; + return ret; } -static -int visit_struct_decl_field(struct ctf_visitor_generate_ir *ctx, - struct ctf_field_class_struct *struct_decl, - struct ctf_node *cls_specifier_list, - struct bt_list_head *field_class_declarators) +static int visit_struct_decl_field(struct ctf_visitor_generate_ir *ctx, + struct ctf_field_class_struct *struct_decl, + struct ctf_node *cls_specifier_list, + struct bt_list_head *field_class_declarators) { - int ret = 0; - struct ctf_node *iter; - struct ctf_field_class *field_decl = NULL; - - bt_list_for_each_entry(iter, field_class_declarators, siblings) { - field_decl = NULL; - GQuark qfield_name; - const char *field_name; - - ret = visit_field_class_declarator(ctx, cls_specifier_list, - &qfield_name, iter, &field_decl, NULL); - if (ret) { - BT_ASSERT(!field_decl); - _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, - "Cannot visit field class declarator: ret=%d", ret); - goto error; - } - - BT_ASSERT(field_decl); - field_name = g_quark_to_string(qfield_name); - - /* Check if field with same name already exists */ - if (ctf_field_class_struct_borrow_member_by_name( - struct_decl, field_name)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, - "Duplicate field in structure field class: " - "field-name=\"%s\"", field_name); - ret = -EINVAL; - goto error; - } - - /* Add field to structure */ - ctf_field_class_struct_append_member(struct_decl, - field_name, field_decl); - field_decl = NULL; - } - - return 0; + int ret = 0; + struct ctf_node *iter; + struct ctf_field_class *field_decl = NULL; + + bt_list_for_each_entry (iter, field_class_declarators, siblings) { + field_decl = NULL; + GQuark qfield_name; + const char *field_name; + + ret = visit_field_class_declarator(ctx, cls_specifier_list, &qfield_name, iter, &field_decl, + NULL); + if (ret) { + BT_ASSERT(!field_decl); + _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, + "Cannot visit field class declarator: ret=%d", ret); + goto error; + } + + BT_ASSERT(field_decl); + field_name = g_quark_to_string(qfield_name); + + /* Check if field with same name already exists */ + if (ctf_field_class_struct_borrow_member_by_name(struct_decl, field_name)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, + "Duplicate field in structure field class: " + "field-name=\"%s\"", + field_name); + ret = -EINVAL; + goto error; + } + + /* Add field to structure */ + ctf_field_class_struct_append_member(struct_decl, field_name, field_decl); + field_decl = NULL; + } + + return 0; error: - ctf_field_class_destroy(field_decl); - field_decl = NULL; - return ret; + ctf_field_class_destroy(field_decl); + field_decl = NULL; + return ret; } -static -int visit_variant_decl_field(struct ctf_visitor_generate_ir *ctx, - struct ctf_field_class_variant *variant_decl, - struct ctf_node *cls_specifier_list, - struct bt_list_head *field_class_declarators) +static int visit_variant_decl_field(struct ctf_visitor_generate_ir *ctx, + struct ctf_field_class_variant *variant_decl, + struct ctf_node *cls_specifier_list, + struct bt_list_head *field_class_declarators) { - int ret = 0; - struct ctf_node *iter; - struct ctf_field_class *field_decl = NULL; - - bt_list_for_each_entry(iter, field_class_declarators, siblings) { - field_decl = NULL; - GQuark qfield_name; - const char *field_name; - - ret = visit_field_class_declarator(ctx, cls_specifier_list, - &qfield_name, iter, &field_decl, NULL); - if (ret) { - BT_ASSERT(!field_decl); - _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, - "Cannot visit field class declarator: ret=%d", ret); - goto error; - } - - BT_ASSERT(field_decl); - field_name = g_quark_to_string(qfield_name); - - /* Check if field with same name already exists */ - if (ctf_field_class_variant_borrow_option_by_name( - variant_decl, field_name)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, - "Duplicate field in variant field class: " - "field-name=\"%s\"", field_name); - ret = -EINVAL; - goto error; - } - - /* Add field to structure */ - ctf_field_class_variant_append_option(variant_decl, - field_name, field_decl); - field_decl = NULL; - } - - return 0; + int ret = 0; + struct ctf_node *iter; + struct ctf_field_class *field_decl = NULL; + + bt_list_for_each_entry (iter, field_class_declarators, siblings) { + field_decl = NULL; + GQuark qfield_name; + const char *field_name; + + ret = visit_field_class_declarator(ctx, cls_specifier_list, &qfield_name, iter, &field_decl, + NULL); + if (ret) { + BT_ASSERT(!field_decl); + _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, + "Cannot visit field class declarator: ret=%d", ret); + goto error; + } + + BT_ASSERT(field_decl); + field_name = g_quark_to_string(qfield_name); + + /* Check if field with same name already exists */ + if (ctf_field_class_variant_borrow_option_by_name(variant_decl, field_name)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, + "Duplicate field in variant field class: " + "field-name=\"%s\"", + field_name); + ret = -EINVAL; + goto error; + } + + /* Add field to structure */ + ctf_field_class_variant_append_option(variant_decl, field_name, field_decl); + field_decl = NULL; + } + + return 0; error: - ctf_field_class_destroy(field_decl); - field_decl = NULL; - return ret; + ctf_field_class_destroy(field_decl); + field_decl = NULL; + return ret; } -static -int visit_field_class_def(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *cls_specifier_list, - struct bt_list_head *field_class_declarators) +static int visit_field_class_def(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *cls_specifier_list, + struct bt_list_head *field_class_declarators) { - int ret = 0; - GQuark qidentifier; - struct ctf_node *iter; - struct ctf_field_class *class_decl = NULL; - - bt_list_for_each_entry(iter, field_class_declarators, siblings) { - ret = visit_field_class_declarator(ctx, cls_specifier_list, - &qidentifier, iter, &class_decl, NULL); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot visit field class declarator: ret=%d", ret); - ret = -EINVAL; - goto end; - } - - /* Do not allow field class def and alias of untagged variants */ - if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) { - struct ctf_field_class_variant *var_fc = - ctf_field_class_as_variant(class_decl); - - if (var_fc->tag_path.path->len == 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Type definition of untagged variant field class is not allowed."); - ret = -EPERM; - goto end; - } - } - - ret = ctx_decl_scope_register_alias(ctx, ctx->current_scope, - g_quark_to_string(qidentifier), class_decl); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot register field class alias: name=\"%s\"", - g_quark_to_string(qidentifier)); - goto end; - } - } + int ret = 0; + GQuark qidentifier; + struct ctf_node *iter; + struct ctf_field_class *class_decl = NULL; + + bt_list_for_each_entry (iter, field_class_declarators, siblings) { + ret = visit_field_class_declarator(ctx, cls_specifier_list, &qidentifier, iter, &class_decl, + NULL); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit field class declarator: ret=%d", + ret); + ret = -EINVAL; + goto end; + } + + /* Do not allow field class def and alias of untagged variants */ + if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) { + struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(class_decl); + + if (var_fc->tag_path.path->len == 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + iter, "Type definition of untagged variant field class is not allowed."); + ret = -EPERM; + goto end; + } + } + + ret = ctx_decl_scope_register_alias(ctx, ctx->current_scope, g_quark_to_string(qidentifier), + class_decl); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot register field class alias: name=\"%s\"", + g_quark_to_string(qidentifier)); + goto end; + } + } end: - ctf_field_class_destroy(class_decl); - class_decl = NULL; - return ret; + ctf_field_class_destroy(class_decl); + class_decl = NULL; + return ret; } -static -int visit_field_class_alias(struct ctf_visitor_generate_ir *ctx, struct ctf_node *target, - struct ctf_node *alias) +static int visit_field_class_alias(struct ctf_visitor_generate_ir *ctx, struct ctf_node *target, + struct ctf_node *alias) { - int ret = 0; - GQuark qalias; - struct ctf_node *node; - GQuark qdummy_field_name; - struct ctf_field_class *class_decl = NULL; - - /* Create target field class */ - if (bt_list_empty(&target->u.field_class_alias_target.field_class_declarators)) { - node = NULL; - } else { - node = _BT_LIST_FIRST_ENTRY( - &target->u.field_class_alias_target.field_class_declarators, - struct ctf_node, siblings); - } - - ret = visit_field_class_declarator(ctx, - target->u.field_class_alias_target.field_class_specifier_list, - &qdummy_field_name, node, &class_decl, NULL); - if (ret) { - BT_ASSERT(!class_decl); - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot visit field class declarator: ret=%d", ret); - goto end; - } - - /* Do not allow field class def and alias of untagged variants */ - if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) { - struct ctf_field_class_variant *var_fc = - ctf_field_class_as_variant(class_decl); - - if (var_fc->tag_path.path->len == 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(target, - "Type definition of untagged variant field class is not allowed."); - ret = -EPERM; - goto end; - } - } - - /* - * The semantic validator does not check whether the target is - * abstract or not (if it has an identifier). Check it here. - */ - if (qdummy_field_name != 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(target, - "Expecting empty identifier: id=\"%s\"", - g_quark_to_string(qdummy_field_name)); - ret = -EINVAL; - goto end; - } - - /* Create alias identifier */ - node = _BT_LIST_FIRST_ENTRY(&alias->u.field_class_alias_name.field_class_declarators, - struct ctf_node, siblings); - qalias = create_class_alias_identifier(ctx, - alias->u.field_class_alias_name.field_class_specifier_list, node); - ret = ctx_decl_scope_register_alias(ctx, ctx->current_scope, - g_quark_to_string(qalias), class_decl); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot register class alias: name=\"%s\"", - g_quark_to_string(qalias)); - goto end; - } + int ret = 0; + GQuark qalias; + struct ctf_node *node; + GQuark qdummy_field_name; + struct ctf_field_class *class_decl = NULL; + + /* Create target field class */ + if (bt_list_empty(&target->u.field_class_alias_target.field_class_declarators)) { + node = NULL; + } else { + node = _BT_LIST_FIRST_ENTRY(&target->u.field_class_alias_target.field_class_declarators, + struct ctf_node, siblings); + } + + ret = visit_field_class_declarator( + ctx, target->u.field_class_alias_target.field_class_specifier_list, &qdummy_field_name, + node, &class_decl, NULL); + if (ret) { + BT_ASSERT(!class_decl); + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot visit field class declarator: ret=%d", ret); + goto end; + } + + /* Do not allow field class def and alias of untagged variants */ + if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) { + struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(class_decl); + + if (var_fc->tag_path.path->len == 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + target, "Type definition of untagged variant field class is not allowed."); + ret = -EPERM; + goto end; + } + } + + /* + * The semantic validator does not check whether the target is + * abstract or not (if it has an identifier). Check it here. + */ + if (qdummy_field_name != 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(target, "Expecting empty identifier: id=\"%s\"", + g_quark_to_string(qdummy_field_name)); + ret = -EINVAL; + goto end; + } + + /* Create alias identifier */ + node = _BT_LIST_FIRST_ENTRY(&alias->u.field_class_alias_name.field_class_declarators, + struct ctf_node, siblings); + qalias = create_class_alias_identifier( + ctx, alias->u.field_class_alias_name.field_class_specifier_list, node); + ret = ctx_decl_scope_register_alias(ctx, ctx->current_scope, g_quark_to_string(qalias), + class_decl); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot register class alias: name=\"%s\"", + g_quark_to_string(qalias)); + goto end; + } end: - ctf_field_class_destroy(class_decl); - class_decl = NULL; - return ret; + ctf_field_class_destroy(class_decl); + class_decl = NULL; + return ret; } -static -int visit_struct_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node, - struct ctf_field_class_struct *struct_decl) +static int visit_struct_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node, + struct ctf_field_class_struct *struct_decl) { - int ret = 0; - - switch (entry_node->type) { - case NODE_TYPEDEF: - ret = visit_field_class_def(ctx, - entry_node->u.field_class_def.field_class_specifier_list, - &entry_node->u.field_class_def.field_class_declarators); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Cannot add field class found in structure field class: ret=%d", - ret); - goto end; - } - break; - case NODE_TYPEALIAS: - ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target, - entry_node->u.field_class_alias.alias); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Cannot add field class alias found in structure field class: ret=%d", - ret); - goto end; - } - break; - case NODE_STRUCT_OR_VARIANT_DECLARATION: - /* Field */ - ret = visit_struct_decl_field(ctx, struct_decl, - entry_node->u.struct_or_variant_declaration. - field_class_specifier_list, - &entry_node->u.struct_or_variant_declaration. - field_class_declarators); - if (ret) { - goto end; - } - break; - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected node type: node-type=%d", entry_node->type); - ret = -EINVAL; - goto end; - } + int ret = 0; + + switch (entry_node->type) { + case NODE_TYPEDEF: + ret = visit_field_class_def(ctx, entry_node->u.field_class_def.field_class_specifier_list, + &entry_node->u.field_class_def.field_class_declarators); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Cannot add field class found in structure field class: ret=%d", ret); + goto end; + } + break; + case NODE_TYPEALIAS: + ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target, + entry_node->u.field_class_alias.alias); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Cannot add field class alias found in structure field class: ret=%d", + ret); + goto end; + } + break; + case NODE_STRUCT_OR_VARIANT_DECLARATION: + /* Field */ + ret = visit_struct_decl_field( + ctx, struct_decl, + entry_node->u.struct_or_variant_declaration.field_class_specifier_list, + &entry_node->u.struct_or_variant_declaration.field_class_declarators); + if (ret) { + goto end; + } + break; + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Unexpected node type: node-type=%d", + entry_node->type); + ret = -EINVAL; + goto end; + } end: - return ret; + return ret; } -static -int visit_variant_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node, - struct ctf_field_class_variant *variant_decl) +static int visit_variant_decl_entry(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *entry_node, + struct ctf_field_class_variant *variant_decl) { - int ret = 0; - - switch (entry_node->type) { - case NODE_TYPEDEF: - ret = visit_field_class_def(ctx, - entry_node->u.field_class_def.field_class_specifier_list, - &entry_node->u.field_class_def.field_class_declarators); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Cannot add field class found in variant field class: ret=%d", - ret); - goto end; - } - break; - case NODE_TYPEALIAS: - ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target, - entry_node->u.field_class_alias.alias); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Cannot add field class alias found in variant field class: ret=%d", - ret); - goto end; - } - break; - case NODE_STRUCT_OR_VARIANT_DECLARATION: - /* Field */ - ret = visit_variant_decl_field(ctx, variant_decl, - entry_node->u.struct_or_variant_declaration. - field_class_specifier_list, - &entry_node->u.struct_or_variant_declaration. - field_class_declarators); - if (ret) { - goto end; - } - break; - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected node type: node-type=%d", - entry_node->type); - ret = -EINVAL; - goto end; - } + int ret = 0; + + switch (entry_node->type) { + case NODE_TYPEDEF: + ret = visit_field_class_def(ctx, entry_node->u.field_class_def.field_class_specifier_list, + &entry_node->u.field_class_def.field_class_declarators); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Cannot add field class found in variant field class: ret=%d", ret); + goto end; + } + break; + case NODE_TYPEALIAS: + ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target, + entry_node->u.field_class_alias.alias); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Cannot add field class alias found in variant field class: ret=%d", + ret); + goto end; + } + break; + case NODE_STRUCT_OR_VARIANT_DECLARATION: + /* Field */ + ret = visit_variant_decl_field( + ctx, variant_decl, + entry_node->u.struct_or_variant_declaration.field_class_specifier_list, + &entry_node->u.struct_or_variant_declaration.field_class_declarators); + if (ret) { + goto end; + } + break; + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Unexpected node type: node-type=%d", + entry_node->type); + ret = -EINVAL; + goto end; + } end: - return ret; + return ret; } -static -int visit_struct_decl(struct ctf_visitor_generate_ir *ctx, const char *name, - struct bt_list_head *decl_list, int has_body, - struct bt_list_head *min_align, - struct ctf_field_class_struct **struct_decl) +static int visit_struct_decl(struct ctf_visitor_generate_ir *ctx, const char *name, + struct bt_list_head *decl_list, int has_body, + struct bt_list_head *min_align, + struct ctf_field_class_struct **struct_decl) { - int ret = 0; - - BT_ASSERT(struct_decl); - *struct_decl = NULL; - - /* For named struct (without body), lookup in declaration scope */ - if (!has_body) { - if (!name) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless structure field class: missing name."); - ret = -EPERM; - goto error; - } - - *struct_decl = ctx_decl_scope_lookup_struct(ctx, ctx->current_scope, - name, -1, true); - if (!*struct_decl) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find structure field class: name=\"struct %s\"", - name); - ret = -EINVAL; - goto error; - } - } else { - struct ctf_node *entry_node; - uint64_t min_align_value = 0; - - if (name) { - if (ctx_decl_scope_lookup_struct(ctx, - ctx->current_scope, name, 1, false)) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Structure field class already declared in local scope: " - "name=\"struct %s\"", name); - ret = -EINVAL; - goto error; - } - } - - if (!bt_list_empty(min_align)) { - ret = get_unary_unsigned(ctx, min_align, - &min_align_value); - if (ret) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Unexpected unary expression for structure field class's `align` attribute: " - "ret=%d", ret); - goto error; - } - } - - *struct_decl = ctf_field_class_struct_create(); - BT_ASSERT(*struct_decl); - - if (min_align_value != 0) { - (*struct_decl)->base.alignment = min_align_value; - } - - _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); - - bt_list_for_each_entry(entry_node, decl_list, siblings) { - ret = visit_struct_decl_entry(ctx, entry_node, - *struct_decl); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Cannot visit structure field class entry: " - "ret=%d", ret); - ctx_pop_scope(ctx); - goto error; - } - } - - ctx_pop_scope(ctx); - - if (name) { - ret = ctx_decl_scope_register_struct(ctx, - ctx->current_scope, name, *struct_decl); - if (ret) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register structure field class in declaration scope: " - "name=\"struct %s\", ret=%d", name, ret); - goto error; - } - } - } - - return 0; + int ret = 0; + + BT_ASSERT(struct_decl); + *struct_decl = NULL; + + /* For named struct (without body), lookup in declaration scope */ + if (!has_body) { + if (!name) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Bodyless structure field class: missing name."); + ret = -EPERM; + goto error; + } + + *struct_decl = ctx_decl_scope_lookup_struct(ctx, ctx->current_scope, name, -1, true); + if (!*struct_decl) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Cannot find structure field class: name=\"struct %s\"", name); + ret = -EINVAL; + goto error; + } + } else { + struct ctf_node *entry_node; + uint64_t min_align_value = 0; + + if (name) { + if (ctx_decl_scope_lookup_struct(ctx, ctx->current_scope, name, 1, false)) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Structure field class already declared in local scope: " + "name=\"struct %s\"", + name); + ret = -EINVAL; + goto error; + } + } + + if (!bt_list_empty(min_align)) { + ret = get_unary_unsigned(ctx, min_align, &min_align_value); + if (ret) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Unexpected unary expression for structure field class's `align` attribute: " + "ret=%d", + ret); + goto error; + } + } + + *struct_decl = ctf_field_class_struct_create(); + BT_ASSERT(*struct_decl); + + if (min_align_value != 0) { + (*struct_decl)->base.alignment = min_align_value; + } + + _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); + + bt_list_for_each_entry (entry_node, decl_list, siblings) { + ret = visit_struct_decl_entry(ctx, entry_node, *struct_decl); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, + "Cannot visit structure field class entry: " + "ret=%d", + ret); + ctx_pop_scope(ctx); + goto error; + } + } + + ctx_pop_scope(ctx); + + if (name) { + ret = ctx_decl_scope_register_struct(ctx, ctx->current_scope, name, *struct_decl); + if (ret) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Cannot register structure field class in declaration scope: " + "name=\"struct %s\", ret=%d", + name, ret); + goto error; + } + } + } + + return 0; error: - ctf_field_class_destroy(&(*struct_decl)->base); - *struct_decl = NULL; - return ret; + ctf_field_class_destroy(&(*struct_decl)->base); + *struct_decl = NULL; + return ret; } -static -int visit_variant_decl(struct ctf_visitor_generate_ir *ctx, const char *name, - const char *tag, struct bt_list_head *decl_list, - int has_body, struct ctf_field_class_variant **variant_decl) +static int visit_variant_decl(struct ctf_visitor_generate_ir *ctx, const char *name, + const char *tag, struct bt_list_head *decl_list, int has_body, + struct ctf_field_class_variant **variant_decl) { - int ret = 0; - struct ctf_field_class_variant *untagged_variant_decl = NULL; - - BT_ASSERT(variant_decl); - *variant_decl = NULL; - - /* For named variant (without body), lookup in declaration scope */ - if (!has_body) { - if (!name) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name."); - ret = -EPERM; - goto error; - } - - untagged_variant_decl = - ctx_decl_scope_lookup_variant(ctx, ctx->current_scope, - name, -1, true); - if (!untagged_variant_decl) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find variant field class: name=\"variant %s\"", - name); - ret = -EINVAL; - goto error; - } - } else { - struct ctf_node *entry_node; - - if (name) { - if (ctx_decl_scope_lookup_variant(ctx, - ctx->current_scope, name, 1, false)) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Variant field class already declared in local scope: " - "name=\"variant %s\"", name); - ret = -EINVAL; - goto error; - } - } - - untagged_variant_decl = ctf_field_class_variant_create(); - BT_ASSERT(untagged_variant_decl); - _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); - - bt_list_for_each_entry(entry_node, decl_list, siblings) { - ret = visit_variant_decl_entry(ctx, entry_node, - untagged_variant_decl); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Cannot visit variant field class entry: " - "ret=%d", ret); - ctx_pop_scope(ctx); - goto error; - } - } - - ctx_pop_scope(ctx); - - if (name) { - ret = ctx_decl_scope_register_variant(ctx, - ctx->current_scope, name, - untagged_variant_decl); - if (ret) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register variant field class in declaration scope: " - "name=\"variant %s\", ret=%d", name, ret); - goto error; - } - } - } - - /* - * If tagged, create tagged variant and return; otherwise - * return untagged variant. - */ - if (!tag) { - *variant_decl = untagged_variant_decl; - untagged_variant_decl = NULL; - } else { - /* - * At this point, we have a fresh untagged variant; nobody - * else owns it. Set its tag now. - */ - g_string_assign(untagged_variant_decl->tag_ref, tag); - *variant_decl = untagged_variant_decl; - untagged_variant_decl = NULL; - } - - BT_ASSERT(!untagged_variant_decl); - BT_ASSERT(*variant_decl); - return 0; + int ret = 0; + struct ctf_field_class_variant *untagged_variant_decl = NULL; + + BT_ASSERT(variant_decl); + *variant_decl = NULL; + + /* For named variant (without body), lookup in declaration scope */ + if (!has_body) { + if (!name) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name."); + ret = -EPERM; + goto error; + } + + untagged_variant_decl = + ctx_decl_scope_lookup_variant(ctx, ctx->current_scope, name, -1, true); + if (!untagged_variant_decl) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Cannot find variant field class: name=\"variant %s\"", name); + ret = -EINVAL; + goto error; + } + } else { + struct ctf_node *entry_node; + + if (name) { + if (ctx_decl_scope_lookup_variant(ctx, ctx->current_scope, name, 1, false)) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Variant field class already declared in local scope: " + "name=\"variant %s\"", + name); + ret = -EINVAL; + goto error; + } + } + + untagged_variant_decl = ctf_field_class_variant_create(); + BT_ASSERT(untagged_variant_decl); + _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); + + bt_list_for_each_entry (entry_node, decl_list, siblings) { + ret = visit_variant_decl_entry(ctx, entry_node, untagged_variant_decl); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, + "Cannot visit variant field class entry: " + "ret=%d", + ret); + ctx_pop_scope(ctx); + goto error; + } + } + + ctx_pop_scope(ctx); + + if (name) { + ret = ctx_decl_scope_register_variant(ctx, ctx->current_scope, name, + untagged_variant_decl); + if (ret) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Cannot register variant field class in declaration scope: " + "name=\"variant %s\", ret=%d", + name, ret); + goto error; + } + } + } + + /* + * If tagged, create tagged variant and return; otherwise + * return untagged variant. + */ + if (!tag) { + *variant_decl = untagged_variant_decl; + untagged_variant_decl = NULL; + } else { + /* + * At this point, we have a fresh untagged variant; nobody + * else owns it. Set its tag now. + */ + g_string_assign(untagged_variant_decl->tag_ref, tag); + *variant_decl = untagged_variant_decl; + untagged_variant_decl = NULL; + } + + BT_ASSERT(!untagged_variant_decl); + BT_ASSERT(*variant_decl); + return 0; error: - ctf_field_class_destroy(&untagged_variant_decl->base); - untagged_variant_decl = NULL; - ctf_field_class_destroy(&(*variant_decl)->base); - *variant_decl = NULL; - return ret; + ctf_field_class_destroy(&untagged_variant_decl->base); + untagged_variant_decl = NULL; + ctf_field_class_destroy(&(*variant_decl)->base); + *variant_decl = NULL; + return ret; } -struct uori { - bool is_signed; - union { - uint64_t u; - uint64_t i; - } value; +struct uori +{ + bool is_signed; + union + { + uint64_t u; + uint64_t i; + } value; }; -static -int visit_enum_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *enumerator, - struct ctf_field_class_enum *enum_decl, struct uori *last) +static int visit_enum_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *enumerator, + struct ctf_field_class_enum *enum_decl, struct uori *last) { - int ret = 0; - int nr_vals = 0; - struct ctf_node *iter; - struct uori start = { - .is_signed = false, - .value = { - .u = 0, - }, - }; - struct uori end = { - .is_signed = false, - .value = { - .u = 0, - }, - }; - const char *label = enumerator->u.enumerator.id; - struct bt_list_head *values = &enumerator->u.enumerator.values; - - bt_list_for_each_entry(iter, values, siblings) { - struct uori *target; - - if (iter->type != NODE_UNARY_EXPRESSION) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Wrong expression for enumeration field class label: " - "node-type=%d, label=\"%s\"", iter->type, - label); - ret = -EINVAL; - goto error; - } - - if (nr_vals == 0) { - target = &start; - } else { - target = &end; - } - - switch (iter->u.unary_expression.type) { - case UNARY_SIGNED_CONSTANT: - target->is_signed = true; - target->value.i = - iter->u.unary_expression.u.signed_constant; - break; - case UNARY_UNSIGNED_CONSTANT: - target->is_signed = false; - target->value.u = - iter->u.unary_expression.u.unsigned_constant; - break; - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Invalid enumeration field class entry: " - "expecting constant signed or unsigned integer: " - "node-type=%d, label=\"%s\"", - iter->u.unary_expression.type, label); - ret = -EINVAL; - goto error; - } - - if (nr_vals > 1) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Invalid enumeration field class entry: label=\"%s\"", - label); - ret = -EINVAL; - goto error; - } - - nr_vals++; - } - - if (nr_vals == 0) { - start = *last; - } - - if (nr_vals <= 1) { - end = start; - } - - if (end.is_signed) { - last->value.i = end.value.i + 1; - } else { - last->value.u = end.value.u + 1; - } - - ctf_field_class_enum_map_range(enum_decl, label, - start.value.u, end.value.u); - return 0; + int ret = 0; + int nr_vals = 0; + struct ctf_node *iter; + struct uori start = { + .is_signed = false, + .value = + { + .u = 0, + }, + }; + struct uori end = { + .is_signed = false, + .value = + { + .u = 0, + }, + }; + const char *label = enumerator->u.enumerator.id; + struct bt_list_head *values = &enumerator->u.enumerator.values; + + bt_list_for_each_entry (iter, values, siblings) { + struct uori *target; + + if (iter->type != NODE_UNARY_EXPRESSION) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, + "Wrong expression for enumeration field class label: " + "node-type=%d, label=\"%s\"", + iter->type, label); + ret = -EINVAL; + goto error; + } + + if (nr_vals == 0) { + target = &start; + } else { + target = &end; + } + + switch (iter->u.unary_expression.type) { + case UNARY_SIGNED_CONSTANT: + target->is_signed = true; + target->value.i = iter->u.unary_expression.u.signed_constant; + break; + case UNARY_UNSIGNED_CONSTANT: + target->is_signed = false; + target->value.u = iter->u.unary_expression.u.unsigned_constant; + break; + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, + "Invalid enumeration field class entry: " + "expecting constant signed or unsigned integer: " + "node-type=%d, label=\"%s\"", + iter->u.unary_expression.type, label); + ret = -EINVAL; + goto error; + } + + if (nr_vals > 1) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + iter, "Invalid enumeration field class entry: label=\"%s\"", label); + ret = -EINVAL; + goto error; + } + + nr_vals++; + } + + if (nr_vals == 0) { + start = *last; + } + + if (nr_vals <= 1) { + end = start; + } + + if (end.is_signed) { + last->value.i = end.value.i + 1; + } else { + last->value.u = end.value.u + 1; + } + + ctf_field_class_enum_map_range(enum_decl, label, start.value.u, end.value.u); + return 0; error: - return ret; + return ret; } -static -int visit_enum_decl(struct ctf_visitor_generate_ir *ctx, const char *name, - struct ctf_node *container_cls, - struct bt_list_head *enumerator_list, - int has_body, struct ctf_field_class_enum **enum_decl) +static int visit_enum_decl(struct ctf_visitor_generate_ir *ctx, const char *name, + struct ctf_node *container_cls, struct bt_list_head *enumerator_list, + int has_body, struct ctf_field_class_enum **enum_decl) { - int ret = 0; - GQuark qdummy_id; - struct ctf_field_class_int *integer_decl = NULL; - - BT_ASSERT(enum_decl); - *enum_decl = NULL; - - /* For named enum (without body), lookup in declaration scope */ - if (!has_body) { - if (!name) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless enumeration field class: missing name."); - ret = -EPERM; - goto error; - } - - *enum_decl = ctx_decl_scope_lookup_enum(ctx, ctx->current_scope, - name, -1, true); - if (!*enum_decl) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: " - "name=\"enum %s\"", name); - ret = -EINVAL; - goto error; - } - } else { - struct ctf_node *iter; - struct uori last_value = { - .is_signed = false, - .value = { - .u = 0, - }, - }; - - if (name) { - if (ctx_decl_scope_lookup_enum(ctx, ctx->current_scope, - name, 1, false)) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Enumeration field class already declared in local scope: " - "name=\"enum %s\"", name); - ret = -EINVAL; - goto error; - } - } - - if (!container_cls) { - integer_decl = ctf_field_class_as_int(ctx_decl_scope_lookup_alias(ctx, - ctx->current_scope, "int", -1, true)); - if (!integer_decl) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find implicit `int` field class alias for enumeration field class."); - ret = -EINVAL; - goto error; - } - } else { - ctf_field_class *decl; - - ret = visit_field_class_declarator(ctx, container_cls, - &qdummy_id, NULL, &decl, NULL); - if (ret) { - BT_ASSERT(!decl); - ret = -EINVAL; - goto error; - } - - integer_decl = ctf_field_class_as_int(decl); - } - - BT_ASSERT(integer_decl); - - if (integer_decl->base.base.type != CTF_FIELD_CLASS_TYPE_INT) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Container field class for enumeration field class is not an integer field class: " - "fc-type=%d", integer_decl->base.base.type); - ret = -EINVAL; - goto error; - } - - *enum_decl = ctf_field_class_enum_create(); - BT_ASSERT(*enum_decl); - (*enum_decl)->base.base.base.alignment = - integer_decl->base.base.alignment; - ctf_field_class_int_copy_content( - &(*enum_decl)->base, integer_decl); - last_value.is_signed = (*enum_decl)->base.is_signed; - - bt_list_for_each_entry(iter, enumerator_list, siblings) { - ret = visit_enum_decl_entry(ctx, iter, *enum_decl, - &last_value); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot visit enumeration field class entry: " - "ret=%d", ret); - goto error; - } - } - - if (name) { - ret = ctx_decl_scope_register_enum(ctx, - ctx->current_scope, name, *enum_decl); - if (ret) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register enumeration field class in declaration scope: " - "ret=%d", ret); - goto error; - } - } - } - - goto end; + int ret = 0; + GQuark qdummy_id; + struct ctf_field_class_int *integer_decl = NULL; + + BT_ASSERT(enum_decl); + *enum_decl = NULL; + + /* For named enum (without body), lookup in declaration scope */ + if (!has_body) { + if (!name) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Bodyless enumeration field class: missing name."); + ret = -EPERM; + goto error; + } + + *enum_decl = ctx_decl_scope_lookup_enum(ctx, ctx->current_scope, name, -1, true); + if (!*enum_decl) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: " + "name=\"enum %s\"", + name); + ret = -EINVAL; + goto error; + } + } else { + struct ctf_node *iter; + struct uori last_value = { + .is_signed = false, + .value = + { + .u = 0, + }, + }; + + if (name) { + if (ctx_decl_scope_lookup_enum(ctx, ctx->current_scope, name, 1, false)) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Enumeration field class already declared in local scope: " + "name=\"enum %s\"", + name); + ret = -EINVAL; + goto error; + } + } + + if (!container_cls) { + integer_decl = ctf_field_class_as_int( + ctx_decl_scope_lookup_alias(ctx, ctx->current_scope, "int", -1, true)); + if (!integer_decl) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Cannot find implicit `int` field class alias for enumeration field class."); + ret = -EINVAL; + goto error; + } + } else { + ctf_field_class *decl; + + ret = visit_field_class_declarator(ctx, container_cls, &qdummy_id, NULL, &decl, NULL); + if (ret) { + BT_ASSERT(!decl); + ret = -EINVAL; + goto error; + } + + integer_decl = ctf_field_class_as_int(decl); + } + + BT_ASSERT(integer_decl); + + if (integer_decl->base.base.type != CTF_FIELD_CLASS_TYPE_INT) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Container field class for enumeration field class is not an integer field class: " + "fc-type=%d", + integer_decl->base.base.type); + ret = -EINVAL; + goto error; + } + + *enum_decl = ctf_field_class_enum_create(); + BT_ASSERT(*enum_decl); + (*enum_decl)->base.base.base.alignment = integer_decl->base.base.alignment; + ctf_field_class_int_copy_content(&(*enum_decl)->base, integer_decl); + last_value.is_signed = (*enum_decl)->base.is_signed; + + bt_list_for_each_entry (iter, enumerator_list, siblings) { + ret = visit_enum_decl_entry(ctx, iter, *enum_decl, &last_value); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, + "Cannot visit enumeration field class entry: " + "ret=%d", + ret); + goto error; + } + } + + if (name) { + ret = ctx_decl_scope_register_enum(ctx, ctx->current_scope, name, *enum_decl); + if (ret) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Cannot register enumeration field class in declaration scope: " + "ret=%d", + ret); + goto error; + } + } + } + + goto end; error: - ctf_field_class_destroy(&(*enum_decl)->base.base.base); - *enum_decl = NULL; + ctf_field_class_destroy(&(*enum_decl)->base.base.base); + *enum_decl = NULL; end: - ctf_field_class_destroy(&integer_decl->base.base); - integer_decl = NULL; - return ret; + ctf_field_class_destroy(&integer_decl->base.base); + integer_decl = NULL; + return ret; } -static -int visit_field_class_specifier(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *cls_specifier_list, - struct ctf_field_class **decl) +static int visit_field_class_specifier(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *cls_specifier_list, + struct ctf_field_class **decl) { - int ret = 0; - GString *str = NULL; - - *decl = NULL; - str = g_string_new(""); - ret = get_class_specifier_list_name(ctx, cls_specifier_list, str); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, - "Cannot get field class specifier list's name: ret=%d", ret); - goto error; - } - - *decl = ctx_decl_scope_lookup_alias(ctx, ctx->current_scope, str->str, - -1, true); - if (!*decl) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, - "Cannot find field class alias: name=\"%s\"", str->str); - ret = -EINVAL; - goto error; - } - - goto end; + int ret = 0; + GString *str = NULL; + + *decl = NULL; + str = g_string_new(""); + ret = get_class_specifier_list_name(ctx, cls_specifier_list, str); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + cls_specifier_list, "Cannot get field class specifier list's name: ret=%d", ret); + goto error; + } + + *decl = ctx_decl_scope_lookup_alias(ctx, ctx->current_scope, str->str, -1, true); + if (!*decl) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list, + "Cannot find field class alias: name=\"%s\"", str->str); + ret = -EINVAL; + goto error; + } + + goto end; error: - ctf_field_class_destroy(*decl); - *decl = NULL; + ctf_field_class_destroy(*decl); + *decl = NULL; end: - if (str) { - g_string_free(str, TRUE); - } + if (str) { + g_string_free(str, TRUE); + } - return ret; + return ret; } -static -int visit_integer_decl(struct ctf_visitor_generate_ir *ctx, - struct bt_list_head *expressions, - struct ctf_field_class_int **integer_decl) +static int visit_integer_decl(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *expressions, + struct ctf_field_class_int **integer_decl) { - int set = 0; - int ret = 0; - int signedness = 0; - struct ctf_node *expression; - uint64_t alignment = 0, size = 0; - struct ctf_clock_class *mapped_clock_class = NULL; - enum ctf_encoding encoding = CTF_ENCODING_NONE; - bt_field_class_integer_preferred_display_base base = - BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; - enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order; - - *integer_decl = NULL; - - bt_list_for_each_entry(expression, expressions, siblings) { - struct ctf_node *left, *right; - - left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, - struct ctf_node, siblings); - right = _BT_LIST_FIRST_ENTRY( - &expression->u.ctf_expression.right, struct ctf_node, - siblings); - - if (left->u.unary_expression.type != UNARY_STRING) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(left, - "Unexpected unary expression type: type=%d", - left->u.unary_expression.type); - ret = -EINVAL; - goto error; - } - - if (strcmp(left->u.unary_expression.u.string, "signed") == 0) { - if (_IS_SET(&set, _INTEGER_SIGNED_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "signed", - "integer field class"); - ret = -EPERM; - goto error; - } - - signedness = get_boolean(ctx, right); - if (signedness < 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid boolean value for integer field class's `signed` attribute: " - "ret=%d", ret); - ret = -EINVAL; - goto error; - } - - _SET(&set, _INTEGER_SIGNED_SET); - } else if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) { - if (_IS_SET(&set, _INTEGER_BYTE_ORDER_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order", - "integer field class"); - ret = -EPERM; - goto error; - } - - byte_order = get_real_byte_order(ctx, right); - if (byte_order == CTF_BYTE_ORDER_UNKNOWN) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `byte_order` attribute in integer field class: " - "ret=%d", ret); - ret = -EINVAL; - goto error; - } - - _SET(&set, _INTEGER_BYTE_ORDER_SET); - } else if (strcmp(left->u.unary_expression.u.string, "size") == 0) { - if (_IS_SET(&set, _INTEGER_SIZE_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "size", - "integer field class"); - ret = -EPERM; - goto error; - } - - if (right->u.unary_expression.type != - UNARY_UNSIGNED_CONSTANT) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `size` attribute in integer field class: " - "expecting unsigned constant integer: " - "node-type=%d", - right->u.unary_expression.type); - ret = -EINVAL; - goto error; - } - - size = right->u.unary_expression.u.unsigned_constant; - if (size == 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `size` attribute in integer field class: " - "expecting positive constant integer: " - "size=%" PRIu64, size); - ret = -EINVAL; - goto error; - } else if (size > 64) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `size` attribute in integer field class: " - "integer fields over 64 bits are not supported as of this version: " - "size=%" PRIu64, size); - ret = -EINVAL; - goto error; - } - - _SET(&set, _INTEGER_SIZE_SET); - } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) { - if (_IS_SET(&set, _INTEGER_ALIGN_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align", - "integer field class"); - ret = -EPERM; - goto error; - } - - if (right->u.unary_expression.type != - UNARY_UNSIGNED_CONSTANT) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `align` attribute in integer field class: " - "expecting unsigned constant integer: " - "node-type=%d", - right->u.unary_expression.type); - ret = -EINVAL; - goto error; - } - - alignment = - right->u.unary_expression.u.unsigned_constant; - if (!is_align_valid(alignment)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `align` attribute in integer field class: " - "expecting power of two: " - "align=%" PRIu64, alignment); - ret = -EINVAL; - goto error; - } - - _SET(&set, _INTEGER_ALIGN_SET); - } else if (strcmp(left->u.unary_expression.u.string, "base") == 0) { - if (_IS_SET(&set, _INTEGER_BASE_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "base", - "integer field class"); - ret = -EPERM; - goto error; - } - - switch (right->u.unary_expression.type) { - case UNARY_UNSIGNED_CONSTANT: - { - uint64_t constant = right->u.unary_expression. - u.unsigned_constant; - - switch (constant) { - case 2: - base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY; - break; - case 8: - base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL; - break; - case 10: - base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; - break; - case 16: - base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL; - break; - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `base` attribute in integer field class: " - "base=%" PRIu64, - right->u.unary_expression.u.unsigned_constant); - ret = -EINVAL; - goto error; - } - break; - } - case UNARY_STRING: - { - char *s_right = ctf_ast_concatenate_unary_strings( - &expression->u.ctf_expression.right); - if (!s_right) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Unexpected unary expression for integer field class's `base` attribute."); - ret = -EINVAL; - goto error; - } - - if (strcmp(s_right, "decimal") == 0 || - strcmp(s_right, "dec") == 0 || - strcmp(s_right, "d") == 0 || - strcmp(s_right, "i") == 0 || - strcmp(s_right, "u") == 0) { - base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; - } else if (strcmp(s_right, "hexadecimal") == 0 || - strcmp(s_right, "hex") == 0 || - strcmp(s_right, "x") == 0 || - strcmp(s_right, "X") == 0 || - strcmp(s_right, "p") == 0) { - base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL; - } else if (strcmp(s_right, "octal") == 0 || - strcmp(s_right, "oct") == 0 || - strcmp(s_right, "o") == 0) { - base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL; - } else if (strcmp(s_right, "binary") == 0 || - strcmp(s_right, "b") == 0) { - base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY; - } else { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Unexpected unary expression for integer field class's `base` attribute: " - "base=\"%s\"", s_right); - g_free(s_right); - ret = -EINVAL; - goto error; - } - - g_free(s_right); - break; - } - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `base` attribute in integer field class: " - "expecting unsigned constant integer or unary string."); - ret = -EINVAL; - goto error; - } - - _SET(&set, _INTEGER_BASE_SET); - } else if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) { - char *s_right; - - if (_IS_SET(&set, _INTEGER_ENCODING_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding", - "integer field class"); - ret = -EPERM; - goto error; - } - - if (right->u.unary_expression.type != UNARY_STRING) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `encoding` attribute in integer field class: " - "expecting unary string."); - ret = -EINVAL; - goto error; - } - - s_right = ctf_ast_concatenate_unary_strings( - &expression->u.ctf_expression.right); - if (!s_right) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Unexpected unary expression for integer field class's `encoding` attribute."); - ret = -EINVAL; - goto error; - } - - if (strcmp(s_right, "UTF8") == 0 || - strcmp(s_right, "utf8") == 0 || - strcmp(s_right, "utf-8") == 0 || - strcmp(s_right, "UTF-8") == 0 || - strcmp(s_right, "ASCII") == 0 || - strcmp(s_right, "ascii") == 0) { - encoding = CTF_ENCODING_UTF8; - } else if (strcmp(s_right, "none") == 0) { - encoding = CTF_ENCODING_NONE; - } else { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `encoding` attribute in integer field class: " - "unknown encoding: encoding=\"%s\"", - s_right); - g_free(s_right); - ret = -EINVAL; - goto error; - } - - g_free(s_right); - _SET(&set, _INTEGER_ENCODING_SET); - } else if (strcmp(left->u.unary_expression.u.string, "map") == 0) { - const char *clock_name; - - if (_IS_SET(&set, _INTEGER_MAP_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "map", - "integer field class"); - ret = -EPERM; - goto error; - } - - if (right->u.unary_expression.type != UNARY_STRING) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `map` attribute in integer field class: " - "expecting unary string."); - ret = -EINVAL; - goto error; - } - - clock_name = - get_map_clock_name_value( - &expression->u.ctf_expression.right); - if (!clock_name) { - char *s_right = ctf_ast_concatenate_unary_strings( - &expression->u.ctf_expression.right); - - if (!s_right) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Unexpected unary expression for integer field class's `map` attribute."); - ret = -EINVAL; - goto error; - } - - _BT_COMP_LOGE_NODE(right, - "Invalid `map` attribute in integer field class: " - "cannot find clock class at this point: name=\"%s\"", - s_right); - _SET(&set, _INTEGER_MAP_SET); - g_free(s_right); - continue; - } - - mapped_clock_class = - ctf_trace_class_borrow_clock_class_by_name( - ctx->ctf_tc, clock_name); - if (!mapped_clock_class) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `map` attribute in integer field class: " - "cannot find clock class at this point: name=\"%s\"", - clock_name); - ret = -EINVAL; - goto error; - } - - _SET(&set, _INTEGER_MAP_SET); - } else { - _BT_COMP_LOGW_NODE(left, - "Unknown attribute in integer field class: " - "attr-name=\"%s\"", - left->u.unary_expression.u.string); - } - } - - if (!_IS_SET(&set, _INTEGER_SIZE_SET)) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `size` attribute in integer field class."); - ret = -EPERM; - goto error; - } - - if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) { - if (size % CHAR_BIT) { - /* Bit-packed alignment */ - alignment = 1; - } else { - /* Byte-packed alignment */ - alignment = CHAR_BIT; - } - } - - *integer_decl = ctf_field_class_int_create(); - BT_ASSERT(*integer_decl); - (*integer_decl)->base.base.alignment = alignment; - (*integer_decl)->base.byte_order = byte_order; - (*integer_decl)->base.size = size; - (*integer_decl)->is_signed = (signedness > 0); - (*integer_decl)->disp_base = base; - (*integer_decl)->encoding = encoding; - (*integer_decl)->mapped_clock_class = mapped_clock_class; - return 0; + int set = 0; + int ret = 0; + int signedness = 0; + struct ctf_node *expression; + uint64_t alignment = 0, size = 0; + struct ctf_clock_class *mapped_clock_class = NULL; + enum ctf_encoding encoding = CTF_ENCODING_NONE; + bt_field_class_integer_preferred_display_base base = + BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; + enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order; + + *integer_decl = NULL; + + bt_list_for_each_entry (expression, expressions, siblings) { + struct ctf_node *left, *right; + + left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, struct ctf_node, siblings); + right = + _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.right, struct ctf_node, siblings); + + if (left->u.unary_expression.type != UNARY_STRING) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(left, "Unexpected unary expression type: type=%d", + left->u.unary_expression.type); + ret = -EINVAL; + goto error; + } + + if (strcmp(left->u.unary_expression.u.string, "signed") == 0) { + if (_IS_SET(&set, _INTEGER_SIGNED_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "signed", "integer field class"); + ret = -EPERM; + goto error; + } + + signedness = get_boolean(ctx, right); + if (signedness < 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid boolean value for integer field class's `signed` attribute: " + "ret=%d", + ret); + ret = -EINVAL; + goto error; + } + + _SET(&set, _INTEGER_SIGNED_SET); + } else if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) { + if (_IS_SET(&set, _INTEGER_BYTE_ORDER_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order", "integer field class"); + ret = -EPERM; + goto error; + } + + byte_order = get_real_byte_order(ctx, right); + if (byte_order == CTF_BYTE_ORDER_UNKNOWN) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `byte_order` attribute in integer field class: " + "ret=%d", + ret); + ret = -EINVAL; + goto error; + } + + _SET(&set, _INTEGER_BYTE_ORDER_SET); + } else if (strcmp(left->u.unary_expression.u.string, "size") == 0) { + if (_IS_SET(&set, _INTEGER_SIZE_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "size", "integer field class"); + ret = -EPERM; + goto error; + } + + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, + "Invalid `size` attribute in integer field class: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); + ret = -EINVAL; + goto error; + } + + size = right->u.unary_expression.u.unsigned_constant; + if (size == 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, + "Invalid `size` attribute in integer field class: " + "expecting positive constant integer: " + "size=%" PRIu64, + size); + ret = -EINVAL; + goto error; + } else if (size > 64) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `size` attribute in integer field class: " + "integer fields over 64 bits are not supported as of this version: " + "size=%" PRIu64, + size); + ret = -EINVAL; + goto error; + } + + _SET(&set, _INTEGER_SIZE_SET); + } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) { + if (_IS_SET(&set, _INTEGER_ALIGN_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align", "integer field class"); + ret = -EPERM; + goto error; + } + + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, + "Invalid `align` attribute in integer field class: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); + ret = -EINVAL; + goto error; + } + + alignment = right->u.unary_expression.u.unsigned_constant; + if (!is_align_valid(alignment)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, + "Invalid `align` attribute in integer field class: " + "expecting power of two: " + "align=%" PRIu64, + alignment); + ret = -EINVAL; + goto error; + } + + _SET(&set, _INTEGER_ALIGN_SET); + } else if (strcmp(left->u.unary_expression.u.string, "base") == 0) { + if (_IS_SET(&set, _INTEGER_BASE_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "base", "integer field class"); + ret = -EPERM; + goto error; + } + + switch (right->u.unary_expression.type) { + case UNARY_UNSIGNED_CONSTANT: + { + uint64_t constant = right->u.unary_expression.u.unsigned_constant; + + switch (constant) { + case 2: + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY; + break; + case 8: + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL; + break; + case 10: + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; + break; + case 16: + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL; + break; + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `base` attribute in integer field class: " + "base=%" PRIu64, + right->u.unary_expression.u.unsigned_constant); + ret = -EINVAL; + goto error; + } + break; + } + case UNARY_STRING: + { + char *s_right = + ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right); + if (!s_right) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Unexpected unary expression for integer field class's `base` attribute."); + ret = -EINVAL; + goto error; + } + + if (strcmp(s_right, "decimal") == 0 || strcmp(s_right, "dec") == 0 || + strcmp(s_right, "d") == 0 || strcmp(s_right, "i") == 0 || + strcmp(s_right, "u") == 0) { + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; + } else if (strcmp(s_right, "hexadecimal") == 0 || strcmp(s_right, "hex") == 0 || + strcmp(s_right, "x") == 0 || strcmp(s_right, "X") == 0 || + strcmp(s_right, "p") == 0) { + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL; + } else if (strcmp(s_right, "octal") == 0 || strcmp(s_right, "oct") == 0 || + strcmp(s_right, "o") == 0) { + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL; + } else if (strcmp(s_right, "binary") == 0 || strcmp(s_right, "b") == 0) { + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY; + } else { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Unexpected unary expression for integer field class's `base` attribute: " + "base=\"%s\"", + s_right); + g_free(s_right); + ret = -EINVAL; + goto error; + } + + g_free(s_right); + break; + } + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, "Invalid `base` attribute in integer field class: " + "expecting unsigned constant integer or unary string."); + ret = -EINVAL; + goto error; + } + + _SET(&set, _INTEGER_BASE_SET); + } else if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) { + char *s_right; + + if (_IS_SET(&set, _INTEGER_ENCODING_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding", "integer field class"); + ret = -EPERM; + goto error; + } + + if (right->u.unary_expression.type != UNARY_STRING) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, "Invalid `encoding` attribute in integer field class: " + "expecting unary string."); + ret = -EINVAL; + goto error; + } + + s_right = ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right); + if (!s_right) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Unexpected unary expression for integer field class's `encoding` attribute."); + ret = -EINVAL; + goto error; + } + + if (strcmp(s_right, "UTF8") == 0 || strcmp(s_right, "utf8") == 0 || + strcmp(s_right, "utf-8") == 0 || strcmp(s_right, "UTF-8") == 0 || + strcmp(s_right, "ASCII") == 0 || strcmp(s_right, "ascii") == 0) { + encoding = CTF_ENCODING_UTF8; + } else if (strcmp(s_right, "none") == 0) { + encoding = CTF_ENCODING_NONE; + } else { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `encoding` attribute in integer field class: " + "unknown encoding: encoding=\"%s\"", + s_right); + g_free(s_right); + ret = -EINVAL; + goto error; + } + + g_free(s_right); + _SET(&set, _INTEGER_ENCODING_SET); + } else if (strcmp(left->u.unary_expression.u.string, "map") == 0) { + const char *clock_name; + + if (_IS_SET(&set, _INTEGER_MAP_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "map", "integer field class"); + ret = -EPERM; + goto error; + } + + if (right->u.unary_expression.type != UNARY_STRING) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, + "Invalid `map` attribute in integer field class: " + "expecting unary string."); + ret = -EINVAL; + goto error; + } + + clock_name = get_map_clock_name_value(&expression->u.ctf_expression.right); + if (!clock_name) { + char *s_right = + ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right); + + if (!s_right) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Unexpected unary expression for integer field class's `map` attribute."); + ret = -EINVAL; + goto error; + } + + _BT_COMP_LOGE_NODE(right, + "Invalid `map` attribute in integer field class: " + "cannot find clock class at this point: name=\"%s\"", + s_right); + _SET(&set, _INTEGER_MAP_SET); + g_free(s_right); + continue; + } + + mapped_clock_class = + ctf_trace_class_borrow_clock_class_by_name(ctx->ctf_tc, clock_name); + if (!mapped_clock_class) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `map` attribute in integer field class: " + "cannot find clock class at this point: name=\"%s\"", + clock_name); + ret = -EINVAL; + goto error; + } + + _SET(&set, _INTEGER_MAP_SET); + } else { + _BT_COMP_LOGW_NODE(left, + "Unknown attribute in integer field class: " + "attr-name=\"%s\"", + left->u.unary_expression.u.string); + } + } + + if (!_IS_SET(&set, _INTEGER_SIZE_SET)) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Missing `size` attribute in integer field class."); + ret = -EPERM; + goto error; + } + + if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) { + if (size % CHAR_BIT) { + /* Bit-packed alignment */ + alignment = 1; + } else { + /* Byte-packed alignment */ + alignment = CHAR_BIT; + } + } + + *integer_decl = ctf_field_class_int_create(); + BT_ASSERT(*integer_decl); + (*integer_decl)->base.base.alignment = alignment; + (*integer_decl)->base.byte_order = byte_order; + (*integer_decl)->base.size = size; + (*integer_decl)->is_signed = (signedness > 0); + (*integer_decl)->disp_base = base; + (*integer_decl)->encoding = encoding; + (*integer_decl)->mapped_clock_class = mapped_clock_class; + return 0; error: - ctf_field_class_destroy(&(*integer_decl)->base.base); - *integer_decl = NULL; - return ret; + ctf_field_class_destroy(&(*integer_decl)->base.base); + *integer_decl = NULL; + return ret; } -static -int visit_floating_point_number_decl(struct ctf_visitor_generate_ir *ctx, - struct bt_list_head *expressions, - struct ctf_field_class_float **float_decl) +static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir *ctx, + struct bt_list_head *expressions, + struct ctf_field_class_float **float_decl) { - int set = 0; - int ret = 0; - struct ctf_node *expression; - uint64_t alignment = 1, exp_dig = 0, mant_dig = 0; - enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order; - - *float_decl = NULL; - - bt_list_for_each_entry(expression, expressions, siblings) { - struct ctf_node *left, *right; - - left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, - struct ctf_node, siblings); - right = _BT_LIST_FIRST_ENTRY( - &expression->u.ctf_expression.right, struct ctf_node, - siblings); - - if (left->u.unary_expression.type != UNARY_STRING) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(left, - "Unexpected unary expression type: type=%d", - left->u.unary_expression.type); - ret = -EINVAL; - goto error; - } - - if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) { - if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order", - "floating point number field class"); - ret = -EPERM; - goto error; - } - - byte_order = get_real_byte_order(ctx, right); - if (byte_order == CTF_BYTE_ORDER_UNKNOWN) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `byte_order` attribute in floating point number field class: " - "ret=%d", ret); - ret = -EINVAL; - goto error; - } - - _SET(&set, _FLOAT_BYTE_ORDER_SET); - } else if (strcmp(left->u.unary_expression.u.string, "exp_dig") == 0) { - if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "exp_dig", - "floating point number field class"); - ret = -EPERM; - goto error; - } - - if (right->u.unary_expression.type != - UNARY_UNSIGNED_CONSTANT) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `exp_dig` attribute in floating point number field class: " - "expecting unsigned constant integer: " - "node-type=%d", - right->u.unary_expression.type); - ret = -EINVAL; - goto error; - } - - exp_dig = right->u.unary_expression.u.unsigned_constant; - _SET(&set, _FLOAT_EXP_DIG_SET); - } else if (strcmp(left->u.unary_expression.u.string, "mant_dig") == 0) { - if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "mant_dig", - "floating point number field class"); - ret = -EPERM; - goto error; - } - - if (right->u.unary_expression.type != - UNARY_UNSIGNED_CONSTANT) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `mant_dig` attribute in floating point number field class: " - "expecting unsigned constant integer: " - "node-type=%d", - right->u.unary_expression.type); - ret = -EINVAL; - goto error; - } - - mant_dig = right->u.unary_expression.u. - unsigned_constant; - _SET(&set, _FLOAT_MANT_DIG_SET); - } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) { - if (_IS_SET(&set, _FLOAT_ALIGN_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align", - "floating point number field class"); - ret = -EPERM; - goto error; - } - - if (right->u.unary_expression.type != - UNARY_UNSIGNED_CONSTANT) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `align` attribute in floating point number field class: " - "expecting unsigned constant integer: " - "node-type=%d", - right->u.unary_expression.type); - ret = -EINVAL; - goto error; - } - - alignment = right->u.unary_expression.u. - unsigned_constant; - - if (!is_align_valid(alignment)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `align` attribute in floating point number field class: " - "expecting power of two: " - "align=%" PRIu64, alignment); - ret = -EINVAL; - goto error; - } - - _SET(&set, _FLOAT_ALIGN_SET); - } else { - _BT_COMP_LOGW_NODE(left, - "Unknown attribute in floating point number field class: " - "attr-name=\"%s\"", - left->u.unary_expression.u.string); - } - } - - if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `mant_dig` attribute in floating point number field class."); - ret = -EPERM; - goto error; - } - - if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `exp_dig` attribute in floating point number field class."); - ret = -EPERM; - goto error; - } - - if (mant_dig != 24 && mant_dig != 53) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53."); - ret = -EPERM; - goto error; - } - - if (mant_dig == 24 && exp_dig != 8) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`exp_dig` attribute: expecting 8 because `mant_dig` is 24."); - ret = -EPERM; - goto error; - } - - if (mant_dig == 53 && exp_dig != 11) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`exp_dig` attribute: expecting 11 because `mant_dig` is 53."); - ret = -EPERM; - goto error; - } - - if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) { - if ((mant_dig + exp_dig) % CHAR_BIT) { - /* Bit-packed alignment */ - alignment = 1; - } else { - /* Byte-packed alignment */ - alignment = CHAR_BIT; - } - } - - *float_decl = ctf_field_class_float_create(); - BT_ASSERT(*float_decl); - (*float_decl)->base.base.alignment = alignment; - (*float_decl)->base.byte_order = byte_order; - (*float_decl)->base.size = mant_dig + exp_dig; - return 0; + int set = 0; + int ret = 0; + struct ctf_node *expression; + uint64_t alignment = 1, exp_dig = 0, mant_dig = 0; + enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order; + + *float_decl = NULL; + + bt_list_for_each_entry (expression, expressions, siblings) { + struct ctf_node *left, *right; + + left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, struct ctf_node, siblings); + right = + _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.right, struct ctf_node, siblings); + + if (left->u.unary_expression.type != UNARY_STRING) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(left, "Unexpected unary expression type: type=%d", + left->u.unary_expression.type); + ret = -EINVAL; + goto error; + } + + if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) { + if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order", + "floating point number field class"); + ret = -EPERM; + goto error; + } + + byte_order = get_real_byte_order(ctx, right); + if (byte_order == CTF_BYTE_ORDER_UNKNOWN) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `byte_order` attribute in floating point number field class: " + "ret=%d", + ret); + ret = -EINVAL; + goto error; + } + + _SET(&set, _FLOAT_BYTE_ORDER_SET); + } else if (strcmp(left->u.unary_expression.u.string, "exp_dig") == 0) { + if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "exp_dig", + "floating point number field class"); + ret = -EPERM; + goto error; + } + + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `exp_dig` attribute in floating point number field class: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); + ret = -EINVAL; + goto error; + } + + exp_dig = right->u.unary_expression.u.unsigned_constant; + _SET(&set, _FLOAT_EXP_DIG_SET); + } else if (strcmp(left->u.unary_expression.u.string, "mant_dig") == 0) { + if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "mant_dig", + "floating point number field class"); + ret = -EPERM; + goto error; + } + + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `mant_dig` attribute in floating point number field class: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); + ret = -EINVAL; + goto error; + } + + mant_dig = right->u.unary_expression.u.unsigned_constant; + _SET(&set, _FLOAT_MANT_DIG_SET); + } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) { + if (_IS_SET(&set, _FLOAT_ALIGN_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align", + "floating point number field class"); + ret = -EPERM; + goto error; + } + + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `align` attribute in floating point number field class: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); + ret = -EINVAL; + goto error; + } + + alignment = right->u.unary_expression.u.unsigned_constant; + + if (!is_align_valid(alignment)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `align` attribute in floating point number field class: " + "expecting power of two: " + "align=%" PRIu64, + alignment); + ret = -EINVAL; + goto error; + } + + _SET(&set, _FLOAT_ALIGN_SET); + } else { + _BT_COMP_LOGW_NODE(left, + "Unknown attribute in floating point number field class: " + "attr-name=\"%s\"", + left->u.unary_expression.u.string); + } + } + + if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Missing `mant_dig` attribute in floating point number field class."); + ret = -EPERM; + goto error; + } + + if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Missing `exp_dig` attribute in floating point number field class."); + ret = -EPERM; + goto error; + } + + if (mant_dig != 24 && mant_dig != 53) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53."); + ret = -EPERM; + goto error; + } + + if (mant_dig == 24 && exp_dig != 8) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "`exp_dig` attribute: expecting 8 because `mant_dig` is 24."); + ret = -EPERM; + goto error; + } + + if (mant_dig == 53 && exp_dig != 11) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "`exp_dig` attribute: expecting 11 because `mant_dig` is 53."); + ret = -EPERM; + goto error; + } + + if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) { + if ((mant_dig + exp_dig) % CHAR_BIT) { + /* Bit-packed alignment */ + alignment = 1; + } else { + /* Byte-packed alignment */ + alignment = CHAR_BIT; + } + } + + *float_decl = ctf_field_class_float_create(); + BT_ASSERT(*float_decl); + (*float_decl)->base.base.alignment = alignment; + (*float_decl)->base.byte_order = byte_order; + (*float_decl)->base.size = mant_dig + exp_dig; + return 0; error: - ctf_field_class_destroy(&(*float_decl)->base.base); - *float_decl = NULL; - return ret; + ctf_field_class_destroy(&(*float_decl)->base.base); + *float_decl = NULL; + return ret; } -static -int visit_string_decl(struct ctf_visitor_generate_ir *ctx, - struct bt_list_head *expressions, - struct ctf_field_class_string **string_decl) +static int visit_string_decl(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *expressions, + struct ctf_field_class_string **string_decl) { - int set = 0; - int ret = 0; - struct ctf_node *expression; - enum ctf_encoding encoding = CTF_ENCODING_UTF8; - - *string_decl = NULL; - - bt_list_for_each_entry(expression, expressions, siblings) { - struct ctf_node *left, *right; - - left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, - struct ctf_node, siblings); - right = _BT_LIST_FIRST_ENTRY( - &expression->u.ctf_expression.right, struct ctf_node, - siblings); - - if (left->u.unary_expression.type != UNARY_STRING) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(left, - "Unexpected unary expression type: type=%d", - left->u.unary_expression.type); - ret = -EINVAL; - goto error; - } - - if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) { - char *s_right; - - if (_IS_SET(&set, _STRING_ENCODING_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding", - "string field class"); - ret = -EPERM; - goto error; - } - - if (right->u.unary_expression.type != UNARY_STRING) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `encoding` attribute in string field class: " - "expecting unary string."); - ret = -EINVAL; - goto error; - } - - s_right = ctf_ast_concatenate_unary_strings( - &expression->u.ctf_expression.right); - if (!s_right) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Unexpected unary expression for string field class's `encoding` attribute."); - ret = -EINVAL; - goto error; - } - - if (strcmp(s_right, "UTF8") == 0 || - strcmp(s_right, "utf8") == 0 || - strcmp(s_right, "utf-8") == 0 || - strcmp(s_right, "UTF-8") == 0 || - strcmp(s_right, "ASCII") == 0 || - strcmp(s_right, "ascii") == 0) { - encoding = CTF_ENCODING_UTF8; - } else if (strcmp(s_right, "none") == 0) { - encoding = CTF_ENCODING_NONE; - } else { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(right, - "Invalid `encoding` attribute in string field class: " - "unknown encoding: encoding=\"%s\"", - s_right); - g_free(s_right); - ret = -EINVAL; - goto error; - } - - g_free(s_right); - _SET(&set, _STRING_ENCODING_SET); - } else { - _BT_COMP_LOGW_NODE(left, - "Unknown attribute in string field class: " - "attr-name=\"%s\"", - left->u.unary_expression.u.string); - } - } - - *string_decl = ctf_field_class_string_create(); - BT_ASSERT(*string_decl); - (*string_decl)->encoding = encoding; - return 0; + int set = 0; + int ret = 0; + struct ctf_node *expression; + enum ctf_encoding encoding = CTF_ENCODING_UTF8; + + *string_decl = NULL; + + bt_list_for_each_entry (expression, expressions, siblings) { + struct ctf_node *left, *right; + + left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, struct ctf_node, siblings); + right = + _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.right, struct ctf_node, siblings); + + if (left->u.unary_expression.type != UNARY_STRING) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(left, "Unexpected unary expression type: type=%d", + left->u.unary_expression.type); + ret = -EINVAL; + goto error; + } + + if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) { + char *s_right; + + if (_IS_SET(&set, _STRING_ENCODING_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding", "string field class"); + ret = -EPERM; + goto error; + } + + if (right->u.unary_expression.type != UNARY_STRING) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, "Invalid `encoding` attribute in string field class: " + "expecting unary string."); + ret = -EINVAL; + goto error; + } + + s_right = ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right); + if (!s_right) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Unexpected unary expression for string field class's `encoding` attribute."); + ret = -EINVAL; + goto error; + } + + if (strcmp(s_right, "UTF8") == 0 || strcmp(s_right, "utf8") == 0 || + strcmp(s_right, "utf-8") == 0 || strcmp(s_right, "UTF-8") == 0 || + strcmp(s_right, "ASCII") == 0 || strcmp(s_right, "ascii") == 0) { + encoding = CTF_ENCODING_UTF8; + } else if (strcmp(s_right, "none") == 0) { + encoding = CTF_ENCODING_NONE; + } else { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + right, + "Invalid `encoding` attribute in string field class: " + "unknown encoding: encoding=\"%s\"", + s_right); + g_free(s_right); + ret = -EINVAL; + goto error; + } + + g_free(s_right); + _SET(&set, _STRING_ENCODING_SET); + } else { + _BT_COMP_LOGW_NODE(left, + "Unknown attribute in string field class: " + "attr-name=\"%s\"", + left->u.unary_expression.u.string); + } + } + + *string_decl = ctf_field_class_string_create(); + BT_ASSERT(*string_decl); + (*string_decl)->encoding = encoding; + return 0; error: - ctf_field_class_destroy(&(*string_decl)->base); - *string_decl = NULL; - return ret; + ctf_field_class_destroy(&(*string_decl)->base); + *string_decl = NULL; + return ret; } -static -int visit_field_class_specifier_list(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *ts_list, struct ctf_field_class **decl) +static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir *ctx, + struct ctf_node *ts_list, struct ctf_field_class **decl) { - int ret = 0; - struct ctf_node *first, *node; - - *decl = NULL; - - if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list, - "Unexpected node type: node-type=%d", ts_list->type); - ret = -EINVAL; - goto error; - } - - first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head, - struct ctf_node, siblings); - if (first->type != NODE_TYPE_SPECIFIER) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, - "Unexpected node type: node-type=%d", first->type); - ret = -EINVAL; - goto error; - } - - node = first->u.field_class_specifier.node; - - switch (first->u.field_class_specifier.type) { - case TYPESPEC_INTEGER: { - ctf_field_class_int *int_decl; - - ret = visit_integer_decl(ctx, &node->u.integer.expressions, - &int_decl); - if (ret) { - BT_ASSERT(!int_decl); - goto error; - } - - *decl = &int_decl->base.base; - break; - } - case TYPESPEC_FLOATING_POINT: { - ctf_field_class_float *float_decl; - - ret = visit_floating_point_number_decl(ctx, - &node->u.floating_point.expressions, &float_decl); - if (ret) { - BT_ASSERT(!float_decl); - goto error; - } - - *decl = &float_decl->base.base; - break; - } - case TYPESPEC_STRING: { - ctf_field_class_string *string_decl; - - ret = visit_string_decl(ctx, - &node->u.string.expressions, &string_decl); - if (ret) { - BT_ASSERT(!string_decl); - goto error; - } - - *decl = &string_decl->base; - break; - } - case TYPESPEC_STRUCT: { - ctf_field_class_struct *struct_decl; - - ret = visit_struct_decl(ctx, node->u._struct.name, - &node->u._struct.declaration_list, - node->u._struct.has_body, - &node->u._struct.min_align, &struct_decl); - if (ret) { - BT_ASSERT(!struct_decl); - goto error; - } - - *decl = &struct_decl->base; - break; - } - case TYPESPEC_VARIANT: { - ctf_field_class_variant *variant_decl; - - ret = visit_variant_decl(ctx, node->u.variant.name, - node->u.variant.choice, - &node->u.variant.declaration_list, - node->u.variant.has_body, &variant_decl); - if (ret) { - BT_ASSERT(!variant_decl); - goto error; - } - - *decl = &variant_decl->base; - break; - } - case TYPESPEC_ENUM: { - ctf_field_class_enum *enum_decl; - - ret = visit_enum_decl(ctx, node->u._enum.enum_id, - node->u._enum.container_field_class, - &node->u._enum.enumerator_list, - node->u._enum.has_body, &enum_decl); - if (ret) { - BT_ASSERT(!enum_decl); - goto error; - } - - *decl = &enum_decl->base.base.base; - break; - } - case TYPESPEC_VOID: - case TYPESPEC_CHAR: - case TYPESPEC_SHORT: - case TYPESPEC_INT: - case TYPESPEC_LONG: - case TYPESPEC_FLOAT: - case TYPESPEC_DOUBLE: - case TYPESPEC_SIGNED: - case TYPESPEC_UNSIGNED: - case TYPESPEC_BOOL: - case TYPESPEC_COMPLEX: - case TYPESPEC_IMAGINARY: - case TYPESPEC_CONST: - case TYPESPEC_ID_TYPE: - ret = visit_field_class_specifier(ctx, ts_list, decl); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, - "Cannot visit field class specifier: ret=%d", - ret); - BT_ASSERT(!*decl); - goto error; - } - break; - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, - "Unexpected field class specifier type: node-type=%d", - first->u.field_class_specifier.type); - ret = -EINVAL; - goto error; - } - - BT_ASSERT(*decl); - return 0; + int ret = 0; + struct ctf_node *first, *node; + + *decl = NULL; + + if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list, "Unexpected node type: node-type=%d", + ts_list->type); + ret = -EINVAL; + goto error; + } + + first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head, struct ctf_node, + siblings); + if (first->type != NODE_TYPE_SPECIFIER) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, "Unexpected node type: node-type=%d", first->type); + ret = -EINVAL; + goto error; + } + + node = first->u.field_class_specifier.node; + + switch (first->u.field_class_specifier.type) { + case TYPESPEC_INTEGER: + { + ctf_field_class_int *int_decl; + + ret = visit_integer_decl(ctx, &node->u.integer.expressions, &int_decl); + if (ret) { + BT_ASSERT(!int_decl); + goto error; + } + + *decl = &int_decl->base.base; + break; + } + case TYPESPEC_FLOATING_POINT: + { + ctf_field_class_float *float_decl; + + ret = + visit_floating_point_number_decl(ctx, &node->u.floating_point.expressions, &float_decl); + if (ret) { + BT_ASSERT(!float_decl); + goto error; + } + + *decl = &float_decl->base.base; + break; + } + case TYPESPEC_STRING: + { + ctf_field_class_string *string_decl; + + ret = visit_string_decl(ctx, &node->u.string.expressions, &string_decl); + if (ret) { + BT_ASSERT(!string_decl); + goto error; + } + + *decl = &string_decl->base; + break; + } + case TYPESPEC_STRUCT: + { + ctf_field_class_struct *struct_decl; + + ret = visit_struct_decl(ctx, node->u._struct.name, &node->u._struct.declaration_list, + node->u._struct.has_body, &node->u._struct.min_align, &struct_decl); + if (ret) { + BT_ASSERT(!struct_decl); + goto error; + } + + *decl = &struct_decl->base; + break; + } + case TYPESPEC_VARIANT: + { + ctf_field_class_variant *variant_decl; + + ret = visit_variant_decl(ctx, node->u.variant.name, node->u.variant.choice, + &node->u.variant.declaration_list, node->u.variant.has_body, + &variant_decl); + if (ret) { + BT_ASSERT(!variant_decl); + goto error; + } + + *decl = &variant_decl->base; + break; + } + case TYPESPEC_ENUM: + { + ctf_field_class_enum *enum_decl; + + ret = visit_enum_decl(ctx, node->u._enum.enum_id, node->u._enum.container_field_class, + &node->u._enum.enumerator_list, node->u._enum.has_body, &enum_decl); + if (ret) { + BT_ASSERT(!enum_decl); + goto error; + } + + *decl = &enum_decl->base.base.base; + break; + } + case TYPESPEC_VOID: + case TYPESPEC_CHAR: + case TYPESPEC_SHORT: + case TYPESPEC_INT: + case TYPESPEC_LONG: + case TYPESPEC_FLOAT: + case TYPESPEC_DOUBLE: + case TYPESPEC_SIGNED: + case TYPESPEC_UNSIGNED: + case TYPESPEC_BOOL: + case TYPESPEC_COMPLEX: + case TYPESPEC_IMAGINARY: + case TYPESPEC_CONST: + case TYPESPEC_ID_TYPE: + ret = visit_field_class_specifier(ctx, ts_list, decl); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, "Cannot visit field class specifier: ret=%d", + ret); + BT_ASSERT(!*decl); + goto error; + } + break; + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, + "Unexpected field class specifier type: node-type=%d", + first->u.field_class_specifier.type); + ret = -EINVAL; + goto error; + } + + BT_ASSERT(*decl); + return 0; error: - ctf_field_class_destroy(*decl); - *decl = NULL; - return ret; + ctf_field_class_destroy(*decl); + *decl = NULL; + return ret; } -static -int visit_event_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node, - struct ctf_event_class *event_class, uint64_t *stream_id, - int *set) +static int visit_event_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node, + struct ctf_event_class *event_class, uint64_t *stream_id, + int *set) { - int ret = 0; - char *left = NULL; - - switch (node->type) { - case NODE_TYPEDEF: - ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list, - &node->u.field_class_def.field_class_declarators); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot add field class found in event class."); - goto error; - } - break; - case NODE_TYPEALIAS: - ret = visit_field_class_alias(ctx, node->u.field_class_alias.target, - node->u.field_class_alias.alias); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot add field class alias found in event class."); - goto error; - } - break; - case NODE_CTF_EXPRESSION: - { - left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left); - if (!left) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings."); - ret = -EINVAL; - goto error; - } - - if (strcmp(left, "name") == 0) { - /* This is already known at this stage */ - if (_IS_SET(set, _EVENT_NAME_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "name", "event class"); - ret = -EPERM; - goto error; - } - - _SET(set, _EVENT_NAME_SET); - } else if (strcmp(left, "id") == 0) { - int64_t id = -1; - - if (_IS_SET(set, _EVENT_ID_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id", "event class"); - ret = -EPERM; - goto error; - } - - ret = get_unary_unsigned(ctx, - &node->u.ctf_expression.right, - (uint64_t *) &id); - /* Only read "id" if get_unary_unsigned() succeeded. */ - if (ret || (!ret && id < 0)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Unexpected unary expression for event class's `id` attribute."); - ret = -EINVAL; - goto error; - } - - event_class->id = id; - _SET(set, _EVENT_ID_SET); - } else if (strcmp(left, "stream_id") == 0) { - if (_IS_SET(set, _EVENT_STREAM_ID_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "stream_id", - "event class"); - ret = -EPERM; - goto error; - } - - ret = get_unary_unsigned(ctx, - &node->u.ctf_expression.right, stream_id); - - /* - * Only read "stream_id" if get_unary_unsigned() - * succeeded. - */ - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Unexpected unary expression for event class's `stream_id` attribute."); - ret = -EINVAL; - goto error; - } - - _SET(set, _EVENT_STREAM_ID_SET); - } else if (strcmp(left, "context") == 0) { - if (_IS_SET(set, _EVENT_CONTEXT_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate `context` entry in event class."); - ret = -EPERM; - goto error; - } - - ret = visit_field_class_specifier_list(ctx, - _BT_LIST_FIRST_ENTRY( - &node->u.ctf_expression.right, - struct ctf_node, siblings), - &event_class->spec_context_fc); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot create event class's context field class."); - goto error; - } - - BT_ASSERT(event_class->spec_context_fc); - _SET(set, _EVENT_CONTEXT_SET); - } else if (strcmp(left, "fields") == 0) { - if (_IS_SET(set, _EVENT_FIELDS_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate `fields` entry in event class."); - ret = -EPERM; - goto error; - } - - ret = visit_field_class_specifier_list(ctx, - _BT_LIST_FIRST_ENTRY( - &node->u.ctf_expression.right, - struct ctf_node, siblings), - &event_class->payload_fc); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot create event class's payload field class."); - goto error; - } - - BT_ASSERT(event_class->payload_fc); - _SET(set, _EVENT_FIELDS_SET); - } else if (strcmp(left, "loglevel") == 0) { - uint64_t loglevel_value; - bool is_log_level_known = true; - bt_event_class_log_level log_level; - - if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "loglevel", - "event class"); - ret = -EPERM; - goto error; - } - - ret = get_unary_unsigned(ctx, - &node->u.ctf_expression.right, &loglevel_value); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Unexpected unary expression for event class's `loglevel` attribute."); - ret = -EINVAL; - goto error; - } - - switch (loglevel_value) { - case 0: - log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY; - break; - case 1: - log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT; - break; - case 2: - log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL; - break; - case 3: - log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR; - break; - case 4: - log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING; - break; - case 5: - log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE; - break; - case 6: - log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO; - break; - case 7: - log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM; - break; - case 8: - log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM; - break; - case 9: - log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS; - break; - case 10: - log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE; - break; - case 11: - log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT; - break; - case 12: - log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION; - break; - case 13: - log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE; - break; - case 14: - log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG; - break; - default: - is_log_level_known = false; - _BT_COMP_LOGW_NODE(node, "Not setting event class's log level because its value is unknown: " - "log-level=%" PRIu64, loglevel_value); - } - - if (is_log_level_known) { - ctf_event_class_set_log_level(event_class, log_level); - } - - _SET(set, _EVENT_LOG_LEVEL_SET); - } else if (strcmp(left, "model.emf.uri") == 0) { - char *right; - - if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "model.emf.uri", - "event class"); - ret = -EPERM; - goto error; - } - - right = ctf_ast_concatenate_unary_strings( - &node->u.ctf_expression.right); - if (!right) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Unexpected unary expression for event class's `model.emf.uri` attribute."); - ret = -EINVAL; - goto error; - } - - if (strlen(right) == 0) { - _BT_COMP_LOGW_NODE(node, - "Not setting event class's EMF URI because it's empty."); - } else { - g_string_assign(event_class->emf_uri, - right); - } - - g_free(right); - _SET(set, _EVENT_MODEL_EMF_URI_SET); - } else { - _BT_COMP_LOGW_NODE(node, - "Unknown attribute in event class: " - "attr-name=\"%s\"", left); - } - - g_free(left); - left = NULL; - break; - } - default: - ret = -EPERM; - goto error; - } - - goto end; + int ret = 0; + char *left = NULL; + + switch (node->type) { + case NODE_TYPEDEF: + ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list, + &node->u.field_class_def.field_class_declarators); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot add field class found in event class."); + goto error; + } + break; + case NODE_TYPEALIAS: + ret = visit_field_class_alias(ctx, node->u.field_class_alias.target, + node->u.field_class_alias.alias); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Cannot add field class alias found in event class."); + goto error; + } + break; + case NODE_CTF_EXPRESSION: + { + left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left); + if (!left) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings."); + ret = -EINVAL; + goto error; + } + + if (strcmp(left, "name") == 0) { + /* This is already known at this stage */ + if (_IS_SET(set, _EVENT_NAME_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "name", "event class"); + ret = -EPERM; + goto error; + } + + _SET(set, _EVENT_NAME_SET); + } else if (strcmp(left, "id") == 0) { + int64_t id = -1; + + if (_IS_SET(set, _EVENT_ID_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id", "event class"); + ret = -EPERM; + goto error; + } + + ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, (uint64_t *) &id); + /* Only read "id" if get_unary_unsigned() succeeded. */ + if (ret || (!ret && id < 0)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Unexpected unary expression for event class's `id` attribute."); + ret = -EINVAL; + goto error; + } + + event_class->id = id; + _SET(set, _EVENT_ID_SET); + } else if (strcmp(left, "stream_id") == 0) { + if (_IS_SET(set, _EVENT_STREAM_ID_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "stream_id", "event class"); + ret = -EPERM; + goto error; + } + + ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, stream_id); + + /* + * Only read "stream_id" if get_unary_unsigned() + * succeeded. + */ + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Unexpected unary expression for event class's `stream_id` attribute."); + ret = -EINVAL; + goto error; + } + + _SET(set, _EVENT_STREAM_ID_SET); + } else if (strcmp(left, "context") == 0) { + if (_IS_SET(set, _EVENT_CONTEXT_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate `context` entry in event class."); + ret = -EPERM; + goto error; + } + + ret = visit_field_class_specifier_list( + ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings), + &event_class->spec_context_fc); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Cannot create event class's context field class."); + goto error; + } + + BT_ASSERT(event_class->spec_context_fc); + _SET(set, _EVENT_CONTEXT_SET); + } else if (strcmp(left, "fields") == 0) { + if (_IS_SET(set, _EVENT_FIELDS_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate `fields` entry in event class."); + ret = -EPERM; + goto error; + } + + ret = visit_field_class_specifier_list( + ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings), + &event_class->payload_fc); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Cannot create event class's payload field class."); + goto error; + } + + BT_ASSERT(event_class->payload_fc); + _SET(set, _EVENT_FIELDS_SET); + } else if (strcmp(left, "loglevel") == 0) { + uint64_t loglevel_value; + bool is_log_level_known = true; + bt_event_class_log_level log_level; + + if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "loglevel", "event class"); + ret = -EPERM; + goto error; + } + + ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, &loglevel_value); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Unexpected unary expression for event class's `loglevel` attribute."); + ret = -EINVAL; + goto error; + } + + switch (loglevel_value) { + case 0: + log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY; + break; + case 1: + log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT; + break; + case 2: + log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL; + break; + case 3: + log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR; + break; + case 4: + log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING; + break; + case 5: + log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE; + break; + case 6: + log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO; + break; + case 7: + log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM; + break; + case 8: + log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM; + break; + case 9: + log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS; + break; + case 10: + log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE; + break; + case 11: + log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT; + break; + case 12: + log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION; + break; + case 13: + log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE; + break; + case 14: + log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG; + break; + default: + is_log_level_known = false; + _BT_COMP_LOGW_NODE( + node, + "Not setting event class's log level because its value is unknown: " + "log-level=%" PRIu64, + loglevel_value); + } + + if (is_log_level_known) { + ctf_event_class_set_log_level(event_class, log_level); + } + + _SET(set, _EVENT_LOG_LEVEL_SET); + } else if (strcmp(left, "model.emf.uri") == 0) { + char *right; + + if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "model.emf.uri", "event class"); + ret = -EPERM; + goto error; + } + + right = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.right); + if (!right) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, + "Unexpected unary expression for event class's `model.emf.uri` attribute."); + ret = -EINVAL; + goto error; + } + + if (strlen(right) == 0) { + _BT_COMP_LOGW_NODE(node, "Not setting event class's EMF URI because it's empty."); + } else { + g_string_assign(event_class->emf_uri, right); + } + + g_free(right); + _SET(set, _EVENT_MODEL_EMF_URI_SET); + } else { + _BT_COMP_LOGW_NODE(node, + "Unknown attribute in event class: " + "attr-name=\"%s\"", + left); + } + + g_free(left); + left = NULL; + break; + } + default: + ret = -EPERM; + goto error; + } + + goto end; error: - g_free(left); + g_free(left); end: - return ret; + return ret; } -static -char *get_event_decl_name(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) +static char *get_event_decl_name(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) { - char *left = NULL; - char *name = NULL; - struct ctf_node *iter; - struct bt_list_head *decl_list = &node->u.event.declaration_list; - - bt_list_for_each_entry(iter, decl_list, siblings) { - if (iter->type != NODE_CTF_EXPRESSION) { - continue; - } - - left = ctf_ast_concatenate_unary_strings(&iter->u.ctf_expression.left); - if (!left) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot concatenate unary strings."); - goto error; - } - - if (strcmp(left, "name") == 0) { - name = ctf_ast_concatenate_unary_strings( - &iter->u.ctf_expression.right); - if (!name) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Unexpected unary expression for event class's `name` attribute."); - goto error; - } - } - - g_free(left); - left = NULL; - - if (name) { - break; - } - } - - return name; + char *left = NULL; + char *name = NULL; + struct ctf_node *iter; + struct bt_list_head *decl_list = &node->u.event.declaration_list; + + bt_list_for_each_entry (iter, decl_list, siblings) { + if (iter->type != NODE_CTF_EXPRESSION) { + continue; + } + + left = ctf_ast_concatenate_unary_strings(&iter->u.ctf_expression.left); + if (!left) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot concatenate unary strings."); + goto error; + } + + if (strcmp(left, "name") == 0) { + name = ctf_ast_concatenate_unary_strings(&iter->u.ctf_expression.right); + if (!name) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + iter, "Unexpected unary expression for event class's `name` attribute."); + goto error; + } + } + + g_free(left); + left = NULL; + + if (name) { + break; + } + } + + return name; error: - g_free(left); - return NULL; + g_free(left); + return NULL; } -static -int visit_event_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) +static int visit_event_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) { - int ret = 0; - int set = 0; - struct ctf_node *iter; - uint64_t stream_id = 0; - char *event_name = NULL; - struct ctf_event_class *event_class = NULL; - struct ctf_stream_class *stream_class = NULL; - struct bt_list_head *decl_list = &node->u.event.declaration_list; - bool pop_scope = false; - - if (node->visited) { - goto end; - } - - node->visited = TRUE; - event_name = get_event_decl_name(ctx, node); - if (!event_name) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Missing `name` attribute in event class."); - ret = -EPERM; - goto error; - } - - event_class = ctf_event_class_create(); - BT_ASSERT(event_class); - g_string_assign(event_class->name, event_name); - _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); - pop_scope = true; - - bt_list_for_each_entry(iter, decl_list, siblings) { - ret = visit_event_decl_entry(ctx, iter, event_class, - &stream_id, &set); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit event class's entry: " - "ret=%d", ret); - goto error; - } - } - - if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) { - /* - * Allow missing stream_id if there is only a single - * stream class. - */ - switch (ctx->ctf_tc->stream_classes->len) { - case 0: - /* Create implicit stream class if there's none */ - stream_id = 0; - stream_class = ctf_stream_class_create(); - BT_ASSERT(stream_class); - stream_class->id = stream_id; - g_ptr_array_add(ctx->ctf_tc->stream_classes, - stream_class); - break; - case 1: - /* Single stream class: get its ID */ - stream_class = (ctf_stream_class *) ctx->ctf_tc->stream_classes->pdata[0]; - stream_id = stream_class->id; - break; - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Missing `stream_id` attribute in event class."); - ret = -EPERM; - goto error; - } - } - - /* We have the stream ID now; get the stream class if found */ - if (!stream_class) { - stream_class = ctf_trace_class_borrow_stream_class_by_id( - ctx->ctf_tc, stream_id); - if (!stream_class) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot find stream class at this point: " - "id=%" PRId64, stream_id); - ret = -EINVAL; - goto error; - } - } - - BT_ASSERT(stream_class); - - if (!_IS_SET(&set, _EVENT_ID_SET)) { - /* Allow only one event without ID per stream */ - if (stream_class->event_classes->len != 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Missing `id` attribute in event class."); - ret = -EPERM; - goto error; - } - - /* Automatic ID */ - event_class->id = 0; - } - - if (ctf_stream_class_borrow_event_class_by_id(stream_class, - event_class->id)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate event class (same ID) in the same stream class: " - "id=%" PRId64, event_class->id); - ret = -EEXIST; - goto error; - } - - ctf_stream_class_append_event_class(stream_class, event_class); - event_class = NULL; - goto end; + int ret = 0; + int set = 0; + struct ctf_node *iter; + uint64_t stream_id = 0; + char *event_name = NULL; + struct ctf_event_class *event_class = NULL; + struct ctf_stream_class *stream_class = NULL; + struct bt_list_head *decl_list = &node->u.event.declaration_list; + bool pop_scope = false; + + if (node->visited) { + goto end; + } + + node->visited = TRUE; + event_name = get_event_decl_name(ctx, node); + if (!event_name) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Missing `name` attribute in event class."); + ret = -EPERM; + goto error; + } + + event_class = ctf_event_class_create(); + BT_ASSERT(event_class); + g_string_assign(event_class->name, event_name); + _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); + pop_scope = true; + + bt_list_for_each_entry (iter, decl_list, siblings) { + ret = visit_event_decl_entry(ctx, iter, event_class, &stream_id, &set); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, + "Cannot visit event class's entry: " + "ret=%d", + ret); + goto error; + } + } + + if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) { + /* + * Allow missing stream_id if there is only a single + * stream class. + */ + switch (ctx->ctf_tc->stream_classes->len) { + case 0: + /* Create implicit stream class if there's none */ + stream_id = 0; + stream_class = ctf_stream_class_create(); + BT_ASSERT(stream_class); + stream_class->id = stream_id; + g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class); + break; + case 1: + /* Single stream class: get its ID */ + stream_class = (ctf_stream_class *) ctx->ctf_tc->stream_classes->pdata[0]; + stream_id = stream_class->id; + break; + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Missing `stream_id` attribute in event class."); + ret = -EPERM; + goto error; + } + } + + /* We have the stream ID now; get the stream class if found */ + if (!stream_class) { + stream_class = ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, stream_id); + if (!stream_class) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Cannot find stream class at this point: " + "id=%" PRId64, + stream_id); + ret = -EINVAL; + goto error; + } + } + + BT_ASSERT(stream_class); + + if (!_IS_SET(&set, _EVENT_ID_SET)) { + /* Allow only one event without ID per stream */ + if (stream_class->event_classes->len != 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Missing `id` attribute in event class."); + ret = -EPERM; + goto error; + } + + /* Automatic ID */ + event_class->id = 0; + } + + if (ctf_stream_class_borrow_event_class_by_id(stream_class, event_class->id)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Duplicate event class (same ID) in the same stream class: " + "id=%" PRId64, + event_class->id); + ret = -EEXIST; + goto error; + } + + ctf_stream_class_append_event_class(stream_class, event_class); + event_class = NULL; + goto end; error: - ctf_event_class_destroy(event_class); - event_class = NULL; + ctf_event_class_destroy(event_class); + event_class = NULL; - if (ret >= 0) { - ret = -1; - } + if (ret >= 0) { + ret = -1; + } end: - if (pop_scope) { - ctx_pop_scope(ctx); - } + if (pop_scope) { + ctx_pop_scope(ctx); + } - g_free(event_name); + g_free(event_name); - return ret; + return ret; } -static -int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx, - struct ctf_field_class *fc) +static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx, + struct ctf_field_class *fc) { - struct ctf_clock_class *clock_class_to_map_to = NULL; - struct ctf_field_class_int *int_fc = ctf_field_class_as_int(fc); - int ret = 0; - uint64_t clock_class_count; - - if (!fc) { - goto end; - } - - if (fc->type != CTF_FIELD_CLASS_TYPE_INT && - fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { - goto end; - } - - if (int_fc->mapped_clock_class) { - /* Already mapped */ - goto end; - } - - clock_class_count = ctx->ctf_tc->clock_classes->len; - - switch (clock_class_count) { - case 0: - /* - * No clock class exists in the trace at this point. Create an - * implicit one at 1 GHz, named `default`, and use this clock - * class. - */ - clock_class_to_map_to = ctf_clock_class_create(); - BT_ASSERT(clock_class_to_map_to); - clock_class_to_map_to->frequency = UINT64_C(1000000000); - g_string_assign(clock_class_to_map_to->name, "default"); - BT_ASSERT(ret == 0); - g_ptr_array_add(ctx->ctf_tc->clock_classes, - clock_class_to_map_to); - break; - case 1: - /* - * Only one clock class exists in the trace at this point: use - * this one. - */ - clock_class_to_map_to = (ctf_clock_class *) ctx->ctf_tc->clock_classes->pdata[0]; - break; - default: - /* - * Timestamp field not mapped to a clock class and there's more - * than one clock class in the trace: this is an error. - */ - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Timestamp field found with no mapped clock class, " - "but there's more than one clock class in the trace at this point."); - ret = -1; - goto end; - } - - BT_ASSERT(clock_class_to_map_to); - int_fc->mapped_clock_class = clock_class_to_map_to; + struct ctf_clock_class *clock_class_to_map_to = NULL; + struct ctf_field_class_int *int_fc = ctf_field_class_as_int(fc); + int ret = 0; + uint64_t clock_class_count; + + if (!fc) { + goto end; + } + + if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { + goto end; + } + + if (int_fc->mapped_clock_class) { + /* Already mapped */ + goto end; + } + + clock_class_count = ctx->ctf_tc->clock_classes->len; + + switch (clock_class_count) { + case 0: + /* + * No clock class exists in the trace at this point. Create an + * implicit one at 1 GHz, named `default`, and use this clock + * class. + */ + clock_class_to_map_to = ctf_clock_class_create(); + BT_ASSERT(clock_class_to_map_to); + clock_class_to_map_to->frequency = UINT64_C(1000000000); + g_string_assign(clock_class_to_map_to->name, "default"); + BT_ASSERT(ret == 0); + g_ptr_array_add(ctx->ctf_tc->clock_classes, clock_class_to_map_to); + break; + case 1: + /* + * Only one clock class exists in the trace at this point: use + * this one. + */ + clock_class_to_map_to = (ctf_clock_class *) ctx->ctf_tc->clock_classes->pdata[0]; + break; + default: + /* + * Timestamp field not mapped to a clock class and there's more + * than one clock class in the trace: this is an error. + */ + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Timestamp field found with no mapped clock class, " + "but there's more than one clock class in the trace at this point."); + ret = -1; + goto end; + } + + BT_ASSERT(clock_class_to_map_to); + int_fc->mapped_clock_class = clock_class_to_map_to; end: - return ret; + return ret; } -static -int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx, - struct ctf_field_class *root_fc, const char *field_name) +static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx, + struct ctf_field_class *root_fc, + const char *field_name) { - int ret = 0; - uint64_t i, count; - struct ctf_field_class_struct *struct_fc = (ctf_field_class_struct *) root_fc; - struct ctf_field_class_variant *var_fc = (ctf_field_class_variant *) root_fc; - - if (!root_fc) { - goto end; - } - - if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT && - root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) { - goto end; - } - - if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) { - count = struct_fc->members->len; - } else { - count = var_fc->options->len; - } - - for (i = 0; i < count; i++) { - struct ctf_named_field_class *named_fc = NULL; - - if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) { - named_fc = ctf_field_class_struct_borrow_member_by_index( - struct_fc, i); - } else if (root_fc->type == CTF_FIELD_CLASS_TYPE_VARIANT) { - named_fc = ctf_field_class_variant_borrow_option_by_index( - var_fc, i); - } else { - bt_common_abort(); - } - - if (strcmp(named_fc->name->str, field_name) == 0) { - ret = auto_map_field_to_trace_clock_class(ctx, - named_fc->fc); - if (ret) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot automatically map field to trace's clock class: " - "field-name=\"%s\"", field_name); - goto end; - } - } - - ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc, - field_name); - if (ret) { - _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot automatically map structure or variant field class's fields to trace's clock class: " - "field-name=\"%s\", root-field-name=\"%s\"", - field_name, named_fc->name->str); - goto end; - } - } + int ret = 0; + uint64_t i, count; + struct ctf_field_class_struct *struct_fc = (ctf_field_class_struct *) root_fc; + struct ctf_field_class_variant *var_fc = (ctf_field_class_variant *) root_fc; + + if (!root_fc) { + goto end; + } + + if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT && + root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) { + goto end; + } + + if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) { + count = struct_fc->members->len; + } else { + count = var_fc->options->len; + } + + for (i = 0; i < count; i++) { + struct ctf_named_field_class *named_fc = NULL; + + if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) { + named_fc = ctf_field_class_struct_borrow_member_by_index(struct_fc, i); + } else if (root_fc->type == CTF_FIELD_CLASS_TYPE_VARIANT) { + named_fc = ctf_field_class_variant_borrow_option_by_index(var_fc, i); + } else { + bt_common_abort(); + } + + if (strcmp(named_fc->name->str, field_name) == 0) { + ret = auto_map_field_to_trace_clock_class(ctx, named_fc->fc); + if (ret) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Cannot automatically map field to trace's clock class: " + "field-name=\"%s\"", + field_name); + goto end; + } + } + + ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc, field_name); + if (ret) { + _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE( + "Cannot automatically map structure or variant field class's fields to trace's clock class: " + "field-name=\"%s\", root-field-name=\"%s\"", + field_name, named_fc->name->str); + goto end; + } + } end: - return ret; + return ret; } -static -int visit_stream_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node, - struct ctf_stream_class *stream_class, int *set) +static int visit_stream_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node, + struct ctf_stream_class *stream_class, int *set) { - int ret = 0; - char *left = NULL; - - switch (node->type) { - case NODE_TYPEDEF: - ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list, - &node->u.field_class_def.field_class_declarators); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot add field class found in stream class."); - goto error; - } - break; - case NODE_TYPEALIAS: - ret = visit_field_class_alias(ctx, node->u.field_class_alias.target, - node->u.field_class_alias.alias); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot add field class alias found in stream class."); - goto error; - } - break; - case NODE_CTF_EXPRESSION: - { - left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left); - if (!left) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings."); - ret = -EINVAL; - goto error; - } - - if (strcmp(left, "id") == 0) { - int64_t id; - - if (_IS_SET(set, _STREAM_ID_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id", - "stream declaration"); - ret = -EPERM; - goto error; - } - - ret = get_unary_unsigned(ctx, - &node->u.ctf_expression.right, - (uint64_t *) &id); - - /* Only read "id" if get_unary_unsigned() succeeded. */ - if (ret || (!ret && id < 0)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Unexpected unary expression for stream class's `id` attribute."); - ret = -EINVAL; - goto error; - } - - if (ctf_trace_class_borrow_stream_class_by_id( - ctx->ctf_tc, id)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate stream class (same ID): id=%" PRId64, - id); - ret = -EEXIST; - goto error; - } - - stream_class->id = id; - _SET(set, _STREAM_ID_SET); - } else if (strcmp(left, "event.header") == 0) { - if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate `event.header` entry in stream class."); - ret = -EPERM; - goto error; - } - - ret = visit_field_class_specifier_list(ctx, - _BT_LIST_FIRST_ENTRY( - &node->u.ctf_expression.right, - struct ctf_node, siblings), - &stream_class->event_header_fc); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot create stream class's event header field class."); - goto error; - } - - BT_ASSERT(stream_class->event_header_fc); - ret = auto_map_fields_to_trace_clock_class(ctx, - stream_class->event_header_fc, "timestamp"); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class."); - goto error; - } - - _SET(set, _STREAM_EVENT_HEADER_SET); - } else if (strcmp(left, "event.context") == 0) { - if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate `event.context` entry in stream class."); - ret = -EPERM; - goto error; - } - - ret = visit_field_class_specifier_list(ctx, - _BT_LIST_FIRST_ENTRY( - &node->u.ctf_expression.right, - struct ctf_node, siblings), - &stream_class->event_common_context_fc); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot create stream class's event context field class."); - goto error; - } - - BT_ASSERT(stream_class->event_common_context_fc); - _SET(set, _STREAM_EVENT_CONTEXT_SET); - } else if (strcmp(left, "packet.context") == 0) { - if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate `packet.context` entry in stream class."); - ret = -EPERM; - goto error; - } - - ret = visit_field_class_specifier_list(ctx, - _BT_LIST_FIRST_ENTRY( - &node->u.ctf_expression.right, - struct ctf_node, siblings), - &stream_class->packet_context_fc); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot create stream class's packet context field class."); - goto error; - } - - BT_ASSERT(stream_class->packet_context_fc); - ret = auto_map_fields_to_trace_clock_class(ctx, - stream_class->packet_context_fc, - "timestamp_begin"); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class."); - goto error; - } - - ret = auto_map_fields_to_trace_clock_class(ctx, - stream_class->packet_context_fc, - "timestamp_end"); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class."); - goto error; - } - - _SET(set, _STREAM_PACKET_CONTEXT_SET); - } else { - _BT_COMP_LOGW_NODE(node, - "Unknown attribute in stream class: " - "attr-name=\"%s\"", left); - } - - g_free(left); - left = NULL; - break; - } - - default: - ret = -EPERM; - goto error; - } - - return 0; + int ret = 0; + char *left = NULL; + + switch (node->type) { + case NODE_TYPEDEF: + ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list, + &node->u.field_class_def.field_class_declarators); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot add field class found in stream class."); + goto error; + } + break; + case NODE_TYPEALIAS: + ret = visit_field_class_alias(ctx, node->u.field_class_alias.target, + node->u.field_class_alias.alias); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Cannot add field class alias found in stream class."); + goto error; + } + break; + case NODE_CTF_EXPRESSION: + { + left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left); + if (!left) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings."); + ret = -EINVAL; + goto error; + } + + if (strcmp(left, "id") == 0) { + int64_t id; + + if (_IS_SET(set, _STREAM_ID_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id", "stream declaration"); + ret = -EPERM; + goto error; + } + + ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, (uint64_t *) &id); + + /* Only read "id" if get_unary_unsigned() succeeded. */ + if (ret || (!ret && id < 0)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Unexpected unary expression for stream class's `id` attribute."); + ret = -EINVAL; + goto error; + } + + if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, id)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Duplicate stream class (same ID): id=%" PRId64, id); + ret = -EEXIST; + goto error; + } + + stream_class->id = id; + _SET(set, _STREAM_ID_SET); + } else if (strcmp(left, "event.header") == 0) { + if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Duplicate `event.header` entry in stream class."); + ret = -EPERM; + goto error; + } + + ret = visit_field_class_specifier_list( + ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings), + &stream_class->event_header_fc); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Cannot create stream class's event header field class."); + goto error; + } + + BT_ASSERT(stream_class->event_header_fc); + ret = auto_map_fields_to_trace_clock_class(ctx, stream_class->event_header_fc, + "timestamp"); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, + "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class."); + goto error; + } + + _SET(set, _STREAM_EVENT_HEADER_SET); + } else if (strcmp(left, "event.context") == 0) { + if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Duplicate `event.context` entry in stream class."); + ret = -EPERM; + goto error; + } + + ret = visit_field_class_specifier_list( + ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings), + &stream_class->event_common_context_fc); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Cannot create stream class's event context field class."); + goto error; + } + + BT_ASSERT(stream_class->event_common_context_fc); + _SET(set, _STREAM_EVENT_CONTEXT_SET); + } else if (strcmp(left, "packet.context") == 0) { + if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Duplicate `packet.context` entry in stream class."); + ret = -EPERM; + goto error; + } + + ret = visit_field_class_specifier_list( + ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings), + &stream_class->packet_context_fc); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Cannot create stream class's packet context field class."); + goto error; + } + + BT_ASSERT(stream_class->packet_context_fc); + ret = auto_map_fields_to_trace_clock_class(ctx, stream_class->packet_context_fc, + "timestamp_begin"); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, + "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class."); + goto error; + } + + ret = auto_map_fields_to_trace_clock_class(ctx, stream_class->packet_context_fc, + "timestamp_end"); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, + "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class."); + goto error; + } + + _SET(set, _STREAM_PACKET_CONTEXT_SET); + } else { + _BT_COMP_LOGW_NODE(node, + "Unknown attribute in stream class: " + "attr-name=\"%s\"", + left); + } + + g_free(left); + left = NULL; + break; + } + + default: + ret = -EPERM; + goto error; + } + + return 0; error: - g_free(left); - return ret; + g_free(left); + return ret; } -static -int visit_stream_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) +static int visit_stream_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) { - int set = 0; - int ret = 0; - struct ctf_node *iter; - struct ctf_stream_class *stream_class = NULL; - struct bt_list_head *decl_list = &node->u.stream.declaration_list; - - if (node->visited) { - goto end; - } - - node->visited = TRUE; - stream_class = ctf_stream_class_create(); - BT_ASSERT(stream_class); - _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); - - bt_list_for_each_entry(iter, decl_list, siblings) { - ret = visit_stream_decl_entry(ctx, iter, stream_class, &set); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot visit stream class's entry: " - "ret=%d", ret); - ctx_pop_scope(ctx); - goto error; - } - } - - ctx_pop_scope(ctx); - - if (_IS_SET(&set, _STREAM_ID_SET)) { - /* Check that packet header has `stream_id` field */ - struct ctf_named_field_class *named_fc = NULL; - - if (!ctx->ctf_tc->packet_header_fc) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Stream class has a `id` attribute, " - "but trace has no packet header field class."); - ret = -EINVAL; - goto error; - } - - named_fc = ctf_field_class_struct_borrow_member_by_name( - ctf_field_class_as_struct(ctx->ctf_tc->packet_header_fc), "stream_id"); - if (!named_fc) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Stream class has a `id` attribute, " - "but trace's packet header field class has no `stream_id` field."); - ret = -EINVAL; - goto error; - } - - if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT && - named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Stream class has a `id` attribute, " - "but trace's packet header field class's `stream_id` field is not an integer field class."); - ret = -EINVAL; - goto error; - } - } else { - /* Allow only _one_ ID-less stream */ - if (ctx->ctf_tc->stream_classes->len != 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Missing `id` attribute in stream class as there's more than one stream class in the trace."); - ret = -EPERM; - goto error; - } - - /* Automatic ID: 0 */ - stream_class->id = 0; - } - - /* - * Make sure that this stream class's ID is currently unique in - * the trace. - */ - if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, - stream_class->id)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate stream class (same ID): id=%" PRId64, - stream_class->id); - ret = -EINVAL; - goto error; - } - - g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class); - stream_class = NULL; - goto end; + int set = 0; + int ret = 0; + struct ctf_node *iter; + struct ctf_stream_class *stream_class = NULL; + struct bt_list_head *decl_list = &node->u.stream.declaration_list; + + if (node->visited) { + goto end; + } + + node->visited = TRUE; + stream_class = ctf_stream_class_create(); + BT_ASSERT(stream_class); + _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); + + bt_list_for_each_entry (iter, decl_list, siblings) { + ret = visit_stream_decl_entry(ctx, iter, stream_class, &set); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, + "Cannot visit stream class's entry: " + "ret=%d", + ret); + ctx_pop_scope(ctx); + goto error; + } + } + + ctx_pop_scope(ctx); + + if (_IS_SET(&set, _STREAM_ID_SET)) { + /* Check that packet header has `stream_id` field */ + struct ctf_named_field_class *named_fc = NULL; + + if (!ctx->ctf_tc->packet_header_fc) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Stream class has a `id` attribute, " + "but trace has no packet header field class."); + ret = -EINVAL; + goto error; + } + + named_fc = ctf_field_class_struct_borrow_member_by_name( + ctf_field_class_as_struct(ctx->ctf_tc->packet_header_fc), "stream_id"); + if (!named_fc) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Stream class has a `id` attribute, " + "but trace's packet header field class has no `stream_id` field."); + ret = -EINVAL; + goto error; + } + + if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT && + named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, + "Stream class has a `id` attribute, " + "but trace's packet header field class's `stream_id` field is not an integer field class."); + ret = -EINVAL; + goto error; + } + } else { + /* Allow only _one_ ID-less stream */ + if (ctx->ctf_tc->stream_classes->len != 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, + "Missing `id` attribute in stream class as there's more than one stream class in the trace."); + ret = -EPERM; + goto error; + } + + /* Automatic ID: 0 */ + stream_class->id = 0; + } + + /* + * Make sure that this stream class's ID is currently unique in + * the trace. + */ + if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, stream_class->id)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate stream class (same ID): id=%" PRId64, + stream_class->id); + ret = -EINVAL; + goto error; + } + + g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class); + stream_class = NULL; + goto end; error: - ctf_stream_class_destroy(stream_class); - stream_class = NULL; + ctf_stream_class_destroy(stream_class); + stream_class = NULL; end: - return ret; + return ret; } -static -int visit_trace_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node, - int *set) +static int visit_trace_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node, + int *set) { - int ret = 0; - char *left = NULL; - uint64_t val; - - switch (node->type) { - case NODE_TYPEDEF: - ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list, - &node->u.field_class_def.field_class_declarators); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot add field class found in trace (`trace` block)."); - goto error; - } - break; - case NODE_TYPEALIAS: - ret = visit_field_class_alias(ctx, node->u.field_class_alias.target, - node->u.field_class_alias.alias); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot add field class alias found in trace (`trace` block)."); - goto error; - } - break; - case NODE_CTF_EXPRESSION: - { - left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left); - if (!left) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings."); - ret = -EINVAL; - goto error; - } - - if (strcmp(left, "major") == 0) { - if (_IS_SET(set, _TRACE_MAJOR_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "major", "trace"); - ret = -EPERM; - goto error; - } - - ret = get_unary_unsigned(ctx, - &node->u.ctf_expression.right, &val); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Unexpected unary expression for trace's `major` attribute."); - ret = -EINVAL; - goto error; - } - - if (val != 1) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Invalid trace's `minor` attribute: expecting 1."); - ret = -EINVAL; - goto error; - } - - ctx->ctf_tc->major = val; - _SET(set, _TRACE_MAJOR_SET); - } else if (strcmp(left, "minor") == 0) { - if (_IS_SET(set, _TRACE_MINOR_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "minor", "trace"); - ret = -EPERM; - goto error; - } - - ret = get_unary_unsigned(ctx, - &node->u.ctf_expression.right, &val); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Unexpected unary expression for trace's `minor` attribute."); - ret = -EINVAL; - goto error; - } - - if (val != 8) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Invalid trace's `minor` attribute: expecting 8."); - ret = -EINVAL; - goto error; - } - - ctx->ctf_tc->minor = val; - _SET(set, _TRACE_MINOR_SET); - } else if (strcmp(left, "uuid") == 0) { - if (_IS_SET(set, _TRACE_UUID_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "uuid", "trace"); - ret = -EPERM; - goto error; - } - - ret = get_unary_uuid(ctx, - &node->u.ctf_expression.right, - ctx->ctf_tc->uuid); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Invalid trace's `uuid` attribute."); - goto error; - } - - ctx->ctf_tc->is_uuid_set = true; - _SET(set, _TRACE_UUID_SET); - } else if (strcmp(left, "byte_order") == 0) { - /* Default byte order is already known at this stage */ - if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order", - "trace"); - ret = -EPERM; - goto error; - } - - BT_ASSERT(ctx->ctf_tc->default_byte_order != CTF_BYTE_ORDER_UNKNOWN); - _SET(set, _TRACE_BYTE_ORDER_SET); - } else if (strcmp(left, "packet.header") == 0) { - if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate `packet.header` entry in trace."); - ret = -EPERM; - goto error; - } - - ret = visit_field_class_specifier_list(ctx, - _BT_LIST_FIRST_ENTRY( - &node->u.ctf_expression.right, - struct ctf_node, siblings), - &ctx->ctf_tc->packet_header_fc); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot create trace's packet header field class."); - goto error; - } - - BT_ASSERT(ctx->ctf_tc->packet_header_fc); - _SET(set, _TRACE_PACKET_HEADER_SET); - } else { - _BT_COMP_LOGW_NODE(node, - "Unknown attribute in stream class: " - "attr-name=\"%s\"", left); - } - - g_free(left); - left = NULL; - break; - } - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unknown expression in trace."); - ret = -EINVAL; - goto error; - } - - return 0; + int ret = 0; + char *left = NULL; + uint64_t val; + + switch (node->type) { + case NODE_TYPEDEF: + ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list, + &node->u.field_class_def.field_class_declarators); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Cannot add field class found in trace (`trace` block)."); + goto error; + } + break; + case NODE_TYPEALIAS: + ret = visit_field_class_alias(ctx, node->u.field_class_alias.target, + node->u.field_class_alias.alias); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Cannot add field class alias found in trace (`trace` block)."); + goto error; + } + break; + case NODE_CTF_EXPRESSION: + { + left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left); + if (!left) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings."); + ret = -EINVAL; + goto error; + } + + if (strcmp(left, "major") == 0) { + if (_IS_SET(set, _TRACE_MAJOR_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "major", "trace"); + ret = -EPERM; + goto error; + } + + ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, &val); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Unexpected unary expression for trace's `major` attribute."); + ret = -EINVAL; + goto error; + } + + if (val != 1) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Invalid trace's `minor` attribute: expecting 1."); + ret = -EINVAL; + goto error; + } + + ctx->ctf_tc->major = val; + _SET(set, _TRACE_MAJOR_SET); + } else if (strcmp(left, "minor") == 0) { + if (_IS_SET(set, _TRACE_MINOR_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "minor", "trace"); + ret = -EPERM; + goto error; + } + + ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, &val); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Unexpected unary expression for trace's `minor` attribute."); + ret = -EINVAL; + goto error; + } + + if (val != 8) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Invalid trace's `minor` attribute: expecting 8."); + ret = -EINVAL; + goto error; + } + + ctx->ctf_tc->minor = val; + _SET(set, _TRACE_MINOR_SET); + } else if (strcmp(left, "uuid") == 0) { + if (_IS_SET(set, _TRACE_UUID_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "uuid", "trace"); + ret = -EPERM; + goto error; + } + + ret = get_unary_uuid(ctx, &node->u.ctf_expression.right, ctx->ctf_tc->uuid); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Invalid trace's `uuid` attribute."); + goto error; + } + + ctx->ctf_tc->is_uuid_set = true; + _SET(set, _TRACE_UUID_SET); + } else if (strcmp(left, "byte_order") == 0) { + /* Default byte order is already known at this stage */ + if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order", "trace"); + ret = -EPERM; + goto error; + } + + BT_ASSERT(ctx->ctf_tc->default_byte_order != CTF_BYTE_ORDER_UNKNOWN); + _SET(set, _TRACE_BYTE_ORDER_SET); + } else if (strcmp(left, "packet.header") == 0) { + if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate `packet.header` entry in trace."); + ret = -EPERM; + goto error; + } + + ret = visit_field_class_specifier_list( + ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings), + &ctx->ctf_tc->packet_header_fc); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Cannot create trace's packet header field class."); + goto error; + } + + BT_ASSERT(ctx->ctf_tc->packet_header_fc); + _SET(set, _TRACE_PACKET_HEADER_SET); + } else { + _BT_COMP_LOGW_NODE(node, + "Unknown attribute in stream class: " + "attr-name=\"%s\"", + left); + } + + g_free(left); + left = NULL; + break; + } + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unknown expression in trace."); + ret = -EINVAL; + goto error; + } + + return 0; error: - g_free(left); - return ret; + g_free(left); + return ret; } -static -int visit_trace_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) +static int visit_trace_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) { - int ret = 0; - int set = 0; - struct ctf_node *iter; - struct bt_list_head *decl_list = &node->u.trace.declaration_list; - - if (node->visited) { - goto end; - } - - node->visited = TRUE; - - if (ctx->is_trace_visited) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate trace (`trace` block)."); - ret = -EEXIST; - goto error; - } - - _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); - - bt_list_for_each_entry(iter, decl_list, siblings) { - ret = visit_trace_decl_entry(ctx, iter, &set); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit trace's entry (`trace` block): " - "ret=%d", ret); - ctx_pop_scope(ctx); - goto error; - } - } - - ctx_pop_scope(ctx); - - if (!_IS_SET(&set, _TRACE_MAJOR_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Missing `major` attribute in trace (`trace` block)."); - ret = -EPERM; - goto error; - } - - if (!_IS_SET(&set, _TRACE_MINOR_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Missing `minor` attribute in trace (`trace` block)."); - ret = -EPERM; - goto error; - } - - if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Missing `byte_order` attribute in trace (`trace` block)."); - ret = -EPERM; - goto error; - } - - ctx->is_trace_visited = true; + int ret = 0; + int set = 0; + struct ctf_node *iter; + struct bt_list_head *decl_list = &node->u.trace.declaration_list; + + if (node->visited) { + goto end; + } + + node->visited = TRUE; + + if (ctx->is_trace_visited) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate trace (`trace` block)."); + ret = -EEXIST; + goto error; + } + + _TRY_PUSH_SCOPE_OR_GOTO_ERROR(); + + bt_list_for_each_entry (iter, decl_list, siblings) { + ret = visit_trace_decl_entry(ctx, iter, &set); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, + "Cannot visit trace's entry (`trace` block): " + "ret=%d", + ret); + ctx_pop_scope(ctx); + goto error; + } + } + + ctx_pop_scope(ctx); + + if (!_IS_SET(&set, _TRACE_MAJOR_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Missing `major` attribute in trace (`trace` block)."); + ret = -EPERM; + goto error; + } + + if (!_IS_SET(&set, _TRACE_MINOR_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Missing `minor` attribute in trace (`trace` block)."); + ret = -EPERM; + goto error; + } + + if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Missing `byte_order` attribute in trace (`trace` block)."); + ret = -EPERM; + goto error; + } + + ctx->is_trace_visited = true; end: - return 0; + return 0; error: - return ret; + return ret; } -static -int visit_env(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) +static int visit_env(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) { - int ret = 0; - char *left = NULL; - struct ctf_node *entry_node; - struct bt_list_head *decl_list = &node->u.env.declaration_list; - - if (node->visited) { - goto end; - } - - node->visited = TRUE; - - bt_list_for_each_entry(entry_node, decl_list, siblings) { - struct bt_list_head *right_head = - &entry_node->u.ctf_expression.right; - - if (entry_node->type != NODE_CTF_EXPRESSION) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Wrong expression in environment entry: " - "node-type=%d", entry_node->type); - ret = -EPERM; - goto error; - } - - left = ctf_ast_concatenate_unary_strings( - &entry_node->u.ctf_expression.left); - if (!left) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Cannot get environment entry's name."); - ret = -EINVAL; - goto error; - } - - if (is_unary_string(right_head)) { - char *right = ctf_ast_concatenate_unary_strings(right_head); - - if (!right) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected unary expression for environment entry's value: " - "name=\"%s\"", left); - ret = -EINVAL; - goto error; - } - - if (strcmp(left, "tracer_name") == 0) { - if (strncmp(right, "lttng", 5) == 0) { - BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: " - "tracer-name=\"%s\"", - left, right); - ctx->is_lttng = true; - } - } - - ctf_trace_class_append_env_entry(ctx->ctf_tc, - left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR, - right, 0); - g_free(right); - } else if (is_unary_unsigned(right_head) || - is_unary_signed(right_head)) { - int64_t v; - - if (is_unary_unsigned(right_head)) { - ret = get_unary_unsigned(ctx, right_head, - (uint64_t *) &v); - } else { - ret = get_unary_signed(right_head, &v); - } - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected unary expression for environment entry's value: " - "name=\"%s\"", left); - ret = -EINVAL; - goto error; - } - - ctf_trace_class_append_env_entry(ctx->ctf_tc, - left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT, - NULL, v); - } else { - _BT_COMP_LOGW_NODE(entry_node, - "Environment entry has unknown type: " - "name=\"%s\"", left); - } - - g_free(left); - left = NULL; - } + int ret = 0; + char *left = NULL; + struct ctf_node *entry_node; + struct bt_list_head *decl_list = &node->u.env.declaration_list; + + if (node->visited) { + goto end; + } + + node->visited = TRUE; + + bt_list_for_each_entry (entry_node, decl_list, siblings) { + struct bt_list_head *right_head = &entry_node->u.ctf_expression.right; + + if (entry_node->type != NODE_CTF_EXPRESSION) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, + "Wrong expression in environment entry: " + "node-type=%d", + entry_node->type); + ret = -EPERM; + goto error; + } + + left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left); + if (!left) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Cannot get environment entry's name."); + ret = -EINVAL; + goto error; + } + + if (is_unary_string(right_head)) { + char *right = ctf_ast_concatenate_unary_strings(right_head); + + if (!right) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, + "Unexpected unary expression for environment entry's value: " + "name=\"%s\"", + left); + ret = -EINVAL; + goto error; + } + + if (strcmp(left, "tracer_name") == 0) { + if (strncmp(right, "lttng", 5) == 0) { + BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: " + "tracer-name=\"%s\"", + left, right); + ctx->is_lttng = true; + } + } + + ctf_trace_class_append_env_entry(ctx->ctf_tc, left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR, + right, 0); + g_free(right); + } else if (is_unary_unsigned(right_head) || is_unary_signed(right_head)) { + int64_t v; + + if (is_unary_unsigned(right_head)) { + ret = get_unary_unsigned(ctx, right_head, (uint64_t *) &v); + } else { + ret = get_unary_signed(right_head, &v); + } + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, + "Unexpected unary expression for environment entry's value: " + "name=\"%s\"", + left); + ret = -EINVAL; + goto error; + } + + ctf_trace_class_append_env_entry(ctx->ctf_tc, left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT, + NULL, v); + } else { + _BT_COMP_LOGW_NODE(entry_node, + "Environment entry has unknown type: " + "name=\"%s\"", + left); + } + + g_free(left); + left = NULL; + } end: - return 0; + return 0; error: - g_free(left); - return ret; + g_free(left); + return ret; } -static -int set_trace_byte_order(struct ctf_visitor_generate_ir *ctx, struct ctf_node *trace_node) +static int set_trace_byte_order(struct ctf_visitor_generate_ir *ctx, struct ctf_node *trace_node) { - int ret = 0; - int set = 0; - char *left = NULL; - struct ctf_node *node; - struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list; - - bt_list_for_each_entry(node, decl_list, siblings) { - if (node->type == NODE_CTF_EXPRESSION) { - struct ctf_node *right_node; - - left = ctf_ast_concatenate_unary_strings( - &node->u.ctf_expression.left); - if (!left) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot concatenate unary strings."); - ret = -EINVAL; - goto error; - } - - if (strcmp(left, "byte_order") == 0) { - enum ctf_byte_order bo; - - if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order", - "trace"); - ret = -EPERM; - goto error; - } - - _SET(&set, _TRACE_BYTE_ORDER_SET); - right_node = _BT_LIST_FIRST_ENTRY( - &node->u.ctf_expression.right, - struct ctf_node, siblings); - bo = byte_order_from_unary_expr(ctx, - right_node); - if (bo == CTF_BYTE_ORDER_UNKNOWN) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Invalid `byte_order` attribute in trace (`trace` block): " - "expecting `le`, `be`, or `network`."); - ret = -EINVAL; - goto error; - } else if (bo == CTF_BYTE_ORDER_DEFAULT) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Invalid `byte_order` attribute in trace (`trace` block): " - "cannot be set to `native` here."); - ret = -EPERM; - goto error; - } - - ctx->ctf_tc->default_byte_order = bo; - } - - g_free(left); - left = NULL; - } - } - - if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node, - "Missing `byte_order` attribute in trace (`trace` block)."); - ret = -EINVAL; - goto error; - } - - return 0; + int ret = 0; + int set = 0; + char *left = NULL; + struct ctf_node *node; + struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list; + + bt_list_for_each_entry (node, decl_list, siblings) { + if (node->type == NODE_CTF_EXPRESSION) { + struct ctf_node *right_node; + + left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left); + if (!left) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings."); + ret = -EINVAL; + goto error; + } + + if (strcmp(left, "byte_order") == 0) { + enum ctf_byte_order bo; + + if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order", "trace"); + ret = -EPERM; + goto error; + } + + _SET(&set, _TRACE_BYTE_ORDER_SET); + right_node = + _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings); + bo = byte_order_from_unary_expr(ctx, right_node); + if (bo == CTF_BYTE_ORDER_UNKNOWN) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Invalid `byte_order` attribute in trace (`trace` block): " + "expecting `le`, `be`, or `network`."); + ret = -EINVAL; + goto error; + } else if (bo == CTF_BYTE_ORDER_DEFAULT) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + node, "Invalid `byte_order` attribute in trace (`trace` block): " + "cannot be set to `native` here."); + ret = -EPERM; + goto error; + } + + ctx->ctf_tc->default_byte_order = bo; + } + + g_free(left); + left = NULL; + } + } + + if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node, + "Missing `byte_order` attribute in trace (`trace` block)."); + ret = -EINVAL; + goto error; + } + + return 0; error: - g_free(left); - return ret; + g_free(left); + return ret; } -static -int visit_clock_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node, - struct ctf_clock_class *clock, int *set, int64_t *offset_seconds, - uint64_t *offset_cycles) +static int visit_clock_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node, + struct ctf_clock_class *clock, int *set, int64_t *offset_seconds, + uint64_t *offset_cycles) { - int ret = 0; - char *left = NULL; - - if (entry_node->type != NODE_CTF_EXPRESSION) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected node type: node-type=%d", - entry_node->type); - ret = -EPERM; - goto error; - } - - left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left); - if (!left) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Cannot concatenate unary strings."); - ret = -EINVAL; - goto error; - } - - if (strcmp(left, "name") == 0) { - char *right; - - if (_IS_SET(set, _CLOCK_NAME_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "name", "clock class"); - ret = -EPERM; - goto error; - } - - right = ctf_ast_concatenate_unary_strings( - &entry_node->u.ctf_expression.right); - if (!right) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected unary expression for clock class's `name` attribute."); - ret = -EINVAL; - goto error; - } - - g_string_assign(clock->name, right); - g_free(right); - _SET(set, _CLOCK_NAME_SET); - } else if (strcmp(left, "uuid") == 0) { - bt_uuid_t uuid; - - if (_IS_SET(set, _CLOCK_UUID_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "uuid", "clock class"); - ret = -EPERM; - goto error; - } - - ret = get_unary_uuid(ctx, &entry_node->u.ctf_expression.right, - uuid); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Invalid clock class's `uuid` attribute."); - goto error; - } - - clock->has_uuid = true; - bt_uuid_copy(clock->uuid, uuid); - _SET(set, _CLOCK_UUID_SET); - } else if (strcmp(left, "description") == 0) { - char *right; - - if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "description", - "clock class"); - ret = -EPERM; - goto error; - } - - right = ctf_ast_concatenate_unary_strings( - &entry_node->u.ctf_expression.right); - if (!right) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected unary expression for clock class's `description` attribute."); - ret = -EINVAL; - goto error; - } - - g_string_assign(clock->description, right); - g_free(right); - _SET(set, _CLOCK_DESCRIPTION_SET); - } else if (strcmp(left, "freq") == 0) { - uint64_t freq = UINT64_C(-1); - - if (_IS_SET(set, _CLOCK_FREQ_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "freq", "clock class"); - ret = -EPERM; - goto error; - } - - ret = get_unary_unsigned(ctx, - &entry_node->u.ctf_expression.right, &freq); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected unary expression for clock class's `freq` attribute."); - ret = -EINVAL; - goto error; - } - - if (freq == UINT64_C(-1) || freq == 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Invalid clock class frequency: freq=%" PRIu64, - freq); - ret = -EINVAL; - goto error; - } - - clock->frequency = freq; - _SET(set, _CLOCK_FREQ_SET); - } else if (strcmp(left, "precision") == 0) { - uint64_t precision; - - if (_IS_SET(set, _CLOCK_PRECISION_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "precision", - "clock class"); - ret = -EPERM; - goto error; - } - - ret = get_unary_unsigned(ctx, - &entry_node->u.ctf_expression.right, &precision); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected unary expression for clock class's `precision` attribute."); - ret = -EINVAL; - goto error; - } - - clock->precision = precision; - _SET(set, _CLOCK_PRECISION_SET); - } else if (strcmp(left, "offset_s") == 0) { - if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset_s", - "clock class"); - ret = -EPERM; - goto error; - } - - ret = get_unary_signed( - &entry_node->u.ctf_expression.right, offset_seconds); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected unary expression for clock class's `offset_s` attribute."); - ret = -EINVAL; - goto error; - } - - _SET(set, _CLOCK_OFFSET_S_SET); - } else if (strcmp(left, "offset") == 0) { - if (_IS_SET(set, _CLOCK_OFFSET_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset", "clock class"); - ret = -EPERM; - goto error; - } - - ret = get_unary_unsigned(ctx, - &entry_node->u.ctf_expression.right, offset_cycles); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected unary expression for clock class's `offset` attribute."); - ret = -EINVAL; - goto error; - } - - _SET(set, _CLOCK_OFFSET_SET); - } else if (strcmp(left, "absolute") == 0) { - struct ctf_node *right; - - if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "absolute", - "clock class"); - ret = -EPERM; - goto error; - } - - right = _BT_LIST_FIRST_ENTRY( - &entry_node->u.ctf_expression.right, - struct ctf_node, siblings); - ret = get_boolean(ctx, right); - if (ret < 0) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Unexpected unary expression for clock class's `absolute` attribute."); - ret = -EINVAL; - goto error; - } - - clock->is_absolute = ret; - _SET(set, _CLOCK_ABSOLUTE_SET); - } else { - _BT_COMP_LOGW_NODE(entry_node, - "Unknown attribute in clock class: attr-name=\"%s\"", - left); - } - - g_free(left); - left = NULL; - return 0; + int ret = 0; + char *left = NULL; + + if (entry_node->type != NODE_CTF_EXPRESSION) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Unexpected node type: node-type=%d", + entry_node->type); + ret = -EPERM; + goto error; + } + + left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left); + if (!left) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Cannot concatenate unary strings."); + ret = -EINVAL; + goto error; + } + + if (strcmp(left, "name") == 0) { + char *right; + + if (_IS_SET(set, _CLOCK_NAME_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "name", "clock class"); + ret = -EPERM; + goto error; + } + + right = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.right); + if (!right) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Unexpected unary expression for clock class's `name` attribute."); + ret = -EINVAL; + goto error; + } + + g_string_assign(clock->name, right); + g_free(right); + _SET(set, _CLOCK_NAME_SET); + } else if (strcmp(left, "uuid") == 0) { + bt_uuid_t uuid; + + if (_IS_SET(set, _CLOCK_UUID_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "uuid", "clock class"); + ret = -EPERM; + goto error; + } + + ret = get_unary_uuid(ctx, &entry_node->u.ctf_expression.right, uuid); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Invalid clock class's `uuid` attribute."); + goto error; + } + + clock->has_uuid = true; + bt_uuid_copy(clock->uuid, uuid); + _SET(set, _CLOCK_UUID_SET); + } else if (strcmp(left, "description") == 0) { + char *right; + + if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "description", "clock class"); + ret = -EPERM; + goto error; + } + + right = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.right); + if (!right) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, + "Unexpected unary expression for clock class's `description` attribute."); + ret = -EINVAL; + goto error; + } + + g_string_assign(clock->description, right); + g_free(right); + _SET(set, _CLOCK_DESCRIPTION_SET); + } else if (strcmp(left, "freq") == 0) { + uint64_t freq = UINT64_C(-1); + + if (_IS_SET(set, _CLOCK_FREQ_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "freq", "clock class"); + ret = -EPERM; + goto error; + } + + ret = get_unary_unsigned(ctx, &entry_node->u.ctf_expression.right, &freq); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Unexpected unary expression for clock class's `freq` attribute."); + ret = -EINVAL; + goto error; + } + + if (freq == UINT64_C(-1) || freq == 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, + "Invalid clock class frequency: freq=%" PRIu64, freq); + ret = -EINVAL; + goto error; + } + + clock->frequency = freq; + _SET(set, _CLOCK_FREQ_SET); + } else if (strcmp(left, "precision") == 0) { + uint64_t precision; + + if (_IS_SET(set, _CLOCK_PRECISION_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "precision", "clock class"); + ret = -EPERM; + goto error; + } + + ret = get_unary_unsigned(ctx, &entry_node->u.ctf_expression.right, &precision); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Unexpected unary expression for clock class's `precision` attribute."); + ret = -EINVAL; + goto error; + } + + clock->precision = precision; + _SET(set, _CLOCK_PRECISION_SET); + } else if (strcmp(left, "offset_s") == 0) { + if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset_s", "clock class"); + ret = -EPERM; + goto error; + } + + ret = get_unary_signed(&entry_node->u.ctf_expression.right, offset_seconds); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Unexpected unary expression for clock class's `offset_s` attribute."); + ret = -EINVAL; + goto error; + } + + _SET(set, _CLOCK_OFFSET_S_SET); + } else if (strcmp(left, "offset") == 0) { + if (_IS_SET(set, _CLOCK_OFFSET_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset", "clock class"); + ret = -EPERM; + goto error; + } + + ret = get_unary_unsigned(ctx, &entry_node->u.ctf_expression.right, offset_cycles); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Unexpected unary expression for clock class's `offset` attribute."); + ret = -EINVAL; + goto error; + } + + _SET(set, _CLOCK_OFFSET_SET); + } else if (strcmp(left, "absolute") == 0) { + struct ctf_node *right; + + if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "absolute", "clock class"); + ret = -EPERM; + goto error; + } + + right = + _BT_LIST_FIRST_ENTRY(&entry_node->u.ctf_expression.right, struct ctf_node, siblings); + ret = get_boolean(ctx, right); + if (ret < 0) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + entry_node, "Unexpected unary expression for clock class's `absolute` attribute."); + ret = -EINVAL; + goto error; + } + + clock->is_absolute = ret; + _SET(set, _CLOCK_ABSOLUTE_SET); + } else { + _BT_COMP_LOGW_NODE(entry_node, "Unknown attribute in clock class: attr-name=\"%s\"", left); + } + + g_free(left); + left = NULL; + return 0; error: - g_free(left); - return ret; + g_free(left); + return ret; } -static inline -uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns) +static inline uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns) { - uint64_t cycles; + uint64_t cycles; - /* 1GHz */ - if (frequency == UINT64_C(1000000000)) { - cycles = ns; - } else { - cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9); - } + /* 1GHz */ + if (frequency == UINT64_C(1000000000)) { + cycles = ns; + } else { + cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9); + } - return cycles; + return cycles; } -static -void calibrate_clock_class_offsets(int64_t *offset_seconds, - uint64_t *offset_cycles, uint64_t freq) +static void calibrate_clock_class_offsets(int64_t *offset_seconds, uint64_t *offset_cycles, + uint64_t freq) { - if (*offset_cycles >= freq) { - const uint64_t s_in_offset_cycles = *offset_cycles / freq; + if (*offset_cycles >= freq) { + const uint64_t s_in_offset_cycles = *offset_cycles / freq; - *offset_seconds += (int64_t) s_in_offset_cycles; - *offset_cycles -= (s_in_offset_cycles * freq); - } + *offset_seconds += (int64_t) s_in_offset_cycles; + *offset_cycles -= (s_in_offset_cycles * freq); + } } -static -void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir *ctx, - struct ctf_clock_class *clock) +static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir *ctx, + struct ctf_clock_class *clock) { - if (ctx->decoder_config.force_clock_class_origin_unix_epoch) { - clock->is_absolute = true; - } + if (ctx->decoder_config.force_clock_class_origin_unix_epoch) { + clock->is_absolute = true; + } - return; + return; } -static -void apply_clock_class_offset(struct ctf_visitor_generate_ir *ctx, - struct ctf_clock_class *clock) +static void apply_clock_class_offset(struct ctf_visitor_generate_ir *ctx, + struct ctf_clock_class *clock) { - uint64_t freq; - int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s; - uint64_t offset_ns_to_apply; - int64_t cur_offset_s; - uint64_t cur_offset_cycles; - - if (ctx->decoder_config.clock_class_offset_s == 0 && - ctx->decoder_config.clock_class_offset_ns == 0) { - goto end; - } - - /* Transfer nanoseconds to seconds as much as possible */ - if (ctx->decoder_config.clock_class_offset_ns < 0) { - const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns; - const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1; - const int64_t extra_s = -abs_extra_s; - const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns - - (extra_s * INT64_C(1000000000)); - - BT_ASSERT(offset_ns > 0); - offset_ns_to_apply = (uint64_t) offset_ns; - offset_s_to_apply += extra_s; - } else { - const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns / - INT64_C(1000000000); - const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns - - (extra_s * INT64_C(1000000000)); - - BT_ASSERT(offset_ns >= 0); - offset_ns_to_apply = (uint64_t) offset_ns; - offset_s_to_apply += extra_s; - } - - freq = clock->frequency; - cur_offset_s = clock->offset_seconds; - cur_offset_cycles = clock->offset_cycles; - - /* Apply offsets */ - cur_offset_s += offset_s_to_apply; - cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply); - - /* - * Recalibrate offsets because the part in cycles can be greater - * than the frequency at this point. - */ - calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq); - - /* Set final offsets */ - clock->offset_seconds = cur_offset_s; - clock->offset_cycles = cur_offset_cycles; + uint64_t freq; + int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s; + uint64_t offset_ns_to_apply; + int64_t cur_offset_s; + uint64_t cur_offset_cycles; + + if (ctx->decoder_config.clock_class_offset_s == 0 && + ctx->decoder_config.clock_class_offset_ns == 0) { + goto end; + } + + /* Transfer nanoseconds to seconds as much as possible */ + if (ctx->decoder_config.clock_class_offset_ns < 0) { + const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns; + const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1; + const int64_t extra_s = -abs_extra_s; + const int64_t offset_ns = + ctx->decoder_config.clock_class_offset_ns - (extra_s * INT64_C(1000000000)); + + BT_ASSERT(offset_ns > 0); + offset_ns_to_apply = (uint64_t) offset_ns; + offset_s_to_apply += extra_s; + } else { + const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns / INT64_C(1000000000); + const int64_t offset_ns = + ctx->decoder_config.clock_class_offset_ns - (extra_s * INT64_C(1000000000)); + + BT_ASSERT(offset_ns >= 0); + offset_ns_to_apply = (uint64_t) offset_ns; + offset_s_to_apply += extra_s; + } + + freq = clock->frequency; + cur_offset_s = clock->offset_seconds; + cur_offset_cycles = clock->offset_cycles; + + /* Apply offsets */ + cur_offset_s += offset_s_to_apply; + cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply); + + /* + * Recalibrate offsets because the part in cycles can be greater + * than the frequency at this point. + */ + calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq); + + /* Set final offsets */ + clock->offset_seconds = cur_offset_s; + clock->offset_cycles = cur_offset_cycles; end: - return; + return; } -static -int visit_clock_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *clock_node) +static int visit_clock_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *clock_node) { - int ret = 0; - int set = 0; - struct ctf_clock_class *clock; - struct ctf_node *entry_node; - struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list; - const char *clock_class_name; - int64_t offset_seconds = 0; - uint64_t offset_cycles = 0; - uint64_t freq; - - if (clock_node->visited) { - return 0; - } - - clock_node->visited = TRUE; - - /* CTF 1.8's default frequency for a clock class is 1 GHz */ - clock = ctf_clock_class_create(); - if (!clock) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node, - "Cannot create default clock class."); - ret = -ENOMEM; - goto end; - } - - bt_list_for_each_entry(entry_node, decl_list, siblings) { - ret = visit_clock_decl_entry(ctx, entry_node, clock, &set, - &offset_seconds, &offset_cycles); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, - "Cannot visit clock class's entry: ret=%d", - ret); - goto end; - } - } - - if (!_IS_SET(&set, _CLOCK_NAME_SET)) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node, - "Missing `name` attribute in clock class."); - ret = -EPERM; - goto end; - } - - clock_class_name = clock->name->str; - BT_ASSERT(clock_class_name); - if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) { - /* - * Old versions of LTTng forgot to set its clock class - * as absolute, even if it is. This is important because - * it's a condition to be able to sort messages - * from different sources. - */ - clock->is_absolute = true; - } - - /* - * Adjust offsets so that the part in cycles is less than the - * frequency (move to the part in seconds). - */ - freq = clock->frequency; - calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq); - BT_ASSERT(offset_cycles < clock->frequency); - clock->offset_seconds = offset_seconds; - clock->offset_cycles = offset_cycles; - apply_clock_class_offset(ctx, clock); - apply_clock_class_is_absolute(ctx, clock); - g_ptr_array_add(ctx->ctf_tc->clock_classes, clock); - clock = NULL; + int ret = 0; + int set = 0; + struct ctf_clock_class *clock; + struct ctf_node *entry_node; + struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list; + const char *clock_class_name; + int64_t offset_seconds = 0; + uint64_t offset_cycles = 0; + uint64_t freq; + + if (clock_node->visited) { + return 0; + } + + clock_node->visited = TRUE; + + /* CTF 1.8's default frequency for a clock class is 1 GHz */ + clock = ctf_clock_class_create(); + if (!clock) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node, "Cannot create default clock class."); + ret = -ENOMEM; + goto end; + } + + bt_list_for_each_entry (entry_node, decl_list, siblings) { + ret = visit_clock_decl_entry(ctx, entry_node, clock, &set, &offset_seconds, &offset_cycles); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Cannot visit clock class's entry: ret=%d", + ret); + goto end; + } + } + + if (!_IS_SET(&set, _CLOCK_NAME_SET)) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node, "Missing `name` attribute in clock class."); + ret = -EPERM; + goto end; + } + + clock_class_name = clock->name->str; + BT_ASSERT(clock_class_name); + if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) { + /* + * Old versions of LTTng forgot to set its clock class + * as absolute, even if it is. This is important because + * it's a condition to be able to sort messages + * from different sources. + */ + clock->is_absolute = true; + } + + /* + * Adjust offsets so that the part in cycles is less than the + * frequency (move to the part in seconds). + */ + freq = clock->frequency; + calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq); + BT_ASSERT(offset_cycles < clock->frequency); + clock->offset_seconds = offset_seconds; + clock->offset_cycles = offset_cycles; + apply_clock_class_offset(ctx, clock); + apply_clock_class_is_absolute(ctx, clock); + g_ptr_array_add(ctx->ctf_tc->clock_classes, clock); + clock = NULL; end: - if (clock) { - ctf_clock_class_destroy(clock); - } + if (clock) { + ctf_clock_class_destroy(clock); + } - return ret; + return ret; } -static -int visit_root_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *root_decl_node) +static int visit_root_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *root_decl_node) { - int ret = 0; - - if (root_decl_node->visited) { - goto end; - } - - root_decl_node->visited = TRUE; - - switch (root_decl_node->type) { - case NODE_TYPEDEF: - ret = visit_field_class_def(ctx, - root_decl_node->u.field_class_def.field_class_specifier_list, - &root_decl_node->u.field_class_def.field_class_declarators); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node, - "Cannot add field class found in root scope."); - goto end; - } - break; - case NODE_TYPEALIAS: - ret = visit_field_class_alias(ctx, root_decl_node->u.field_class_alias.target, - root_decl_node->u.field_class_alias.alias); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node, - "Cannot add field class alias found in root scope."); - goto end; - } - break; - case NODE_TYPE_SPECIFIER_LIST: - { - struct ctf_field_class *decl = NULL; - - /* - * Just add the field class specifier to the root - * declaration scope. Put local reference. - */ - ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node, - "Cannot visit root scope's field class: " - "ret=%d", ret); - BT_ASSERT(!decl); - goto end; - } - - ctf_field_class_destroy(decl); - decl = NULL; - break; - } - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node, - "Unexpected node type: node-type=%d", - root_decl_node->type); - ret = -EPERM; - goto end; - } + int ret = 0; + + if (root_decl_node->visited) { + goto end; + } + + root_decl_node->visited = TRUE; + + switch (root_decl_node->type) { + case NODE_TYPEDEF: + ret = + visit_field_class_def(ctx, root_decl_node->u.field_class_def.field_class_specifier_list, + &root_decl_node->u.field_class_def.field_class_declarators); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node, + "Cannot add field class found in root scope."); + goto end; + } + break; + case NODE_TYPEALIAS: + ret = visit_field_class_alias(ctx, root_decl_node->u.field_class_alias.target, + root_decl_node->u.field_class_alias.alias); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node, + "Cannot add field class alias found in root scope."); + goto end; + } + break; + case NODE_TYPE_SPECIFIER_LIST: + { + struct ctf_field_class *decl = NULL; + + /* + * Just add the field class specifier to the root + * declaration scope. Put local reference. + */ + ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node, + "Cannot visit root scope's field class: " + "ret=%d", + ret); + BT_ASSERT(!decl); + goto end; + } + + ctf_field_class_destroy(decl); + decl = NULL; + break; + } + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node, "Unexpected node type: node-type=%d", + root_decl_node->type); + ret = -EPERM; + goto end; + } end: - return ret; + return ret; } BT_HIDDEN -struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create( - const struct ctf_metadata_decoder_config *decoder_config) +struct ctf_visitor_generate_ir * +ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config *decoder_config) { - struct ctf_visitor_generate_ir *ctx = NULL; + struct ctf_visitor_generate_ir *ctx = NULL; - /* Create visitor's context */ - ctx = ctx_create(decoder_config); - if (!ctx) { - BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, decoder_config->log_level, - decoder_config->self_comp, - "Cannot create visitor's context."); - goto error; - } + /* Create visitor's context */ + ctx = ctx_create(decoder_config); + if (!ctx) { + BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, decoder_config->log_level, decoder_config->self_comp, + "Cannot create visitor's context."); + goto error; + } - goto end; + goto end; error: - ctx_destroy(ctx); - ctx = NULL; + ctx_destroy(ctx); + ctx = NULL; end: - return ctx; + return ctx; } BT_HIDDEN void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor) { - ctx_destroy(visitor); + ctx_destroy(visitor); } BT_HIDDEN -bt_trace_class *ctf_visitor_generate_ir_get_ir_trace_class( - struct ctf_visitor_generate_ir *ctx) +bt_trace_class *ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir *ctx) { - BT_ASSERT_DBG(ctx); + BT_ASSERT_DBG(ctx); - if (ctx->trace_class) { - bt_trace_class_get_ref(ctx->trace_class); - } + if (ctx->trace_class) { + bt_trace_class_get_ref(ctx->trace_class); + } - return ctx->trace_class; + return ctx->trace_class; } BT_HIDDEN -struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class( - struct ctf_visitor_generate_ir *ctx) +struct ctf_trace_class * +ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir *ctx) { - BT_ASSERT_DBG(ctx); - BT_ASSERT_DBG(ctx->ctf_tc); - return ctx->ctf_tc; + BT_ASSERT_DBG(ctx); + BT_ASSERT_DBG(ctx->ctf_tc); + return ctx->ctf_tc; } BT_HIDDEN -int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *ctx, - struct ctf_node *node) +int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node) { - int ret = 0; - - BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects."); - - switch (node->type) { - case NODE_ROOT: - { - struct ctf_node *iter; - bool got_trace_decl = false; - - /* - * The first thing we need is the native byte order of - * the trace block, because early class aliases can have - * a `byte_order` attribute set to `native`. If we don't - * have the native byte order yet, and we don't have any - * trace block yet, then fail with EINCOMPLETE. - */ - if (ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_UNKNOWN) { - bt_list_for_each_entry(iter, &node->u.root.trace, siblings) { - if (got_trace_decl) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Duplicate trace (`trace` block)."); - ret = -1; - goto end; - } - - ret = set_trace_byte_order(ctx, iter); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Cannot set trace's native byte order: " - "ret=%d", ret); - goto end; - } - - got_trace_decl = true; - } - - if (!got_trace_decl) { - BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block)."); - ret = -EINCOMPLETE; - goto end; - } - } - - BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE || - ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG); - BT_ASSERT(ctx->current_scope && - !ctx->current_scope->parent_scope); - - /* Environment */ - bt_list_for_each_entry(iter, &node->u.root.env, siblings) { - ret = visit_env(ctx, iter); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot visit trace's environment (`env` block) entry: " - "ret=%d", ret); - goto end; - } - } - - BT_ASSERT(ctx->current_scope && - !ctx->current_scope->parent_scope); - - /* - * Visit clock blocks. - */ - bt_list_for_each_entry(iter, &node->u.root.clock, siblings) { - ret = visit_clock_decl(ctx, iter); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot visit clock class: ret=%d", - ret); - goto end; - } - } - - BT_ASSERT(ctx->current_scope && - !ctx->current_scope->parent_scope); - - /* - * Visit root declarations next, as they can be used by any - * following entity. - */ - bt_list_for_each_entry(iter, &node->u.root.declaration_list, - siblings) { - ret = visit_root_decl(ctx, iter); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot visit root entry: ret=%d", - ret); - goto end; - } - } - - BT_ASSERT(ctx->current_scope && - !ctx->current_scope->parent_scope); - - /* Callsite blocks are not supported */ - bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) { - _BT_COMP_LOGW_NODE(iter, - "\"callsite\" blocks are not supported as of this version."); - } - - BT_ASSERT(ctx->current_scope && - !ctx->current_scope->parent_scope); - - /* Trace */ - bt_list_for_each_entry(iter, &node->u.root.trace, siblings) { - ret = visit_trace_decl(ctx, iter); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot visit trace (`trace` block): " - "ret=%d", ret); - goto end; - } - } - - BT_ASSERT(ctx->current_scope && - !ctx->current_scope->parent_scope); - - /* Streams */ - bt_list_for_each_entry(iter, &node->u.root.stream, siblings) { - ret = visit_stream_decl(ctx, iter); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot visit stream class: ret=%d", - ret); - goto end; - } - } - - BT_ASSERT(ctx->current_scope && - !ctx->current_scope->parent_scope); - - /* Events */ - bt_list_for_each_entry(iter, &node->u.root.event, siblings) { - ret = visit_event_decl(ctx, iter); - if (ret) { - _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, - "Cannot visit event class: ret=%d", - ret); - goto end; - } - } - - BT_ASSERT(ctx->current_scope && - !ctx->current_scope->parent_scope); - break; - } - default: - _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, - "Unexpected node type: node-type=%d", - node->type); - ret = -EINVAL; - goto end; - } - - /* Update default clock classes */ - ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc, - &ctx->log_cfg); - if (ret) { - ret = -EINVAL; - goto end; - } - - /* Update trace class meanings */ - ret = ctf_trace_class_update_meanings(ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - - /* Update stream class configuration */ - ret = ctf_trace_class_update_stream_class_config(ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - - /* Update text arrays and sequences */ - ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - - /* Update structure/array/sequence alignments */ - ret = ctf_trace_class_update_alignments(ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - - /* Resolve sequence lengths and variant tags */ - ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc, &ctx->log_cfg); - if (ret) { - ret = -EINVAL; - goto end; - } - - if (ctx->trace_class) { - /* - * Update "in IR" for field classes. - * - * If we have no IR trace class, then we'll have no way - * to create IR fields anyway, so we leave all the - * `in_ir` members false. - */ - ret = ctf_trace_class_update_in_ir(ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - } - - /* Update saved value indexes */ - ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - - /* Validate what we have so far */ - ret = ctf_trace_class_validate(ctx->ctf_tc, &ctx->log_cfg); - if (ret) { - ret = -EINVAL; - goto end; - } - - /* - * If there are fields which are not related to the CTF format - * itself in the packet header and in event header field - * classes, warn about it because they are never translated. - */ - ctf_trace_class_warn_meaningless_header_fields(ctx->ctf_tc, - &ctx->log_cfg); - - if (ctx->trace_class) { - /* Copy new CTF metadata -> new IR metadata */ - ret = ctf_trace_class_translate(ctx->log_cfg.self_comp, - ctx->trace_class, ctx->ctf_tc); - if (ret) { - ret = -EINVAL; - goto end; - } - } + int ret = 0; + + BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects."); + + switch (node->type) { + case NODE_ROOT: + { + struct ctf_node *iter; + bool got_trace_decl = false; + + /* + * The first thing we need is the native byte order of + * the trace block, because early class aliases can have + * a `byte_order` attribute set to `native`. If we don't + * have the native byte order yet, and we don't have any + * trace block yet, then fail with EINCOMPLETE. + */ + if (ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_UNKNOWN) { + bt_list_for_each_entry (iter, &node->u.root.trace, siblings) { + if (got_trace_decl) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate trace (`trace` block)."); + ret = -1; + goto end; + } + + ret = set_trace_byte_order(ctx, iter); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, + "Cannot set trace's native byte order: " + "ret=%d", + ret); + goto end; + } + + got_trace_decl = true; + } + + if (!got_trace_decl) { + BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block)."); + ret = -EINCOMPLETE; + goto end; + } + } + + BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE || + ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG); + BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope); + + /* Environment */ + bt_list_for_each_entry (iter, &node->u.root.env, siblings) { + ret = visit_env(ctx, iter); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE( + iter, + "Cannot visit trace's environment (`env` block) entry: " + "ret=%d", + ret); + goto end; + } + } + + BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope); + + /* + * Visit clock blocks. + */ + bt_list_for_each_entry (iter, &node->u.root.clock, siblings) { + ret = visit_clock_decl(ctx, iter); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit clock class: ret=%d", ret); + goto end; + } + } + + BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope); + + /* + * Visit root declarations next, as they can be used by any + * following entity. + */ + bt_list_for_each_entry (iter, &node->u.root.declaration_list, siblings) { + ret = visit_root_decl(ctx, iter); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit root entry: ret=%d", ret); + goto end; + } + } + + BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope); + + /* Callsite blocks are not supported */ + bt_list_for_each_entry (iter, &node->u.root.callsite, siblings) { + _BT_COMP_LOGW_NODE(iter, "\"callsite\" blocks are not supported as of this version."); + } + + BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope); + + /* Trace */ + bt_list_for_each_entry (iter, &node->u.root.trace, siblings) { + ret = visit_trace_decl(ctx, iter); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, + "Cannot visit trace (`trace` block): " + "ret=%d", + ret); + goto end; + } + } + + BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope); + + /* Streams */ + bt_list_for_each_entry (iter, &node->u.root.stream, siblings) { + ret = visit_stream_decl(ctx, iter); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit stream class: ret=%d", ret); + goto end; + } + } + + BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope); + + /* Events */ + bt_list_for_each_entry (iter, &node->u.root.event, siblings) { + ret = visit_event_decl(ctx, iter); + if (ret) { + _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit event class: ret=%d", ret); + goto end; + } + } + + BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope); + break; + } + default: + _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected node type: node-type=%d", node->type); + ret = -EINVAL; + goto end; + } + + /* Update default clock classes */ + ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc, &ctx->log_cfg); + if (ret) { + ret = -EINVAL; + goto end; + } + + /* Update trace class meanings */ + ret = ctf_trace_class_update_meanings(ctx->ctf_tc); + if (ret) { + ret = -EINVAL; + goto end; + } + + /* Update stream class configuration */ + ret = ctf_trace_class_update_stream_class_config(ctx->ctf_tc); + if (ret) { + ret = -EINVAL; + goto end; + } + + /* Update text arrays and sequences */ + ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc); + if (ret) { + ret = -EINVAL; + goto end; + } + + /* Update structure/array/sequence alignments */ + ret = ctf_trace_class_update_alignments(ctx->ctf_tc); + if (ret) { + ret = -EINVAL; + goto end; + } + + /* Resolve sequence lengths and variant tags */ + ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc, &ctx->log_cfg); + if (ret) { + ret = -EINVAL; + goto end; + } + + if (ctx->trace_class) { + /* + * Update "in IR" for field classes. + * + * If we have no IR trace class, then we'll have no way + * to create IR fields anyway, so we leave all the + * `in_ir` members false. + */ + ret = ctf_trace_class_update_in_ir(ctx->ctf_tc); + if (ret) { + ret = -EINVAL; + goto end; + } + } + + /* Update saved value indexes */ + ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc); + if (ret) { + ret = -EINVAL; + goto end; + } + + /* Validate what we have so far */ + ret = ctf_trace_class_validate(ctx->ctf_tc, &ctx->log_cfg); + if (ret) { + ret = -EINVAL; + goto end; + } + + /* + * If there are fields which are not related to the CTF format + * itself in the packet header and in event header field + * classes, warn about it because they are never translated. + */ + ctf_trace_class_warn_meaningless_header_fields(ctx->ctf_tc, &ctx->log_cfg); + + if (ctx->trace_class) { + /* Copy new CTF metadata -> new IR metadata */ + ret = ctf_trace_class_translate(ctx->log_cfg.self_comp, ctx->trace_class, ctx->ctf_tc); + if (ret) { + ret = -EINVAL; + goto end; + } + } end: - return ret; + return ret; }