X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=plugins%2Fctf%2Fcommon%2Fmetadata%2Fvisitor-generate-ir.c;h=d746b27e551dac3d38a769e6b73794cfdcbab22b;hb=40f4ba76dd6f9508ca51b6220eaed57632281a07;hp=4188d45bdc6fcedc85acac5b6db4030287ecffad;hpb=56b43721cde738dace9fc445bcf388e944686cbc;p=babeltrace.git diff --git a/plugins/ctf/common/metadata/visitor-generate-ir.c b/plugins/ctf/common/metadata/visitor-generate-ir.c index 4188d45b..d746b27e 100644 --- a/plugins/ctf/common/metadata/visitor-generate-ir.c +++ b/plugins/ctf/common/metadata/visitor-generate-ir.c @@ -6,7 +6,7 @@ * Based on older ctf-visitor-generate-io-struct.c. * * Copyright 2010 - Mathieu Desnoyers - * Copyright 2015-2016 - Philippe Proulx + * Copyright 2015-2018 - Philippe Proulx * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,25 +36,21 @@ #include #include #include -#include +#include #include #include #include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include "scanner.h" #include "parser.h" #include "ast.h" #include "decoder.h" +#include "ctf-meta.h" +#include "ctf-meta-visitors.h" /* Bit value (left shift) */ #define _BV(_val) (1 << (_val)) @@ -65,6 +61,16 @@ /* Set bit in a set of bits */ #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_LOGE_STR("Cannot push scope."); \ + goto error; \ + } \ + } while (0) + /* Bits for verifying existing attributes in various declarations */ enum { _CLOCK_NAME_SET = _BV(0), @@ -118,41 +124,39 @@ enum { _EVENT_ID_SET = _BV(1), _EVENT_MODEL_EMF_URI_SET = _BV(2), _EVENT_STREAM_ID_SET = _BV(3), - _EVENT_LOGLEVEL_SET = _BV(4), + _EVENT_LOG_LEVEL_SET = _BV(4), _EVENT_CONTEXT_SET = _BV(5), _EVENT_FIELDS_SET = _BV(6), }; enum loglevel { - LOGLEVEL_EMERG = 0, - LOGLEVEL_ALERT = 1, - LOGLEVEL_CRIT = 2, - LOGLEVEL_ERR = 3, - LOGLEVEL_WARNING = 4, - LOGLEVEL_NOTICE = 5, - LOGLEVEL_INFO = 6, - LOGLEVEL_DEBUG_SYSTEM = 7, - LOGLEVEL_DEBUG_PROGRAM = 8, - LOGLEVEL_DEBUG_PROCESS = 9, - LOGLEVEL_DEBUG_MODULE = 10, - LOGLEVEL_DEBUG_UNIT = 11, - LOGLEVEL_DEBUG_FUNCTION = 12, - LOGLEVEL_DEBUG_LINE = 13, - LOGLEVEL_DEBUG = 14, + 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 type aliases */ +/* Prefixes of class aliases */ #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, _type, _member) \ - bt_list_entry((_ptr)->next, _type, _member) - -#define _BT_CTF_FIELD_TYPE_INIT(_name) struct bt_ctf_field_type *_name = NULL; +#define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) \ + bt_list_entry((_ptr)->next, _class, _member) #define _BT_LOGE_DUP_ATTR(_node, _attr, _entity) \ _BT_LOGE_LINENO((_node)->lineno, \ @@ -175,9 +179,9 @@ enum loglevel { */ struct ctx_decl_scope { /* - * Alias name to field type. + * Alias name to field class. * - * GQuark -> struct bt_ctf_field_type * + * GQuark -> struct ctf_field_class * (owned by this) */ GHashTable *decl_map; @@ -189,33 +193,23 @@ struct ctx_decl_scope { * Visitor context (private). */ struct ctx { - /* Trace being filled (owned by this) */ - struct bt_ctf_trace *trace; + /* Trace IR trace being filled (owned by this) */ + struct bt_trace *trace; - /* Current declaration scope (top of the stack) */ + /* 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; - /* 1 if trace declaration is visited */ - int is_trace_visited; + /* True if trace declaration is visited */ + bool is_trace_visited; - /* 1 if this is an LTTng trace */ + /* True if this is an LTTng trace */ bool is_lttng; - /* Eventual name suffix of the trace to set */ - char *trace_name_suffix; - - /* Trace attributes */ - enum bt_ctf_byte_order trace_bo; - uint64_t trace_major; - uint64_t trace_minor; - unsigned char trace_uuid[BABELTRACE_UUID_LEN]; - - /* - * Stream IDs to stream classes. - * - * int64_t -> struct bt_ctf_stream_class * - */ - GHashTable *stream_classes; + /* Eventual name suffix of the trace to set (owned by this) */ + char *trace_class_name_suffix; /* Config passed by the user */ struct ctf_metadata_decoder_config decoder_config; @@ -224,38 +218,7 @@ struct ctx { /* * Visitor (public). */ -struct ctf_visitor_generate_ir { }; - -static -const char *loglevel_str [] = { - [ LOGLEVEL_EMERG ] = "TRACE_EMERG", - [ LOGLEVEL_ALERT ] = "TRACE_ALERT", - [ LOGLEVEL_CRIT ] = "TRACE_CRIT", - [ LOGLEVEL_ERR ] = "TRACE_ERR", - [ LOGLEVEL_WARNING ] = "TRACE_WARNING", - [ LOGLEVEL_NOTICE ] = "TRACE_NOTICE", - [ LOGLEVEL_INFO ] = "TRACE_INFO", - [ LOGLEVEL_DEBUG_SYSTEM ] = "TRACE_DEBUG_SYSTEM", - [ LOGLEVEL_DEBUG_PROGRAM ] = "TRACE_DEBUG_PROGRAM", - [ LOGLEVEL_DEBUG_PROCESS ] = "TRACE_DEBUG_PROCESS", - [ LOGLEVEL_DEBUG_MODULE ] = "TRACE_DEBUG_MODULE", - [ LOGLEVEL_DEBUG_UNIT ] = "TRACE_DEBUG_UNIT", - [ LOGLEVEL_DEBUG_FUNCTION ] = "TRACE_DEBUG_FUNCTION", - [ LOGLEVEL_DEBUG_LINE ] = "TRACE_DEBUG_LINE", - [ LOGLEVEL_DEBUG ] = "TRACE_DEBUG", -}; - -static -const char *print_loglevel(int64_t value) -{ - if (value < 0) { - return NULL; - } - if (value >= _NR_LOGLEVELS) { - return "<>"; - } - return loglevel_str[value]; -} +struct ctf_visitor_generate_ir; /** * Creates a new declaration scope. @@ -275,7 +238,7 @@ struct ctx_decl_scope *ctx_decl_scope_create(struct ctx_decl_scope *par_scope) } scope->decl_map = g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify) bt_ctf_field_type_put); + NULL, (GDestroyNotify) ctf_field_class_destroy); scope->parent_scope = par_scope; end: @@ -315,7 +278,7 @@ GQuark get_prefixed_named_quark(char prefix, const char *name) { GQuark qname = 0; - assert(name); + BT_ASSERT(name); /* Prefix character + original string + '\0' */ char *prname = g_new(char, strlen(name) + 2); @@ -333,29 +296,31 @@ end: } /** - * Looks up a prefixed type alias within a declaration scope. + * Looks up a prefixed class alias within a declaration scope. * * @param scope Declaration scope * @param prefix Prefix character * @param name Alias name - * @param level Number of levels to dig (-1 means infinite) - * @returns Declaration, or NULL if not found + * @param levels Number of levels to dig into (-1 means infinite) + * @param copy True to return a copy + * @returns Declaration (owned by caller if \p copy is true), + * or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_prefix_alias( - struct ctx_decl_scope *scope, char prefix, - const char *name, int levels) +struct ctf_field_class *ctx_decl_scope_lookup_prefix_alias( + struct ctx_decl_scope *scope, char prefix, const char *name, + int levels, bool copy) { GQuark qname = 0; int cur_levels = 0; - _BT_CTF_FIELD_TYPE_INIT(decl); + struct ctf_field_class *decl = NULL; struct ctx_decl_scope *cur_scope = scope; - assert(scope); - assert(name); + BT_ASSERT(scope); + BT_ASSERT(name); qname = get_prefixed_named_quark(prefix, name); if (!qname) { - goto error; + goto end; } if (levels < 0) { @@ -367,34 +332,39 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_prefix_alias( (gconstpointer) GUINT_TO_POINTER(qname)); if (decl) { /* Caller's reference */ - bt_get(decl); - break; + if (copy) { + decl = ctf_field_class_copy(decl); + BT_ASSERT(decl); + } + + goto end; } cur_scope = cur_scope->parent_scope; cur_levels++; } +end: return decl; - -error: - return NULL; } /** - * Looks up a type alias within a declaration scope. + * Looks up a class alias within a declaration scope. * * @param scope Declaration scope * @param name Alias name - * @param level Number of levels to dig (-1 means infinite) - * @returns Declaration, or NULL if not found + * @param levels Number of levels to dig into (-1 means infinite) + * @param copy True to return a copy + * @returns Declaration (owned by caller if \p copy is true), + * or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_alias( - struct ctx_decl_scope *scope, const char *name, int levels) +struct ctf_field_class *ctx_decl_scope_lookup_alias( + struct ctx_decl_scope *scope, const char *name, int levels, + bool copy) { return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ALIAS, - name, levels); + name, levels, copy); } /** @@ -402,15 +372,18 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_alias( * * @param scope Declaration scope * @param name Enumeration name - * @param level Number of levels to dig (-1 means infinite) - * @returns Declaration, or NULL if not found + * @param levels Number of levels to dig into (-1 means infinite) + * @param copy True to return a copy + * @returns Declaration (owned by caller if \p copy is true), + * or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_enum( - struct ctx_decl_scope *scope, const char *name, int levels) +struct ctf_field_class_enum *ctx_decl_scope_lookup_enum( + struct ctx_decl_scope *scope, const char *name, int levels, + bool copy) { - return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ENUM, - name, levels); + return (void *) ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ENUM, + name, levels, copy); } /** @@ -418,15 +391,18 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_enum( * * @param scope Declaration scope * @param name Structure name - * @param level Number of levels to dig (-1 means infinite) - * @returns Declaration, or NULL if not found + * @param levels Number of levels to dig into (-1 means infinite) + * @param copy True to return a copy + * @returns Declaration (owned by caller if \p copy is true), + * or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_struct( - struct ctx_decl_scope *scope, const char *name, int levels) +struct ctf_field_class_struct *ctx_decl_scope_lookup_struct( + struct ctx_decl_scope *scope, const char *name, int levels, + bool copy) { - return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_STRUCT, - name, levels); + return (void *) ctx_decl_scope_lookup_prefix_alias(scope, + _PREFIX_STRUCT, name, levels, copy); } /** @@ -434,77 +410,74 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_struct( * * @param scope Declaration scope * @param name Variant name - * @param level Number of levels to dig (-1 means infinite) - * @returns Declaration, or NULL if not found + * @param levels Number of levels to dig into (-1 means infinite) + * @param copy True to return a copy + * @returns Declaration (owned by caller if \p copy is true), + * or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_variant( - struct ctx_decl_scope *scope, const char *name, int levels) +struct ctf_field_class_variant *ctx_decl_scope_lookup_variant( + struct ctx_decl_scope *scope, const char *name, int levels, + bool copy) { - return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_VARIANT, - name, levels); + return (void *) ctx_decl_scope_lookup_prefix_alias(scope, + _PREFIX_VARIANT, name, levels, copy); } /** - * Registers a prefixed type alias within a declaration scope. + * Registers a prefixed class alias within a declaration scope. * * @param scope Declaration scope * @param prefix Prefix character * @param name Alias name (non-NULL) - * @param decl Declaration to register + * @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 ctx_decl_scope *scope, - char prefix, const char *name, struct bt_ctf_field_type *decl) + char prefix, const char *name, struct ctf_field_class *decl) { int ret = 0; GQuark qname = 0; - _BT_CTF_FIELD_TYPE_INIT(edecl); - assert(scope); - assert(name); - assert(decl); + BT_ASSERT(scope); + BT_ASSERT(name); + BT_ASSERT(decl); qname = get_prefixed_named_quark(prefix, name); if (!qname) { ret = -ENOMEM; - goto error; + goto end; } /* Make sure alias does not exist in local scope */ - edecl = ctx_decl_scope_lookup_prefix_alias(scope, prefix, name, 1); - if (edecl) { - BT_PUT(edecl); + if (ctx_decl_scope_lookup_prefix_alias(scope, prefix, name, 1, + false)) { ret = -EEXIST; - goto error; + goto end; } - g_hash_table_insert(scope->decl_map, - GUINT_TO_POINTER(qname), decl); - - /* Hash table's reference */ - bt_get(decl); + decl = ctf_field_class_copy(decl); + BT_ASSERT(decl); + g_hash_table_insert(scope->decl_map, GUINT_TO_POINTER(qname), decl); - return 0; - -error: +end: return ret; } /** - * Registers a type alias within a declaration scope. + * Registers a class alias within a declaration scope. * * @param scope Declaration scope * @param name Alias name (non-NULL) - * @param decl Declaration to register + * @param decl Field class to register (copied) * @returns 0 if registration went okay, negative value otherwise */ static int ctx_decl_scope_register_alias(struct ctx_decl_scope *scope, - const char *name, struct bt_ctf_field_type *decl) + const char *name, struct ctf_field_class *decl) { return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ALIAS, - name, decl); + name, (void *) decl); } /** @@ -512,15 +485,15 @@ int ctx_decl_scope_register_alias(struct ctx_decl_scope *scope, * * @param scope Declaration scope * @param name Enumeration name (non-NULL) - * @param decl Enumeration declaration to register + * @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 ctx_decl_scope *scope, - const char *name, struct bt_ctf_field_type *decl) + const char *name, struct ctf_field_class_enum *decl) { return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ENUM, - name, decl); + name, (void *) decl); } /** @@ -528,15 +501,15 @@ int ctx_decl_scope_register_enum(struct ctx_decl_scope *scope, * * @param scope Declaration scope * @param name Structure name (non-NULL) - * @param decl Structure declaration to register + * @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 ctx_decl_scope *scope, - const char *name, struct bt_ctf_field_type *decl) + const char *name, struct ctf_field_class_struct *decl) { return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_STRUCT, - name, decl); + name, (void *) decl); } /** @@ -544,15 +517,15 @@ int ctx_decl_scope_register_struct(struct ctx_decl_scope *scope, * * @param scope Declaration scope * @param name Variant name (non-NULL) - * @param decl Variant declaration to register + * @param decl Variant field class to register * @returns 0 if registration went okay, negative value otherwise */ static int ctx_decl_scope_register_variant(struct ctx_decl_scope *scope, - const char *name, struct bt_ctf_field_type *decl) + const char *name, struct ctf_field_class_variant *decl) { return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_VARIANT, - name, decl); + name, (void *) decl); } /** @@ -564,9 +537,6 @@ static void ctx_destroy(struct ctx *ctx) { struct ctx_decl_scope *scope; - /* - * Destroy all scopes, from current one to the root scope. - */ if (!ctx) { goto end; @@ -574,6 +544,9 @@ void ctx_destroy(struct ctx *ctx) 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; @@ -581,13 +554,16 @@ void ctx_destroy(struct ctx *ctx) scope = parent_scope; } - bt_put(ctx->trace); + bt_object_put_ref(ctx->trace); + + if (ctx->ctf_tc) { + ctf_trace_class_destroy(ctx->ctf_tc); + } - if (ctx->stream_classes) { - g_hash_table_destroy(ctx->stream_classes); + if (ctx->trace_class_name_suffix) { + free(ctx->trace_class_name_suffix); } - free(ctx->trace_name_suffix); g_free(ctx); end: @@ -601,14 +577,12 @@ end: * @returns New visitor context, or NULL on error */ static -struct ctx *ctx_create(struct bt_ctf_trace *trace, - const struct ctf_metadata_decoder_config *decoder_config, - const char *trace_name_suffix) +struct ctx *ctx_create(const struct ctf_metadata_decoder_config *decoder_config, + const char *trace_class_name_suffix) { struct ctx *ctx = NULL; - struct ctx_decl_scope *scope = NULL; - assert(decoder_config); + BT_ASSERT(decoder_config); ctx = g_new0(struct ctx, 1); if (!ctx) { @@ -616,39 +590,42 @@ struct ctx *ctx_create(struct bt_ctf_trace *trace, goto error; } - /* Root declaration scope */ - scope = ctx_decl_scope_create(NULL); - if (!scope) { - BT_LOGE_STR("Cannot create declaration scope."); + ctx->trace = bt_trace_create(); + if (!ctx->trace) { + BT_LOGE_STR("Cannot create empty trace."); + goto error; + } + + ctx->ctf_tc = ctf_trace_class_create(); + if (!ctx->ctf_tc) { + BT_LOGE_STR("Cannot create CTF trace class."); goto error; } - ctx->stream_classes = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, (GDestroyNotify) bt_put); - if (!ctx->stream_classes) { - BT_LOGE_STR("Failed to allocate a GHashTable."); + /* Root declaration scope */ + ctx->current_scope = ctx_decl_scope_create(NULL); + if (!ctx->current_scope) { + BT_LOGE_STR("Cannot create declaration scope."); goto error; } - if (trace_name_suffix) { - ctx->trace_name_suffix = strdup(trace_name_suffix); - if (!ctx->trace_name_suffix) { + if (trace_class_name_suffix) { + ctx->trace_class_name_suffix = strdup(trace_class_name_suffix); + if (!ctx->trace_class_name_suffix) { BT_LOGE_STR("Failed to copy string."); goto error; } } - ctx->trace = trace; - ctx->current_scope = scope; - scope = NULL; - ctx->trace_bo = BT_CTF_BYTE_ORDER_NATIVE; ctx->decoder_config = *decoder_config; - return ctx; + goto end; error: ctx_destroy(ctx); - ctx_decl_scope_destroy(scope); - return NULL; + ctx = NULL; + +end: + return ctx; } /** @@ -664,7 +641,7 @@ int ctx_push_scope(struct ctx *ctx) int ret = 0; struct ctx_decl_scope *new_scope; - assert(ctx); + BT_ASSERT(ctx); new_scope = ctx_decl_scope_create(ctx->current_scope); if (!new_scope) { BT_LOGE_STR("Cannot create declaration scope."); @@ -683,7 +660,7 @@ void ctx_pop_scope(struct ctx *ctx) { struct ctx_decl_scope *parent_scope = NULL; - assert(ctx); + BT_ASSERT(ctx); if (!ctx->current_scope) { goto end; @@ -698,8 +675,63 @@ end: } static -int visit_type_specifier_list(struct ctx *ctx, struct ctf_node *ts_list, - struct bt_ctf_field_type **decl); +int visit_field_class_specifier_list(struct ctx *ctx, struct ctf_node *ts_list, + struct ctf_field_class **decl); + +static +char *remove_underscores_from_field_ref(const char *field_ref) +{ + const char *in_ch; + char *out_ch; + char *ret; + enum { + UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE, + UNDERSCORE_REMOVE_STATE_DO_NOT_REMOVE_NEXT_UNDERSCORE, + } state = UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE; + + BT_ASSERT(field_ref); + ret = calloc(strlen(field_ref) + 1, 1); + if (!ret) { + BT_LOGE("Failed to allocate a string: size=%zu", + strlen(field_ref) + 1); + goto end; + } + + in_ch = field_ref; + out_ch = ret; + + while (*in_ch != '\0') { + switch (*in_ch) { + case ' ': + case '\t': + /* Remove whitespace */ + in_ch++; + continue; + case '_': + if (state == UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE) { + in_ch++; + state = UNDERSCORE_REMOVE_STATE_DO_NOT_REMOVE_NEXT_UNDERSCORE; + continue; + } + + goto copy; + case '.': + state = UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE; + goto copy; + default: + state = UNDERSCORE_REMOVE_STATE_DO_NOT_REMOVE_NEXT_UNDERSCORE; + goto copy; + } + +copy: + *out_ch = *in_ch; + in_ch++; + out_ch++; + } + +end: + return ret; +} static int is_unary_string(struct bt_list_head *head) @@ -728,7 +760,7 @@ char *concatenate_unary_strings(struct bt_list_head *head) struct ctf_node *node; str = g_string_new(NULL); - assert(str); + BT_ASSERT(str); bt_list_for_each_entry(node, head, siblings) { char *src_string; @@ -858,6 +890,8 @@ int get_unary_unsigned(struct bt_list_head *head, uint64_t *value) int ret = 0; struct ctf_node *node; + *value = 0; + if (bt_list_empty(head)) { ret = -1; goto end; @@ -913,7 +947,6 @@ int get_unary_signed(struct bt_list_head *head, int64_t *value) 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_UNSIGNED_CONSTANT && uexpr_type != UNARY_SIGNED_CONSTANT) || uexpr_link != UNARY_LINK_UNKNOWN || i != 0; @@ -922,7 +955,7 @@ int get_unary_signed(struct bt_list_head *head, int64_t *value) goto end; } - switch (node->u.unary_expression.type) { + switch (uexpr_type) { case UNARY_UNSIGNED_CONSTANT: *value = (int64_t) node->u.unary_expression.u.unsigned_constant; @@ -1024,10 +1057,10 @@ end: } static -enum bt_ctf_byte_order byte_order_from_unary_expr(struct ctf_node *unary_expr) +enum ctf_byte_order byte_order_from_unary_expr(struct ctf_node *unary_expr) { const char *str; - enum bt_ctf_byte_order bo = BT_CTF_BYTE_ORDER_UNKNOWN; + enum ctf_byte_order bo = -1; if (unary_expr->u.unary_expression.type != UNARY_STRING) { _BT_LOGE_NODE(unary_expr, @@ -1038,11 +1071,11 @@ enum bt_ctf_byte_order byte_order_from_unary_expr(struct ctf_node *unary_expr) str = unary_expr->u.unary_expression.u.string; if (!strcmp(str, "be") || !strcmp(str, "network")) { - bo = BT_CTF_BYTE_ORDER_BIG_ENDIAN; + bo = CTF_BYTE_ORDER_BIG; } else if (!strcmp(str, "le")) { - bo = BT_CTF_BYTE_ORDER_LITTLE_ENDIAN; + bo = CTF_BYTE_ORDER_LITTLE; } else if (!strcmp(str, "native")) { - bo = BT_CTF_BYTE_ORDER_NATIVE; + bo = CTF_BYTE_ORDER_DEFAULT; } else { _BT_LOGE_NODE(unary_expr, "Unexpected \"byte_order\" attribute value: " @@ -1056,13 +1089,13 @@ end: } static -enum bt_ctf_byte_order get_real_byte_order(struct ctx *ctx, - struct ctf_node *uexpr) +enum ctf_byte_order get_real_byte_order(struct ctx *ctx, + struct ctf_node *uexpr) { - enum bt_ctf_byte_order bo = byte_order_from_unary_expr(uexpr); + enum ctf_byte_order bo = byte_order_from_unary_expr(uexpr); - if (bo == BT_CTF_BYTE_ORDER_NATIVE) { - bo = bt_ctf_trace_get_native_byte_order(ctx->trace); + if (bo == CTF_BYTE_ORDER_DEFAULT) { + bo = ctx->ctf_tc->default_byte_order; } return bo; @@ -1071,24 +1104,24 @@ enum bt_ctf_byte_order get_real_byte_order(struct ctx *ctx, static int is_align_valid(uint64_t align) { - return (align != 0) && !(align & (align - 1)); + return (align != 0) && !(align & (align - UINT64_C(1))); } static -int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, - GString *str) +int get_class_specifier_name(struct ctx *ctx, struct ctf_node *cls_specifier, + GString *str) { int ret = 0; - if (type_specifier->type != NODE_TYPE_SPECIFIER) { - _BT_LOGE_NODE(type_specifier, + if (cls_specifier->type != NODE_TYPE_SPECIFIER) { + _BT_LOGE_NODE(cls_specifier, "Unexpected node type: node-type=%d", - type_specifier->type); + cls_specifier->type); ret = -EINVAL; goto end; } - switch (type_specifier->u.type_specifier.type) { + switch (cls_specifier->u.field_class_specifier.type) { case TYPESPEC_VOID: g_string_append(str, "void"); break; @@ -1129,17 +1162,17 @@ int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, g_string_append(str, "const"); break; case TYPESPEC_ID_TYPE: - if (type_specifier->u.type_specifier.id_type) { + if (cls_specifier->u.field_class_specifier.id_type) { g_string_append(str, - type_specifier->u.type_specifier.id_type); + cls_specifier->u.field_class_specifier.id_type); } break; case TYPESPEC_STRUCT: { - struct ctf_node *node = type_specifier->u.type_specifier.node; + struct ctf_node *node = cls_specifier->u.field_class_specifier.node; if (!node->u._struct.name) { - _BT_LOGE_NODE(node, "Unexpected empty structure field type name."); + _BT_LOGE_NODE(node, "Unexpected empty structure field class name."); ret = -EINVAL; goto end; } @@ -1150,10 +1183,10 @@ int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, } case TYPESPEC_VARIANT: { - struct ctf_node *node = type_specifier->u.type_specifier.node; + struct ctf_node *node = cls_specifier->u.field_class_specifier.node; if (!node->u.variant.name) { - _BT_LOGE_NODE(node, "Unexpected empty variant field type name."); + _BT_LOGE_NODE(node, "Unexpected empty variant field class name."); ret = -EINVAL; goto end; } @@ -1164,11 +1197,11 @@ int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, } case TYPESPEC_ENUM: { - struct ctf_node *node = type_specifier->u.type_specifier.node; + struct ctf_node *node = cls_specifier->u.field_class_specifier.node; if (!node->u._enum.enum_id) { _BT_LOGE_NODE(node, - "Unexpected empty enumeration field type (`enum`) name."); + "Unexpected empty enumeration field class (`enum`) name."); ret = -EINVAL; goto end; } @@ -1181,9 +1214,9 @@ int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, case TYPESPEC_INTEGER: case TYPESPEC_STRING: default: - _BT_LOGE_NODE(type_specifier->u.type_specifier.node, - "Unexpected type specifier type: %d", - type_specifier->u.type_specifier.type); + _BT_LOGE_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; } @@ -1193,14 +1226,14 @@ end: } static -int get_type_specifier_list_name(struct ctx *ctx, - struct ctf_node *type_specifier_list, GString *str) +int get_class_specifier_list_name(struct ctx *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 = - &type_specifier_list->u.type_specifier_list.head; + &cls_specifier_list->u.field_class_specifier_list.head; bt_list_for_each_entry(iter, head, siblings) { if (alias_item_nr != 0) { @@ -1208,7 +1241,7 @@ int get_type_specifier_list_name(struct ctx *ctx, } alias_item_nr++; - ret = get_type_specifier_name(ctx, iter, str); + ret = get_class_specifier_name(ctx, iter, str); if (ret) { goto end; } @@ -1219,9 +1252,9 @@ end: } static -GQuark create_typealias_identifier(struct ctx *ctx, - struct ctf_node *type_specifier_list, - struct ctf_node *node_type_declarator) +GQuark create_class_alias_identifier(struct ctx *ctx, + struct ctf_node *cls_specifier_list, + struct ctf_node *node_field_class_declarator) { int ret; char *str_c; @@ -1229,10 +1262,10 @@ GQuark create_typealias_identifier(struct ctx *ctx, GQuark qalias = 0; struct ctf_node *iter; struct bt_list_head *pointers = - &node_type_declarator->u.type_declarator.pointers; + &node_field_class_declarator->u.field_class_declarator.pointers; str = g_string_new(""); - ret = get_type_specifier_list_name(ctx, type_specifier_list, str); + ret = get_class_specifier_list_name(ctx, cls_specifier_list, str); if (ret) { g_string_free(str, TRUE); goto end; @@ -1255,35 +1288,35 @@ end: } static -int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, - GQuark *field_name, struct ctf_node *node_type_declarator, - struct bt_ctf_field_type **field_decl, - struct bt_ctf_field_type *nested_decl) +int visit_field_class_declarator(struct ctx *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 type declarator node */ - if (node_type_declarator) { - if (node_type_declarator->u.type_declarator.type == + /* Validate field class declarator node */ + if (node_field_class_declarator) { + if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_UNKNOWN) { - _BT_LOGE_NODE(node_type_declarator, - "Unexpected type declarator type: type=%d", - node_type_declarator->u.type_declarator.type); + _BT_LOGE_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_type_declarator->u.type_declarator.bitfield_len != + if (node_field_class_declarator->u.field_class_declarator.bitfield_len != NULL) { - _BT_LOGE_NODE(node_type_declarator, + _BT_LOGE_NODE(node_field_class_declarator, "GCC bitfields are not supported as of this version."); ret = -EPERM; goto error; @@ -1293,88 +1326,83 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, /* Find the right nested declaration if not provided */ if (!nested_decl) { struct bt_list_head *pointers = - &node_type_declarator->u.type_declarator.pointers; + &node_field_class_declarator->u.field_class_declarator.pointers; - if (node_type_declarator && !bt_list_empty(pointers)) { + if (node_field_class_declarator && !bt_list_empty(pointers)) { GQuark qalias; - _BT_CTF_FIELD_TYPE_INIT(nested_decl_copy); /* * If we have a pointer declarator, it HAS to - * be present in the typealiases (else fail). + * be present in the field class aliases (else + * fail). */ - qalias = create_typealias_identifier(ctx, - type_specifier_list, node_type_declarator); + qalias = create_class_alias_identifier(ctx, + cls_specifier_list, node_field_class_declarator); nested_decl = ctx_decl_scope_lookup_alias(ctx->current_scope, - g_quark_to_string(qalias), -1); + g_quark_to_string(qalias), -1, true); if (!nested_decl) { - _BT_LOGE_NODE(node_type_declarator, - "Cannot find type alias: name=\"%s\"", + _BT_LOGE_NODE(node_field_class_declarator, + "Cannot find class alias: name=\"%s\"", g_quark_to_string(qalias)); ret = -EINVAL; goto error; } - /* Make a copy of it */ - nested_decl_copy = bt_ctf_field_type_copy(nested_decl); - BT_PUT(nested_decl); - if (!nested_decl_copy) { - _BT_LOGE_NODE(node_type_declarator, - "Cannot copy nested field type."); - ret = -EINVAL; - goto error; - } - - BT_MOVE(nested_decl, nested_decl_copy); + if (nested_decl->type == CTF_FIELD_CLASS_TYPE_INT) { + /* Pointer: force integer's base to 16 */ + struct ctf_field_class_int *int_fc = + (void *) nested_decl; - /* Force integer's base to 16 since it's a pointer */ - if (bt_ctf_field_type_is_integer(nested_decl)) { - ret = bt_ctf_field_type_integer_set_base( - nested_decl, - BT_CTF_INTEGER_BASE_HEXADECIMAL); - assert(ret == 0); + int_fc->disp_base = + BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL; } } else { - ret = visit_type_specifier_list(ctx, - type_specifier_list, &nested_decl); + ret = visit_field_class_specifier_list(ctx, + cls_specifier_list, &nested_decl); if (ret) { - assert(!nested_decl); + BT_ASSERT(!nested_decl); goto error; } } } - assert(nested_decl); + BT_ASSERT(nested_decl); - if (!node_type_declarator) { - BT_MOVE(*field_decl, nested_decl); + if (!node_field_class_declarator) { + *field_decl = nested_decl; + nested_decl = NULL; goto end; } - if (node_type_declarator->u.type_declarator.type == TYPEDEC_ID) { - if (node_type_declarator->u.type_declarator.u.id) { + 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_type_declarator->u.type_declarator.u.id; + node_field_class_declarator->u.field_class_declarator.u.id; + + if (id[0] == '_') { + id++; + } *field_name = g_quark_from_string(id); } else { *field_name = 0; } - BT_MOVE(*field_decl, nested_decl); + *field_decl = nested_decl; + nested_decl = NULL; goto end; } else { struct ctf_node *first; - _BT_CTF_FIELD_TYPE_INIT(decl); - _BT_CTF_FIELD_TYPE_INIT(outer_field_decl); + struct ctf_field_class *decl = NULL; + struct ctf_field_class *outer_field_decl = NULL; struct bt_list_head *length = - &node_type_declarator-> - u.type_declarator.u.nested.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_LOGE_NODE(node_type_declarator, + _BT_LOGE_NODE(node_field_class_declarator, "Expecting length field reference or value."); ret = -EINVAL; goto error; @@ -1392,48 +1420,96 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, switch (first->u.unary_expression.type) { case UNARY_UNSIGNED_CONSTANT: { - size_t len; - _BT_CTF_FIELD_TYPE_INIT(array_decl); - - len = first->u.unary_expression.u.unsigned_constant; - array_decl = bt_ctf_field_type_array_create(nested_decl, - len); - BT_PUT(nested_decl); - if (!array_decl) { - _BT_LOGE_NODE(first, - "Cannot create array field type."); - ret = -ENOMEM; - goto error; - } - - BT_MOVE(decl, array_decl); + 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 = (void *) array_decl; break; } case UNARY_STRING: { /* Lookup unsigned integer definition, create seq. */ - _BT_CTF_FIELD_TYPE_INIT(seq_decl); + struct ctf_field_class_sequence *seq_decl = NULL; char *length_name = concatenate_unary_strings(length); if (!length_name) { - _BT_LOGE_NODE(node_type_declarator, + _BT_LOGE_NODE(node_field_class_declarator, "Cannot concatenate unary strings."); ret = -EINVAL; goto error; } - seq_decl = bt_ctf_field_type_sequence_create( - nested_decl, length_name); - g_free(length_name); - BT_PUT(nested_decl); - if (!seq_decl) { - _BT_LOGE_NODE(node_type_declarator, - "Cannot create sequence field type."); - ret = -ENOMEM; - 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_LOGE_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_LOGE_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_LOGE_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 = (void *) array_decl; + } else { + char *length_name_no_underscore = + remove_underscores_from_field_ref( + length_name); + if (!length_name_no_underscore) { + /* + * remove_underscores_from_field_ref() + * logs errors + */ + ret = -EINVAL; + goto error; + } + 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_no_underscore); + free(length_name_no_underscore); + decl = (void *) seq_decl; } - BT_MOVE(decl, seq_decl); + g_free(length_name); break; } default: @@ -1441,9 +1517,9 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, goto error; } - assert(!nested_decl); - assert(decl); - assert(!*field_decl); + BT_ASSERT(!nested_decl); + BT_ASSERT(decl); + BT_ASSERT(!*field_decl); /* * At this point, we found the next nested declaration. @@ -1452,238 +1528,226 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, * nested declaration as the content of the outer * container, MOVING its ownership. */ - ret = visit_type_declarator(ctx, type_specifier_list, + ret = visit_field_class_declarator(ctx, cls_specifier_list, field_name, - node_type_declarator-> - u.type_declarator.u.nested.type_declarator, + node_field_class_declarator-> + u.field_class_declarator.u.nested.field_class_declarator, &outer_field_decl, decl); decl = NULL; if (ret) { - assert(!outer_field_decl); + BT_ASSERT(!outer_field_decl); ret = -EINVAL; goto error; } - assert(outer_field_decl); - BT_MOVE(*field_decl, outer_field_decl); + BT_ASSERT(outer_field_decl); + *field_decl = outer_field_decl; + outer_field_decl = NULL; } -end: - BT_PUT(nested_decl); - assert(*field_decl); - - return 0; + BT_ASSERT(*field_decl); + goto end; error: - BT_PUT(nested_decl); - BT_PUT(*field_decl); + ctf_field_class_destroy(*field_decl); + *field_decl = NULL; + if (ret >= 0) { + ret = -1; + } + +end: + ctf_field_class_destroy(nested_decl); + nested_decl = NULL; return ret; } static int visit_struct_decl_field(struct ctx *ctx, - struct bt_ctf_field_type *struct_decl, - struct ctf_node *type_specifier_list, - struct bt_list_head *type_declarators) + 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; - _BT_CTF_FIELD_TYPE_INIT(field_decl); + struct ctf_field_class *field_decl = NULL; - bt_list_for_each_entry(iter, type_declarators, siblings) { + bt_list_for_each_entry(iter, field_class_declarators, siblings) { field_decl = NULL; GQuark qfield_name; const char *field_name; - _BT_CTF_FIELD_TYPE_INIT(efield_decl); - ret = visit_type_declarator(ctx, type_specifier_list, + ret = visit_field_class_declarator(ctx, cls_specifier_list, &qfield_name, iter, &field_decl, NULL); if (ret) { - assert(!field_decl); - _BT_LOGE_NODE(type_specifier_list, - "Cannot visit type declarator: ret=%d", ret); + BT_ASSERT(!field_decl); + _BT_LOGE_NODE(cls_specifier_list, + "Cannot visit field class declarator: ret=%d", ret); goto error; } - assert(field_decl); + BT_ASSERT(field_decl); field_name = g_quark_to_string(qfield_name); /* Check if field with same name already exists */ - efield_decl = - bt_ctf_field_type_structure_get_field_type_by_name( - struct_decl, field_name); - if (efield_decl) { - BT_PUT(efield_decl); - _BT_LOGE_NODE(type_specifier_list, - "Duplicate field in structure field type: " + if (ctf_field_class_struct_borrow_member_by_name( + struct_decl, field_name)) { + _BT_LOGE_NODE(cls_specifier_list, + "Duplicate field in structure field class: " "field-name=\"%s\"", field_name); ret = -EINVAL; goto error; } /* Add field to structure */ - ret = bt_ctf_field_type_structure_add_field(struct_decl, - field_decl, field_name); - BT_PUT(field_decl); - if (ret) { - _BT_LOGE_NODE(type_specifier_list, - "Cannot add field to structure field type: " - "field-name=\"%s\", ret=%d", - g_quark_to_string(qfield_name), ret); - goto error; - } + ctf_field_class_struct_append_member(struct_decl, + field_name, field_decl); + field_decl = NULL; } return 0; error: - BT_PUT(field_decl); - + ctf_field_class_destroy(field_decl); + field_decl = NULL; return ret; } static int visit_variant_decl_field(struct ctx *ctx, - struct bt_ctf_field_type *variant_decl, - struct ctf_node *type_specifier_list, - struct bt_list_head *type_declarators) + 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; - _BT_CTF_FIELD_TYPE_INIT(field_decl); + struct ctf_field_class *field_decl = NULL; - bt_list_for_each_entry(iter, type_declarators, siblings) { + bt_list_for_each_entry(iter, field_class_declarators, siblings) { field_decl = NULL; GQuark qfield_name; const char *field_name; - _BT_CTF_FIELD_TYPE_INIT(efield_decl); - ret = visit_type_declarator(ctx, type_specifier_list, + ret = visit_field_class_declarator(ctx, cls_specifier_list, &qfield_name, iter, &field_decl, NULL); if (ret) { - assert(!field_decl); - _BT_LOGE_NODE(type_specifier_list, - "Cannot visit type declarator: ret=%d", ret); + BT_ASSERT(!field_decl); + _BT_LOGE_NODE(cls_specifier_list, + "Cannot visit field class declarator: ret=%d", ret); goto error; } - assert(field_decl); + BT_ASSERT(field_decl); field_name = g_quark_to_string(qfield_name); /* Check if field with same name already exists */ - efield_decl = - bt_ctf_field_type_variant_get_field_type_by_name( - variant_decl, field_name); - if (efield_decl) { - BT_PUT(efield_decl); - _BT_LOGE_NODE(type_specifier_list, - "Duplicate field in variant field type: " + if (ctf_field_class_variant_borrow_option_by_name( + variant_decl, field_name)) { + _BT_LOGE_NODE(cls_specifier_list, + "Duplicate field in variant field class: " "field-name=\"%s\"", field_name); ret = -EINVAL; goto error; } /* Add field to structure */ - ret = bt_ctf_field_type_variant_add_field(variant_decl, - field_decl, field_name); - BT_PUT(field_decl); - if (ret) { - _BT_LOGE_NODE(type_specifier_list, - "Cannot add field to variant field type: " - "field-name=\"%s\", ret=%d", - g_quark_to_string(qfield_name), ret); - goto error; - } + ctf_field_class_variant_append_option(variant_decl, + field_name, field_decl); + field_decl = NULL; } return 0; error: - BT_PUT(field_decl); - + ctf_field_class_destroy(field_decl); + field_decl = NULL; return ret; } static -int visit_typedef(struct ctx *ctx, struct ctf_node *type_specifier_list, - struct bt_list_head *type_declarators) +int visit_field_class_def(struct ctx *ctx, struct ctf_node *cls_specifier_list, + struct bt_list_head *field_class_declarators) { int ret = 0; GQuark qidentifier; struct ctf_node *iter; - _BT_CTF_FIELD_TYPE_INIT(type_decl); + struct ctf_field_class *class_decl = NULL; - bt_list_for_each_entry(iter, type_declarators, siblings) { - ret = visit_type_declarator(ctx, type_specifier_list, - &qidentifier, iter, &type_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_LOGE_NODE(iter, - "Cannot visit type declarator: ret=%d", ret); + "Cannot visit field class declarator: ret=%d", ret); ret = -EINVAL; goto end; } - /* Do not allow typedef and typealias of untagged variants */ - if (bt_ctf_field_type_is_variant(type_decl)) { - if (bt_ctf_field_type_variant_get_tag_name(type_decl)) { + /* 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 = + (void *) class_decl; + + if (var_fc->tag_path.path->len == 0) { _BT_LOGE_NODE(iter, - "Type definition of untagged variant field type is not allowed."); + "Type definition of untagged variant field class is not allowed."); ret = -EPERM; goto end; } } ret = ctx_decl_scope_register_alias(ctx->current_scope, - g_quark_to_string(qidentifier), type_decl); + g_quark_to_string(qidentifier), class_decl); if (ret) { _BT_LOGE_NODE(iter, - "Cannot register type definition: name=\"%s\"", + "Cannot register field class alias: name=\"%s\"", g_quark_to_string(qidentifier)); goto end; } } end: - BT_PUT(type_decl); - + ctf_field_class_destroy(class_decl); + class_decl = NULL; return ret; } static -int visit_typealias(struct ctx *ctx, struct ctf_node *target, - struct ctf_node *alias) +int visit_field_class_alias(struct ctx *ctx, struct ctf_node *target, + struct ctf_node *alias) { int ret = 0; GQuark qalias; struct ctf_node *node; GQuark qdummy_field_name; - _BT_CTF_FIELD_TYPE_INIT(type_decl); + struct ctf_field_class *class_decl = NULL; - /* Create target type declaration */ - if (bt_list_empty(&target->u.typealias_target.type_declarators)) { + /* 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.typealias_target.type_declarators, + &target->u.field_class_alias_target.field_class_declarators, struct ctf_node, siblings); } - ret = visit_type_declarator(ctx, - target->u.typealias_target.type_specifier_list, - &qdummy_field_name, node, &type_decl, NULL); + 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) { - assert(!type_decl); + BT_ASSERT(!class_decl); _BT_LOGE_NODE(node, - "Cannot visit type declarator: ret=%d", ret); + "Cannot visit field class declarator: ret=%d", ret); goto end; } - /* Do not allow typedef and typealias of untagged variants */ - if (bt_ctf_field_type_is_variant(type_decl)) { - if (bt_ctf_field_type_variant_get_tag_name(type_decl)) { - _BT_LOGE_NODE(node, - "Type definition of untagged variant field type is not allowed."); + /* 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 = (void *) class_decl; + + if (var_fc->tag_path.path->len == 0) { + _BT_LOGE_NODE(target, + "Type definition of untagged variant field class is not allowed."); ret = -EPERM; goto end; } @@ -1694,7 +1758,7 @@ int visit_typealias(struct ctx *ctx, struct ctf_node *target, * abstract or not (if it has an identifier). Check it here. */ if (qdummy_field_name != 0) { - _BT_LOGE_NODE(node, + _BT_LOGE_NODE(target, "Expecting empty identifier: id=\"%s\"", g_quark_to_string(qdummy_field_name)); ret = -EINVAL; @@ -1702,49 +1766,49 @@ int visit_typealias(struct ctx *ctx, struct ctf_node *target, } /* Create alias identifier */ - node = _BT_LIST_FIRST_ENTRY(&alias->u.typealias_alias.type_declarators, + node = _BT_LIST_FIRST_ENTRY(&alias->u.field_class_alias_name.field_class_declarators, struct ctf_node, siblings); - qalias = create_typealias_identifier(ctx, - alias->u.typealias_alias.type_specifier_list, node); + qalias = create_class_alias_identifier(ctx, + alias->u.field_class_alias_name.field_class_specifier_list, node); ret = ctx_decl_scope_register_alias(ctx->current_scope, - g_quark_to_string(qalias), type_decl); + g_quark_to_string(qalias), class_decl); if (ret) { _BT_LOGE_NODE(node, - "Cannot register type alias: name=\"%s\"", + "Cannot register class alias: name=\"%s\"", g_quark_to_string(qalias)); goto end; } end: - BT_PUT(type_decl); - + ctf_field_class_destroy(class_decl); + class_decl = NULL; return ret; } static int visit_struct_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, - struct bt_ctf_field_type *struct_decl) + struct ctf_field_class_struct *struct_decl) { int ret = 0; switch (entry_node->type) { case NODE_TYPEDEF: - ret = visit_typedef(ctx, - entry_node->u._typedef.type_specifier_list, - &entry_node->u._typedef.type_declarators); + 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_LOGE_NODE(entry_node, - "Cannot add type definition found in structure field type: ret=%d", + "Cannot add field class found in structure field class: ret=%d", ret); goto end; } break; case NODE_TYPEALIAS: - ret = visit_typealias(ctx, entry_node->u.typealias.target, - entry_node->u.typealias.alias); + ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target, + entry_node->u.field_class_alias.alias); if (ret) { _BT_LOGE_NODE(entry_node, - "Cannot add type alias found in structure field type: ret=%d", + "Cannot add field class alias found in structure field class: ret=%d", ret); goto end; } @@ -1753,9 +1817,9 @@ int visit_struct_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, /* Field */ ret = visit_struct_decl_field(ctx, struct_decl, entry_node->u.struct_or_variant_declaration. - type_specifier_list, + field_class_specifier_list, &entry_node->u.struct_or_variant_declaration. - type_declarators); + field_class_declarators); if (ret) { goto end; } @@ -1773,28 +1837,28 @@ end: static int visit_variant_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, - struct bt_ctf_field_type *variant_decl) + struct ctf_field_class_variant *variant_decl) { int ret = 0; switch (entry_node->type) { case NODE_TYPEDEF: - ret = visit_typedef(ctx, - entry_node->u._typedef.type_specifier_list, - &entry_node->u._typedef.type_declarators); + 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_LOGE_NODE(entry_node, - "Cannot add type definition found in variant field type: ret=%d", + "Cannot add field class found in variant field class: ret=%d", ret); goto end; } break; case NODE_TYPEALIAS: - ret = visit_typealias(ctx, entry_node->u.typealias.target, - entry_node->u.typealias.alias); + ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target, + entry_node->u.field_class_alias.alias); if (ret) { _BT_LOGE_NODE(entry_node, - "Cannot add type alias found in variant field type: ret=%d", + "Cannot add field class alias found in variant field class: ret=%d", ret); goto end; } @@ -1803,9 +1867,9 @@ int visit_variant_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, /* Field */ ret = visit_variant_decl_field(ctx, variant_decl, entry_node->u.struct_or_variant_declaration. - type_specifier_list, + field_class_specifier_list, &entry_node->u.struct_or_variant_declaration. - type_declarators); + field_class_declarators); if (ret) { goto end; } @@ -1824,54 +1888,39 @@ end: static int visit_struct_decl(struct ctx *ctx, const char *name, - struct bt_list_head *decl_list, int has_body, - struct bt_list_head *min_align, - struct bt_ctf_field_type **struct_decl) + 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) { - _BT_CTF_FIELD_TYPE_INIT(struct_decl_copy); - if (!name) { - BT_LOGE_STR("Bodyless structure field type: missing name."); + BT_LOGE_STR("Bodyless structure field class: missing name."); ret = -EPERM; goto error; } *struct_decl = ctx_decl_scope_lookup_struct(ctx->current_scope, - name, -1); + name, -1, true); if (!*struct_decl) { - BT_LOGE("Cannot find structure field type: name=\"struct %s\"", + BT_LOGE("Cannot find structure field class: name=\"struct %s\"", name); ret = -EINVAL; goto error; } - - /* Make a copy of it */ - struct_decl_copy = bt_ctf_field_type_copy(*struct_decl); - if (!struct_decl_copy) { - BT_LOGE_STR("Cannot create copy of structure field type."); - ret = -EINVAL; - goto error; - } - - BT_MOVE(*struct_decl, struct_decl_copy); } else { struct ctf_node *entry_node; uint64_t min_align_value = 0; if (name) { - _BT_CTF_FIELD_TYPE_INIT(estruct_decl); - - estruct_decl = ctx_decl_scope_lookup_struct( - ctx->current_scope, name, 1); - if (estruct_decl) { - BT_PUT(estruct_decl); - BT_LOGE("Structure field type already declared in local scope: " + if (ctx_decl_scope_lookup_struct( + ctx->current_scope, name, 1, false)) { + BT_LOGE("Structure field class already declared in local scope: " "name=\"struct %s\"", name); ret = -EINVAL; goto error; @@ -1881,41 +1930,27 @@ int visit_struct_decl(struct ctx *ctx, const char *name, if (!bt_list_empty(min_align)) { ret = get_unary_unsigned(min_align, &min_align_value); if (ret) { - BT_LOGE("Unexpected unary expression for structure field type's `align` attribute: " + BT_LOGE("Unexpected unary expression for structure field class's `align` attribute: " "ret=%d", ret); goto error; } } - *struct_decl = bt_ctf_field_type_structure_create(); - if (!*struct_decl) { - BT_LOGE_STR("Cannot create empty structure field type."); - ret = -ENOMEM; - goto error; - } + *struct_decl = ctf_field_class_struct_create(); + BT_ASSERT(*struct_decl); if (min_align_value != 0) { - ret = bt_ctf_field_type_set_alignment(*struct_decl, - min_align_value); - if (ret) { - BT_LOGE("Cannot set structure field type's alignment: " - "ret=%d", ret); - goto error; - } + (*struct_decl)->base.alignment = min_align_value; } - ret = ctx_push_scope(ctx); - if (ret) { - BT_LOGE_STR("Cannot push scope."); - goto error; - } + _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_LOGE_NODE(entry_node, - "Cannot visit structure field type entry: " + "Cannot visit structure field class entry: " "ret=%d", ret); ctx_pop_scope(ctx); goto error; @@ -1928,7 +1963,7 @@ int visit_struct_decl(struct ctx *ctx, const char *name, ret = ctx_decl_scope_register_struct(ctx->current_scope, name, *struct_decl); if (ret) { - BT_LOGE("Cannot register structure field type in declaration scope: " + BT_LOGE("Cannot register structure field class in declaration scope: " "name=\"struct %s\", ret=%d", name, ret); goto error; } @@ -1938,88 +1973,62 @@ int visit_struct_decl(struct ctx *ctx, const char *name, return 0; error: - BT_PUT(*struct_decl); - + ctf_field_class_destroy((void *) *struct_decl); + *struct_decl = NULL; return ret; } static int visit_variant_decl(struct ctx *ctx, const char *name, const char *tag, struct bt_list_head *decl_list, - int has_body, struct bt_ctf_field_type **variant_decl) + int has_body, struct ctf_field_class_variant **variant_decl) { int ret = 0; - _BT_CTF_FIELD_TYPE_INIT(untagged_variant_decl); + 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) { - _BT_CTF_FIELD_TYPE_INIT(variant_decl_copy); - if (!name) { - BT_LOGE_STR("Bodyless variant field type: missing name."); + BT_LOGE_STR("Bodyless variant field class: missing name."); ret = -EPERM; goto error; } untagged_variant_decl = ctx_decl_scope_lookup_variant(ctx->current_scope, - name, -1); + name, -1, true); if (!untagged_variant_decl) { - BT_LOGE("Cannot find variant field type: name=\"variant %s\"", + BT_LOGE("Cannot find variant field class: name=\"variant %s\"", name); ret = -EINVAL; goto error; } - - /* Make a copy of it */ - variant_decl_copy = bt_ctf_field_type_copy( - untagged_variant_decl); - if (!variant_decl_copy) { - BT_LOGE_STR("Cannot create copy of variant field type."); - ret = -EINVAL; - goto error; - } - - BT_MOVE(untagged_variant_decl, variant_decl_copy); } else { struct ctf_node *entry_node; if (name) { - struct bt_ctf_field_type *evariant_decl = - ctx_decl_scope_lookup_struct(ctx->current_scope, - name, 1); - - if (evariant_decl) { - BT_PUT(evariant_decl); - BT_LOGE("Variant field type already declared in local scope: " + if (ctx_decl_scope_lookup_variant(ctx->current_scope, + name, 1, false)) { + BT_LOGE("Variant field class already declared in local scope: " "name=\"variant %s\"", name); ret = -EINVAL; goto error; } } - untagged_variant_decl = bt_ctf_field_type_variant_create(NULL, - NULL); - if (!untagged_variant_decl) { - BT_LOGE_STR("Cannot create empty variant field type."); - ret = -ENOMEM; - goto error; - } - - ret = ctx_push_scope(ctx); - if (ret) { - BT_LOGE_STR("Cannot push scope."); - 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_LOGE_NODE(entry_node, - "Cannot visit variant field type entry: " + "Cannot visit variant field class entry: " "ret=%d", ret); ctx_pop_scope(ctx); goto error; @@ -2033,7 +2042,7 @@ int visit_variant_decl(struct ctx *ctx, const char *name, ctx->current_scope, name, untagged_variant_decl); if (ret) { - BT_LOGE("Cannot register variant field type in declaration scope: " + BT_LOGE("Cannot register variant field class in declaration scope: " "name=\"variant %s\", ret=%d", name, ret); goto error; } @@ -2045,52 +2054,73 @@ int visit_variant_decl(struct ctx *ctx, const char *name, * return untagged variant. */ if (!tag) { - BT_MOVE(*variant_decl, untagged_variant_decl); + *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. */ - ret = bt_ctf_field_type_variant_set_tag_name( - untagged_variant_decl, tag); - if (ret) { - BT_LOGE("Cannot set variant field type's tag name: " - "tag-name=\"%s\"", tag); + char *tag_no_underscore = + remove_underscores_from_field_ref(tag); + + if (!tag_no_underscore) { + /* remove_underscores_from_field_ref() logs errors */ goto error; } - BT_MOVE(*variant_decl, untagged_variant_decl); + g_string_assign(untagged_variant_decl->tag_ref, + tag_no_underscore); + free(tag_no_underscore); + *variant_decl = untagged_variant_decl; + untagged_variant_decl = NULL; } - assert(!untagged_variant_decl); - assert(*variant_decl); - + BT_ASSERT(!untagged_variant_decl); + BT_ASSERT(*variant_decl); return 0; error: - BT_PUT(untagged_variant_decl); - BT_PUT(*variant_decl); - + ctf_field_class_destroy((void *) untagged_variant_decl); + untagged_variant_decl = NULL; + ctf_field_class_destroy((void *) *variant_decl); + *variant_decl = NULL; return ret; } +struct uori { + bool is_signed; + union { + uint64_t u; + uint64_t i; + } value; +}; + static int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator, - struct bt_ctf_field_type *enum_decl, int64_t *last, int is_signed) + struct ctf_field_class_enum *enum_decl, struct uori *last) { int ret = 0; int nr_vals = 0; struct ctf_node *iter; - int64_t start = 0, end = 0; + 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; + const char *effective_label = label; struct bt_list_head *values = &enumerator->u.enumerator.values; bt_list_for_each_entry(iter, values, siblings) { - int64_t *target; + struct uori *target; if (iter->type != NODE_UNARY_EXPRESSION) { _BT_LOGE_NODE(iter, - "Wrong expression for enumeration field type label: " + "Wrong expression for enumeration field class label: " "node-type=%d, label=\"%s\"", iter->type, label); ret = -EINVAL; @@ -2105,15 +2135,18 @@ int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator, switch (iter->u.unary_expression.type) { case UNARY_SIGNED_CONSTANT: - *target = iter->u.unary_expression.u.signed_constant; + target->is_signed = true; + target->value.i = + iter->u.unary_expression.u.signed_constant; break; case UNARY_UNSIGNED_CONSTANT: - *target = (int64_t) + target->is_signed = false; + target->value.u = iter->u.unary_expression.u.unsigned_constant; break; default: _BT_LOGE_NODE(iter, - "Invalid enumeration field type entry: " + "Invalid enumeration field class entry: " "expecting constant signed or unsigned integer: " "node-type=%d, label=\"%s\"", iter->u.unary_expression.type, label); @@ -2123,7 +2156,7 @@ int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator, if (nr_vals > 1) { _BT_LOGE_NODE(iter, - "Invalid enumeration field type entry: label=\"%s\"", + "Invalid enumeration field class entry: label=\"%s\"", label); ret = -EINVAL; goto error; @@ -2140,25 +2173,26 @@ int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator, end = start; } - *last = end + 1; - - if (is_signed) { - ret = bt_ctf_field_type_enumeration_add_mapping(enum_decl, label, - start, end); + if (end.is_signed) { + last->value.i = end.value.i + 1; } else { - ret = bt_ctf_field_type_enumeration_add_mapping_unsigned(enum_decl, - label, (uint64_t) start, (uint64_t) end); + last->value.u = end.value.u + 1; } - if (ret) { - _BT_LOGE_NODE(enumerator, - "Cannot add mapping to enumeration field type: " - "label=\"%s\", ret=%d, " - "start-value-unsigned=%" PRIu64 ", " - "end-value-unsigned=%" PRIu64, label, ret, - (uint64_t) start, (uint64_t) end); - goto error; + + if (label[0] == '_') { + /* + * Strip the first underscore of any enumeration field + * class's label in case this enumeration FC is used as + * a variant FC tag later. The variant FC choice names + * could also start with `_`, in which case the prefix + * is removed, and it the resulting choice name needs to + * match tag labels. + */ + effective_label = &label[1]; } + ctf_field_class_enum_append_mapping(enum_decl, effective_label, + start.value.u, end.value.u); return 0; error: @@ -2167,107 +2201,92 @@ error: static int visit_enum_decl(struct ctx *ctx, const char *name, - struct ctf_node *container_type, - struct bt_list_head *enumerator_list, - int has_body, - struct bt_ctf_field_type **enum_decl) + 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; - _BT_CTF_FIELD_TYPE_INIT(integer_decl); + 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) { - _BT_CTF_FIELD_TYPE_INIT(enum_decl_copy); - if (!name) { - BT_LOGE_STR("Bodyless enumeration field type: missing name."); + BT_LOGE_STR("Bodyless enumeration field class: missing name."); ret = -EPERM; goto error; } *enum_decl = ctx_decl_scope_lookup_enum(ctx->current_scope, - name, -1); + name, -1, true); if (!*enum_decl) { - BT_LOGE("Cannot find enumeration field type: " + BT_LOGE("Cannot find enumeration field class: " "name=\"enum %s\"", name); ret = -EINVAL; goto error; } - - /* Make a copy of it */ - enum_decl_copy = bt_ctf_field_type_copy(*enum_decl); - if (!enum_decl_copy) { - BT_LOGE_STR("Cannot create copy of enumeration field type."); - ret = -EINVAL; - goto error; - } - - BT_PUT(*enum_decl); - BT_MOVE(*enum_decl, enum_decl_copy); } else { struct ctf_node *iter; - int64_t last_value = 0; + struct uori last_value = { + .is_signed = false, + .value.u = 0, + }; if (name) { - _BT_CTF_FIELD_TYPE_INIT(eenum_decl); - - eenum_decl = ctx_decl_scope_lookup_enum( - ctx->current_scope, name, 1); - if (eenum_decl) { - BT_PUT(eenum_decl); - BT_LOGE("Enumeration field type already declared in local scope: " + if (ctx_decl_scope_lookup_enum(ctx->current_scope, + name, 1, false)) { + BT_LOGE("Enumeration field class already declared in local scope: " "name=\"enum %s\"", name); ret = -EINVAL; goto error; } } - if (!container_type) { - integer_decl = ctx_decl_scope_lookup_alias( - ctx->current_scope, "int", -1); + if (!container_cls) { + integer_decl = (void *) ctx_decl_scope_lookup_alias( + ctx->current_scope, "int", -1, true); if (!integer_decl) { - BT_LOGE_STR("Cannot find implicit `int` field type alias for enumeration field type."); + BT_LOGE_STR("Cannot find implicit `int` field class alias for enumeration field class."); ret = -EINVAL; goto error; } } else { - ret = visit_type_declarator(ctx, container_type, - &qdummy_id, NULL, &integer_decl, NULL); + ret = visit_field_class_declarator(ctx, container_cls, + &qdummy_id, NULL, (void *) &integer_decl, + NULL); if (ret) { - assert(!integer_decl); + BT_ASSERT(!integer_decl); ret = -EINVAL; goto error; } } - assert(integer_decl); + BT_ASSERT(integer_decl); - if (!bt_ctf_field_type_is_integer(integer_decl)) { - BT_LOGE("Container field type for enumeration field type is not an integer field type: " - "ft-id=%s", - bt_ctf_field_type_id_string( - bt_ctf_field_type_get_type_id(integer_decl))); + if (integer_decl->base.base.type != CTF_FIELD_CLASS_TYPE_INT) { + BT_LOGE("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 = bt_ctf_field_type_enumeration_create(integer_decl); - if (!*enum_decl) { - BT_LOGE_STR("Cannot create enumeration field type."); - ret = -ENOMEM; - 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((void *) *enum_decl, + (void *) 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, - bt_ctf_field_type_integer_get_signed(integer_decl)); + &last_value); if (ret) { _BT_LOGE_NODE(iter, - "Cannot visit enumeration field type entry: " + "Cannot visit enumeration field class entry: " "ret=%d", ret); goto error; } @@ -2277,90 +2296,80 @@ int visit_enum_decl(struct ctx *ctx, const char *name, ret = ctx_decl_scope_register_enum(ctx->current_scope, name, *enum_decl); if (ret) { - BT_LOGE("Cannot register enumeration field type in declaration scope: " + BT_LOGE("Cannot register enumeration field class in declaration scope: " "ret=%d", ret); goto error; } } } - BT_PUT(integer_decl); - - return 0; + goto end; error: - BT_PUT(integer_decl); - BT_PUT(*enum_decl); + ctf_field_class_destroy((void *) *enum_decl); + *enum_decl = NULL; +end: + ctf_field_class_destroy((void *) integer_decl); + integer_decl = NULL; return ret; } static -int visit_type_specifier(struct ctx *ctx, - struct ctf_node *type_specifier_list, - struct bt_ctf_field_type **decl) +int visit_field_class_specifier(struct ctx *ctx, + struct ctf_node *cls_specifier_list, + struct ctf_field_class **decl) { int ret = 0; GString *str = NULL; - _BT_CTF_FIELD_TYPE_INIT(decl_copy); *decl = NULL; str = g_string_new(""); - ret = get_type_specifier_list_name(ctx, type_specifier_list, str); + ret = get_class_specifier_list_name(ctx, cls_specifier_list, str); if (ret) { - _BT_LOGE_NODE(type_specifier_list, - "Cannot get type specifier list's name: ret=%d", ret); + _BT_LOGE_NODE(cls_specifier_list, + "Cannot get field class specifier list's name: ret=%d", ret); goto error; } - *decl = ctx_decl_scope_lookup_alias(ctx->current_scope, str->str, -1); + *decl = ctx_decl_scope_lookup_alias(ctx->current_scope, str->str, -1, + true); if (!*decl) { - _BT_LOGE_NODE(type_specifier_list, - "Cannot find type alias: name=\"%s\"", str->str); - ret = -EINVAL; - goto error; - } - - /* Make a copy of the type declaration */ - decl_copy = bt_ctf_field_type_copy(*decl); - if (!decl_copy) { - _BT_LOGE_NODE(type_specifier_list, - "Cannot create field type copy."); + _BT_LOGE_NODE(cls_specifier_list, + "Cannot find field class alias: name=\"%s\"", str->str); ret = -EINVAL; goto error; } - BT_MOVE(*decl, decl_copy); - (void) g_string_free(str, TRUE); - str = NULL; - - return 0; + goto end; error: + ctf_field_class_destroy(*decl); + *decl = NULL; + +end: if (str) { - (void) g_string_free(str, TRUE); + g_string_free(str, TRUE); } - BT_PUT(*decl); - return ret; } static int visit_integer_decl(struct ctx *ctx, - struct bt_list_head *expressions, - struct bt_ctf_field_type **integer_decl) + 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 bt_ctf_clock_class *mapped_clock = NULL; - enum bt_ctf_string_encoding encoding = BT_CTF_STRING_ENCODING_NONE; - enum bt_ctf_integer_base base = BT_CTF_INTEGER_BASE_DECIMAL; - enum bt_ctf_byte_order byte_order = - bt_ctf_trace_get_native_byte_order(ctx->trace); + struct bt_clock_class *mapped_clock_class = NULL; + enum ctf_encoding encoding = CTF_ENCODING_NONE; + enum 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; @@ -2384,7 +2393,7 @@ int visit_integer_decl(struct ctx *ctx, if (!strcmp(left->u.unary_expression.u.string, "signed")) { if (_IS_SET(&set, _INTEGER_SIGNED_SET)) { _BT_LOGE_DUP_ATTR(left, "signed", - "integer field type"); + "integer field class"); ret = -EPERM; goto error; } @@ -2392,7 +2401,7 @@ int visit_integer_decl(struct ctx *ctx, signedness = get_boolean(right); if (signedness < 0) { _BT_LOGE_NODE(right, - "Invalid boolean value for integer field type's `signed` attribute: " + "Invalid boolean value for integer field class's `signed` attribute: " "ret=%d", ret); ret = -EINVAL; goto error; @@ -2403,15 +2412,15 @@ int visit_integer_decl(struct ctx *ctx, "byte_order")) { if (_IS_SET(&set, _INTEGER_BYTE_ORDER_SET)) { _BT_LOGE_DUP_ATTR(left, "byte_order", - "integer field type"); + "integer field class"); ret = -EPERM; goto error; } byte_order = get_real_byte_order(ctx, right); - if (byte_order == BT_CTF_BYTE_ORDER_UNKNOWN) { + if (byte_order == -1) { _BT_LOGE_NODE(right, - "Invalid `byte_order` attribute in integer field type: " + "Invalid `byte_order` attribute in integer field class: " "ret=%d", ret); ret = -EINVAL; goto error; @@ -2421,7 +2430,7 @@ int visit_integer_decl(struct ctx *ctx, } else if (!strcmp(left->u.unary_expression.u.string, "size")) { if (_IS_SET(&set, _INTEGER_SIZE_SET)) { _BT_LOGE_DUP_ATTR(left, "size", - "integer field type"); + "integer field class"); ret = -EPERM; goto error; } @@ -2429,7 +2438,7 @@ int visit_integer_decl(struct ctx *ctx, if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { _BT_LOGE_NODE(right, - "Invalid `size` attribute in integer field type: " + "Invalid `size` attribute in integer field class: " "expecting unsigned constant integer: " "node-type=%d", right->u.unary_expression.type); @@ -2440,14 +2449,14 @@ int visit_integer_decl(struct ctx *ctx, size = right->u.unary_expression.u.unsigned_constant; if (size == 0) { _BT_LOGE_NODE(right, - "Invalid `size` attribute in integer field type: " + "Invalid `size` attribute in integer field class: " "expecting positive constant integer: " "size=%" PRIu64, size); ret = -EINVAL; goto error; } else if (size > 64) { _BT_LOGE_NODE(right, - "Invalid `size` attribute in integer field type: " + "Invalid `size` attribute in integer field class: " "integer fields over 64 bits are not supported as of this version: " "size=%" PRIu64, size); ret = -EINVAL; @@ -2459,7 +2468,7 @@ int visit_integer_decl(struct ctx *ctx, "align")) { if (_IS_SET(&set, _INTEGER_ALIGN_SET)) { _BT_LOGE_DUP_ATTR(left, "align", - "integer field type"); + "integer field class"); ret = -EPERM; goto error; } @@ -2467,7 +2476,7 @@ int visit_integer_decl(struct ctx *ctx, if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { _BT_LOGE_NODE(right, - "Invalid `align` attribute in integer field type: " + "Invalid `align` attribute in integer field class: " "expecting unsigned constant integer: " "node-type=%d", right->u.unary_expression.type); @@ -2479,7 +2488,7 @@ int visit_integer_decl(struct ctx *ctx, right->u.unary_expression.u.unsigned_constant; if (!is_align_valid(alignment)) { _BT_LOGE_NODE(right, - "Invalid `align` attribute in integer field type: " + "Invalid `align` attribute in integer field class: " "expecting power of two: " "align=%" PRIu64, alignment); ret = -EINVAL; @@ -2490,7 +2499,7 @@ int visit_integer_decl(struct ctx *ctx, } else if (!strcmp(left->u.unary_expression.u.string, "base")) { if (_IS_SET(&set, _INTEGER_BASE_SET)) { _BT_LOGE_DUP_ATTR(left, "base", - "integer field type"); + "integer field class"); ret = -EPERM; goto error; } @@ -2503,20 +2512,20 @@ int visit_integer_decl(struct ctx *ctx, switch (constant) { case 2: - base = BT_CTF_INTEGER_BASE_BINARY; + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY; break; case 8: - base = BT_CTF_INTEGER_BASE_OCTAL; + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL; break; case 10: - base = BT_CTF_INTEGER_BASE_DECIMAL; + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; break; case 16: - base = BT_CTF_INTEGER_BASE_HEXADECIMAL; + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL; break; default: _BT_LOGE_NODE(right, - "Invalid `base` attribute in integer field type: " + "Invalid `base` attribute in integer field class: " "base=%" PRIu64, right->u.unary_expression.u.unsigned_constant); ret = -EINVAL; @@ -2530,7 +2539,7 @@ int visit_integer_decl(struct ctx *ctx, &expression->u.ctf_expression.right); if (!s_right) { _BT_LOGE_NODE(right, - "Unexpected unary expression for integer field type's `base` attribute."); + "Unexpected unary expression for integer field class's `base` attribute."); ret = -EINVAL; goto error; } @@ -2540,23 +2549,23 @@ int visit_integer_decl(struct ctx *ctx, !strcmp(s_right, "d") || !strcmp(s_right, "i") || !strcmp(s_right, "u")) { - base = BT_CTF_INTEGER_BASE_DECIMAL; + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; } else if (!strcmp(s_right, "hexadecimal") || !strcmp(s_right, "hex") || !strcmp(s_right, "x") || !strcmp(s_right, "X") || !strcmp(s_right, "p")) { - base = BT_CTF_INTEGER_BASE_HEXADECIMAL; + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL; } else if (!strcmp(s_right, "octal") || !strcmp(s_right, "oct") || !strcmp(s_right, "o")) { - base = BT_CTF_INTEGER_BASE_OCTAL; + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL; } else if (!strcmp(s_right, "binary") || !strcmp(s_right, "b")) { - base = BT_CTF_INTEGER_BASE_BINARY; + base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY; } else { _BT_LOGE_NODE(right, - "Unexpected unary expression for integer field type's `base` attribute: " + "Unexpected unary expression for integer field class's `base` attribute: " "base=\"%s\"", s_right); g_free(s_right); ret = -EINVAL; @@ -2568,7 +2577,7 @@ int visit_integer_decl(struct ctx *ctx, } default: _BT_LOGE_NODE(right, - "Invalid `base` attribute in integer field type: " + "Invalid `base` attribute in integer field class: " "expecting unsigned constant integer or unary string."); ret = -EINVAL; goto error; @@ -2581,14 +2590,14 @@ int visit_integer_decl(struct ctx *ctx, if (_IS_SET(&set, _INTEGER_ENCODING_SET)) { _BT_LOGE_DUP_ATTR(left, "encoding", - "integer field type"); + "integer field class"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_STRING) { _BT_LOGE_NODE(right, - "Invalid `encoding` attribute in integer field type: " + "Invalid `encoding` attribute in integer field class: " "expecting unary string."); ret = -EINVAL; goto error; @@ -2598,7 +2607,7 @@ int visit_integer_decl(struct ctx *ctx, &expression->u.ctf_expression.right); if (!s_right) { _BT_LOGE_NODE(right, - "Unexpected unary expression for integer field type's `encoding` attribute."); + "Unexpected unary expression for integer field class's `encoding` attribute."); ret = -EINVAL; goto error; } @@ -2606,16 +2615,15 @@ int visit_integer_decl(struct ctx *ctx, if (!strcmp(s_right, "UTF8") || !strcmp(s_right, "utf8") || !strcmp(s_right, "utf-8") || - !strcmp(s_right, "UTF-8")) { - encoding = BT_CTF_STRING_ENCODING_UTF8; - } else if (!strcmp(s_right, "ASCII") || + !strcmp(s_right, "UTF-8") || + !strcmp(s_right, "ASCII") || !strcmp(s_right, "ascii")) { - encoding = BT_CTF_STRING_ENCODING_ASCII; + encoding = CTF_ENCODING_UTF8; } else if (!strcmp(s_right, "none")) { - encoding = BT_CTF_STRING_ENCODING_NONE; + encoding = CTF_ENCODING_NONE; } else { _BT_LOGE_NODE(right, - "Invalid `encoding` attribute in integer field type: " + "Invalid `encoding` attribute in integer field class: " "unknown encoding: encoding=\"%s\"", s_right); g_free(s_right); @@ -2630,14 +2638,14 @@ int visit_integer_decl(struct ctx *ctx, if (_IS_SET(&set, _INTEGER_MAP_SET)) { _BT_LOGE_DUP_ATTR(left, "map", - "integer field type"); + "integer field class"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_STRING) { _BT_LOGE_NODE(right, - "Invalid `map` attribute in integer field type: " + "Invalid `map` attribute in integer field class: " "expecting unary string."); ret = -EINVAL; goto error; @@ -2652,13 +2660,13 @@ int visit_integer_decl(struct ctx *ctx, if (!s_right) { _BT_LOGE_NODE(right, - "Unexpected unary expression for integer field type's `map` attribute."); + "Unexpected unary expression for integer field class's `map` attribute."); ret = -EINVAL; goto error; } _BT_LOGE_NODE(right, - "Invalid `map` attribute in integer field type: " + "Invalid `map` attribute in integer field class: " "cannot find clock class at this point: name=\"%s\"", s_right); _SET(&set, _INTEGER_MAP_SET); @@ -2666,11 +2674,12 @@ int visit_integer_decl(struct ctx *ctx, continue; } - mapped_clock = bt_ctf_trace_get_clock_class_by_name( - ctx->trace, clock_name); - if (!mapped_clock) { + mapped_clock_class = + ctf_trace_class_borrow_clock_class_by_name( + ctx->ctf_tc, clock_name); + if (!mapped_clock_class) { _BT_LOGE_NODE(right, - "Invalid `map` attribute in integer field type: " + "Invalid `map` attribute in integer field class: " "cannot find clock class at this point: name=\"%s\"", clock_name); ret = -EINVAL; @@ -2680,14 +2689,14 @@ int visit_integer_decl(struct ctx *ctx, _SET(&set, _INTEGER_MAP_SET); } else { _BT_LOGW_NODE(left, - "Unknown attribute in integer field type: " + "Unknown attribute in integer field class: " "attr-name=\"%s\"", left->u.unary_expression.u.string); } } if (!_IS_SET(&set, _INTEGER_SIZE_SET)) { - BT_LOGE_STR("Missing `size` attribute in integer field type."); + BT_LOGE_STR("Missing `size` attribute in integer field class."); ret = -EPERM; goto error; } @@ -2702,57 +2711,34 @@ int visit_integer_decl(struct ctx *ctx, } } - *integer_decl = bt_ctf_field_type_integer_create((unsigned int) size); - if (!*integer_decl) { - BT_LOGE_STR("Cannot create integer field type."); - ret = -ENOMEM; - goto error; - } - - ret = bt_ctf_field_type_integer_set_signed(*integer_decl, signedness); - ret |= bt_ctf_field_type_integer_set_base(*integer_decl, base); - ret |= bt_ctf_field_type_integer_set_encoding(*integer_decl, encoding); - ret |= bt_ctf_field_type_set_alignment(*integer_decl, - (unsigned int) alignment); - ret |= bt_ctf_field_type_set_byte_order(*integer_decl, byte_order); - - if (mapped_clock) { - /* Move clock */ - ret |= bt_ctf_field_type_integer_set_mapped_clock_class( - *integer_decl, mapped_clock); - bt_put(mapped_clock); - mapped_clock = NULL; - } - - if (ret) { - BT_LOGE_STR("Cannot configure integer field type."); - ret = -EINVAL; - goto error; - } - + *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; + bt_object_get_ref((*integer_decl)->mapped_clock_class); return 0; error: - if (mapped_clock) { - bt_put(mapped_clock); - } - - BT_PUT(*integer_decl); - + ctf_field_class_destroy((void *) *integer_decl); + *integer_decl = NULL; return ret; } static int visit_floating_point_number_decl(struct ctx *ctx, - struct bt_list_head *expressions, - struct bt_ctf_field_type **float_decl) + 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 bt_ctf_byte_order byte_order = - bt_ctf_trace_get_native_byte_order(ctx->trace); + enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order; *float_decl = NULL; @@ -2776,15 +2762,15 @@ int visit_floating_point_number_decl(struct ctx *ctx, if (!strcmp(left->u.unary_expression.u.string, "byte_order")) { if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) { _BT_LOGE_DUP_ATTR(left, "byte_order", - "floating point number field type"); + "floating point number field class"); ret = -EPERM; goto error; } byte_order = get_real_byte_order(ctx, right); - if (byte_order == BT_CTF_BYTE_ORDER_UNKNOWN) { + if (byte_order == -1) { _BT_LOGE_NODE(right, - "Invalid `byte_order` attribute in floating point number field type: " + "Invalid `byte_order` attribute in floating point number field class: " "ret=%d", ret); ret = -EINVAL; goto error; @@ -2795,7 +2781,7 @@ int visit_floating_point_number_decl(struct ctx *ctx, "exp_dig")) { if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) { _BT_LOGE_DUP_ATTR(left, "exp_dig", - "floating point number field type"); + "floating point number field class"); ret = -EPERM; goto error; } @@ -2803,7 +2789,7 @@ int visit_floating_point_number_decl(struct ctx *ctx, if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { _BT_LOGE_NODE(right, - "Invalid `exp_dig` attribute in floating point number field type: " + "Invalid `exp_dig` attribute in floating point number field class: " "expecting unsigned constant integer: " "node-type=%d", right->u.unary_expression.type); @@ -2817,7 +2803,7 @@ int visit_floating_point_number_decl(struct ctx *ctx, "mant_dig")) { if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) { _BT_LOGE_DUP_ATTR(left, "mant_dig", - "floating point number field type"); + "floating point number field class"); ret = -EPERM; goto error; } @@ -2825,7 +2811,7 @@ int visit_floating_point_number_decl(struct ctx *ctx, if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { _BT_LOGE_NODE(right, - "Invalid `mant_dig` attribute in floating point number field type: " + "Invalid `mant_dig` attribute in floating point number field class: " "expecting unsigned constant integer: " "node-type=%d", right->u.unary_expression.type); @@ -2840,7 +2826,7 @@ int visit_floating_point_number_decl(struct ctx *ctx, "align")) { if (_IS_SET(&set, _FLOAT_ALIGN_SET)) { _BT_LOGE_DUP_ATTR(left, "align", - "floating point number field type"); + "floating point number field class"); ret = -EPERM; goto error; } @@ -2848,7 +2834,7 @@ int visit_floating_point_number_decl(struct ctx *ctx, if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { _BT_LOGE_NODE(right, - "Invalid `align` attribute in floating point number field type: " + "Invalid `align` attribute in floating point number field class: " "expecting unsigned constant integer: " "node-type=%d", right->u.unary_expression.type); @@ -2861,7 +2847,7 @@ int visit_floating_point_number_decl(struct ctx *ctx, if (!is_align_valid(alignment)) { _BT_LOGE_NODE(right, - "Invalid `align` attribute in floating point number field type: " + "Invalid `align` attribute in floating point number field class: " "expecting power of two: " "align=%" PRIu64, alignment); ret = -EINVAL; @@ -2871,20 +2857,38 @@ int visit_floating_point_number_decl(struct ctx *ctx, _SET(&set, _FLOAT_ALIGN_SET); } else { _BT_LOGW_NODE(left, - "Unknown attribute in floating point number field type: " + "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_LOGE_STR("Missing `mant_dig` attribute in floating point number field type."); + BT_LOGE_STR("Missing `mant_dig` attribute in floating point number field class."); ret = -EPERM; goto error; } if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) { - BT_LOGE_STR("Missing `exp_dig` attribute in floating point number field type."); + BT_LOGE_STR("Missing `exp_dig` attribute in floating point number field class."); + ret = -EPERM; + goto error; + } + + if (mant_dig != 24 && mant_dig != 53) { + BT_LOGE_STR("`mant_dig` attribute: expecting 24 or 53."); + ret = -EPERM; + goto error; + } + + if (mant_dig == 24 && exp_dig != 8) { + BT_LOGE_STR("`exp_dig` attribute: expecting 8 because `mant_dig` is 24."); + ret = -EPERM; + goto error; + } + + if (mant_dig == 53 && exp_dig != 11) { + BT_LOGE_STR("`exp_dig` attribute: expecting 11 because `mant_dig` is 53."); ret = -EPERM; goto error; } @@ -2899,42 +2903,28 @@ int visit_floating_point_number_decl(struct ctx *ctx, } } - *float_decl = bt_ctf_field_type_floating_point_create(); - if (!*float_decl) { - BT_LOGE_STR("Cannot create floating point number field type."); - ret = -ENOMEM; - goto error; - } - - ret = bt_ctf_field_type_floating_point_set_exponent_digits( - *float_decl, exp_dig); - ret |= bt_ctf_field_type_floating_point_set_mantissa_digits( - *float_decl, mant_dig); - ret |= bt_ctf_field_type_set_byte_order(*float_decl, byte_order); - ret |= bt_ctf_field_type_set_alignment(*float_decl, alignment); - if (ret) { - BT_LOGE_STR("Cannot configure floating point number field type."); - ret = -EINVAL; - goto error; - } - + *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: - BT_PUT(*float_decl); - + ctf_field_class_destroy((void *) *float_decl); + *float_decl = NULL; return ret; } static int visit_string_decl(struct ctx *ctx, - struct bt_list_head *expressions, - struct bt_ctf_field_type **string_decl) + struct bt_list_head *expressions, + struct ctf_field_class_string **string_decl) { int set = 0; int ret = 0; struct ctf_node *expression; - enum bt_ctf_string_encoding encoding = BT_CTF_STRING_ENCODING_UTF8; + enum ctf_encoding encoding = CTF_ENCODING_UTF8; *string_decl = NULL; @@ -2960,14 +2950,14 @@ int visit_string_decl(struct ctx *ctx, if (_IS_SET(&set, _STRING_ENCODING_SET)) { _BT_LOGE_DUP_ATTR(left, "encoding", - "string field type"); + "string field class"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_STRING) { _BT_LOGE_NODE(right, - "Invalid `encoding` attribute in string field type: " + "Invalid `encoding` attribute in string field class: " "expecting unary string."); ret = -EINVAL; goto error; @@ -2977,7 +2967,7 @@ int visit_string_decl(struct ctx *ctx, &expression->u.ctf_expression.right); if (!s_right) { _BT_LOGE_NODE(right, - "Unexpected unary expression for string field type's `encoding` attribute."); + "Unexpected unary expression for string field class's `encoding` attribute."); ret = -EINVAL; goto error; } @@ -2985,16 +2975,15 @@ int visit_string_decl(struct ctx *ctx, if (!strcmp(s_right, "UTF8") || !strcmp(s_right, "utf8") || !strcmp(s_right, "utf-8") || - !strcmp(s_right, "UTF-8")) { - encoding = BT_CTF_STRING_ENCODING_UTF8; - } else if (!strcmp(s_right, "ASCII") || + !strcmp(s_right, "UTF-8") || + !strcmp(s_right, "ASCII") || !strcmp(s_right, "ascii")) { - encoding = BT_CTF_STRING_ENCODING_ASCII; + encoding = CTF_ENCODING_UTF8; } else if (!strcmp(s_right, "none")) { - encoding = BT_CTF_STRING_ENCODING_NONE; + encoding = CTF_ENCODING_NONE; } else { _BT_LOGE_NODE(right, - "Invalid `encoding` attribute in string field type: " + "Invalid `encoding` attribute in string field class: " "unknown encoding: encoding=\"%s\"", s_right); g_free(s_right); @@ -3006,38 +2995,26 @@ int visit_string_decl(struct ctx *ctx, _SET(&set, _STRING_ENCODING_SET); } else { _BT_LOGW_NODE(left, - "Unknown attribute in string field type: " + "Unknown attribute in string field class: " "attr-name=\"%s\"", left->u.unary_expression.u.string); } } - *string_decl = bt_ctf_field_type_string_create(); - if (!*string_decl) { - BT_LOGE_STR("Cannot create string field type."); - ret = -ENOMEM; - goto error; - } - - ret = bt_ctf_field_type_string_set_encoding(*string_decl, encoding); - if (ret) { - BT_LOGE_STR("Cannot configure string field type."); - ret = -EINVAL; - goto error; - } - - return 0; + *string_decl = ctf_field_class_string_create(); + BT_ASSERT(*string_decl); + (*string_decl)->encoding = encoding; + return 0; error: - BT_PUT(*string_decl); - + ctf_field_class_destroy((void *) *string_decl); + *string_decl = NULL; return ret; } static -int visit_type_specifier_list(struct ctx *ctx, - struct ctf_node *ts_list, - struct bt_ctf_field_type **decl) +int visit_field_class_specifier_list(struct ctx *ctx, + struct ctf_node *ts_list, struct ctf_field_class **decl) { int ret = 0; struct ctf_node *first, *node; @@ -3051,7 +3028,7 @@ int visit_type_specifier_list(struct ctx *ctx, goto error; } - first = _BT_LIST_FIRST_ENTRY(&ts_list->u.type_specifier_list.head, + first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head, struct ctf_node, siblings); if (first->type != NODE_TYPE_SPECIFIER) { _BT_LOGE_NODE(first, @@ -3060,30 +3037,30 @@ int visit_type_specifier_list(struct ctx *ctx, goto error; } - node = first->u.type_specifier.node; + node = first->u.field_class_specifier.node; - switch (first->u.type_specifier.type) { + switch (first->u.field_class_specifier.type) { case TYPESPEC_INTEGER: ret = visit_integer_decl(ctx, &node->u.integer.expressions, - decl); + (void *) decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; case TYPESPEC_FLOATING_POINT: ret = visit_floating_point_number_decl(ctx, - &node->u.floating_point.expressions, decl); + &node->u.floating_point.expressions, (void *) decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; case TYPESPEC_STRING: ret = visit_string_decl(ctx, - &node->u.string.expressions, decl); + &node->u.string.expressions, (void *) decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; @@ -3091,9 +3068,9 @@ int visit_type_specifier_list(struct ctx *ctx, ret = visit_struct_decl(ctx, node->u._struct.name, &node->u._struct.declaration_list, node->u._struct.has_body, - &node->u._struct.min_align, decl); + &node->u._struct.min_align, (void *) decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; @@ -3101,19 +3078,19 @@ int visit_type_specifier_list(struct ctx *ctx, ret = visit_variant_decl(ctx, node->u.variant.name, node->u.variant.choice, &node->u.variant.declaration_list, - node->u.variant.has_body, decl); + node->u.variant.has_body, (void *) decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; case TYPESPEC_ENUM: ret = visit_enum_decl(ctx, node->u._enum.enum_id, - node->u._enum.container_type, + node->u._enum.container_field_class, &node->u._enum.enumerator_list, - node->u._enum.has_body, decl); + node->u._enum.has_body, (void *) decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; @@ -3131,58 +3108,56 @@ int visit_type_specifier_list(struct ctx *ctx, case TYPESPEC_IMAGINARY: case TYPESPEC_CONST: case TYPESPEC_ID_TYPE: - ret = visit_type_specifier(ctx, ts_list, decl); + ret = visit_field_class_specifier(ctx, ts_list, decl); if (ret) { _BT_LOGE_NODE(first, - "Cannot visit type specifier: ret=%d", + "Cannot visit field class specifier: ret=%d", ret); - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; default: _BT_LOGE_NODE(first, - "Unexpected type specifier type: node-type=%d", - first->u.type_specifier.type); + "Unexpected field class specifier type: node-type=%d", + first->u.field_class_specifier.type); ret = -EINVAL; goto error; } - assert(*decl); - + BT_ASSERT(*decl); return 0; error: - BT_PUT(*decl); - + ctf_field_class_destroy((void *) *decl); + *decl = NULL; return ret; } static int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, - struct bt_ctf_event_class *event_class, int64_t *stream_id, - int *set) + struct ctf_event_class *event_class, uint64_t *stream_id, + int *set) { int ret = 0; char *left = NULL; - _BT_CTF_FIELD_TYPE_INIT(decl); switch (node->type) { case NODE_TYPEDEF: - ret = visit_typedef(ctx, node->u._typedef.type_specifier_list, - &node->u._typedef.type_declarators); + 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_LOGE_NODE(node, - "Cannot add type definition found in event class."); + "Cannot add field class found in event class."); goto error; } break; case NODE_TYPEALIAS: - ret = visit_typealias(ctx, node->u.typealias.target, - node->u.typealias.alias); + ret = visit_field_class_alias(ctx, node->u.field_class_alias.target, + node->u.field_class_alias.alias); if (ret) { _BT_LOGE_NODE(node, - "Cannot add type alias found in event class."); + "Cannot add field class alias found in event class."); goto error; } break; @@ -3198,19 +3173,17 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, if (!strcmp(left, "name")) { /* This is already known at this stage */ if (_IS_SET(set, _EVENT_NAME_SET)) { - _BT_LOGE_DUP_ATTR(node, "name", - "event class"); + _BT_LOGE_DUP_ATTR(node, "name", "event class"); ret = -EPERM; goto error; } _SET(set, _EVENT_NAME_SET); } else if (!strcmp(left, "id")) { - int64_t id; + int64_t id = -1; if (_IS_SET(set, _EVENT_ID_SET)) { - _BT_LOGE_DUP_ATTR(node, "id", - "event class"); + _BT_LOGE_DUP_ATTR(node, "id", "event class"); ret = -EPERM; goto error; } @@ -3225,14 +3198,7 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - ret = bt_ctf_event_class_set_id(event_class, id); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot set event class's ID: " - "id=%" PRId64, id); - goto error; - } - + event_class->id = id; _SET(set, _EVENT_ID_SET); } else if (!strcmp(left, "stream_id")) { if (_IS_SET(set, _EVENT_STREAM_ID_SET)) { @@ -3243,7 +3209,8 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, } ret = get_unary_unsigned(&node->u.ctf_expression.right, - (uint64_t *) stream_id); + stream_id); + /* * Only read "stream_id" if get_unary_unsigned() * succeeded. @@ -3264,27 +3231,18 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - ret = visit_type_specifier_list(ctx, + ret = visit_field_class_specifier_list(ctx, _BT_LIST_FIRST_ENTRY( &node->u.ctf_expression.right, struct ctf_node, siblings), - &decl); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot create event class's context field type."); - goto error; - } - - assert(decl); - ret = bt_ctf_event_class_set_context_type( - event_class, decl); - BT_PUT(decl); + &event_class->spec_context_fc); if (ret) { _BT_LOGE_NODE(node, - "Cannot set event class's context field type."); + "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")) { if (_IS_SET(set, _EVENT_FIELDS_SET)) { @@ -3294,34 +3252,24 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - ret = visit_type_specifier_list(ctx, + ret = visit_field_class_specifier_list(ctx, _BT_LIST_FIRST_ENTRY( &node->u.ctf_expression.right, struct ctf_node, siblings), - &decl); + &event_class->payload_fc); if (ret) { _BT_LOGE_NODE(node, - "Cannot create event class's payload field type."); - goto error; - } - - assert(decl); - ret = bt_ctf_event_class_set_payload_type( - event_class, decl); - BT_PUT(decl); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot set event class's payload field type."); + "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")) { uint64_t loglevel_value; - const char *loglevel_str; - struct bt_value *value_obj, *str_obj; + enum bt_event_class_log_level log_level = -1; - if (_IS_SET(set, _EVENT_LOGLEVEL_SET)) { + if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) { _BT_LOGE_DUP_ATTR(node, "loglevel", "event class"); ret = -EPERM; @@ -3336,39 +3284,65 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, ret = -EINVAL; goto error; } - value_obj = bt_value_integer_create_init(loglevel_value); - if (!value_obj) { - _BT_LOGE_NODE(node, - "Cannot create integer value object."); - ret = -ENOMEM; - goto error; - } - if (bt_ctf_event_class_set_attribute(event_class, - "loglevel", value_obj) != BT_VALUE_STATUS_OK) { - _BT_LOGE_NODE(node, - "Cannot set event class's `loglevel` attribute."); - ret = -EINVAL; - bt_put(value_obj); - 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: + _BT_LOGW_NODE(node, "Not setting event class's log level because its value is unknown: " + "log-level=%" PRIu64, loglevel_value); } - loglevel_str = print_loglevel(loglevel_value); - if (loglevel_str) { - str_obj = bt_value_string_create_init(loglevel_str); - if (bt_ctf_event_class_set_attribute(event_class, - "loglevel_string", str_obj) != BT_VALUE_STATUS_OK) { - _BT_LOGE_NODE(node, - "Cannot set event class's `loglevel_string` attribute."); - ret = -EINVAL; - bt_put(str_obj); - goto error; - } - bt_put(str_obj); + + if (log_level != -1) { + event_class->log_level = log_level; } - bt_put(value_obj); - _SET(set, _EVENT_LOGLEVEL_SET); + + _SET(set, _EVENT_LOG_LEVEL_SET); } else if (!strcmp(left, "model.emf.uri")) { char *right; - struct bt_value *str_obj; if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) { _BT_LOGE_DUP_ATTR(node, "model.emf.uri", @@ -3386,16 +3360,14 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - str_obj = bt_value_string_create_init(right); - if (bt_ctf_event_class_set_attribute(event_class, - "model.emf.uri", str_obj) != BT_VALUE_STATUS_OK) { - _BT_LOGE_NODE(node, - "Cannot set event class's `model.emf.uri` attribute."); - ret = -EINVAL; - bt_put(str_obj); - goto error; + if (strlen(right) == 0) { + _BT_LOGW_NODE(node, + "Not setting event class's EMF URI because it's empty."); + } else { + g_string_assign(event_class->emf_uri, + right); } - bt_put(str_obj); + g_free(right); _SET(set, _EVENT_MODEL_EMF_URI_SET); } else { @@ -3413,15 +3385,14 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - return 0; + goto end; error: if (left) { g_free(left); } - BT_PUT(decl); - +end: return ret; } @@ -3467,93 +3438,6 @@ char *get_event_decl_name(struct ctx *ctx, struct ctf_node *node) error: g_free(left); - - return NULL; -} - -static -int reset_event_decl_types(struct ctx *ctx, - struct bt_ctf_event_class *event_class) -{ - int ret = 0; - - /* Context type. */ - ret = bt_ctf_event_class_set_context_type(event_class, NULL); - if (ret) { - BT_LOGE("Cannot reset initial event class's context field type: " - "event-name=\"%s\"", - bt_ctf_event_class_get_name(event_class)); - goto end; - } - - /* Event payload. */ - ret = bt_ctf_event_class_set_payload_type(event_class, NULL); - if (ret) { - BT_LOGE("Cannot reset initial event class's payload field type: " - "event-name=\"%s\"", - bt_ctf_event_class_get_name(event_class)); - goto end; - } -end: - return ret; -} - -static -int reset_stream_decl_types(struct ctx *ctx, - struct bt_ctf_stream_class *stream_class) -{ - int ret = 0; - - /* Packet context. */ - ret = bt_ctf_stream_class_set_packet_context_type(stream_class, NULL); - if (ret) { - BT_LOGE_STR("Cannot reset initial stream class's packet context field type."); - goto end; - } - - /* Event header. */ - ret = bt_ctf_stream_class_set_event_header_type(stream_class, NULL); - if (ret) { - BT_LOGE_STR("Cannot reset initial stream class's event header field type."); - goto end; - } - - /* Event context. */ - ret = bt_ctf_stream_class_set_event_context_type(stream_class, NULL); - if (ret) { - BT_LOGE_STR("Cannot reset initial stream class's event context field type."); - goto end; - } -end: - return ret; -} - -static -struct bt_ctf_stream_class *create_reset_stream_class(struct ctx *ctx) -{ - int ret; - struct bt_ctf_stream_class *stream_class; - - stream_class = bt_ctf_stream_class_create_empty(NULL); - if (!stream_class) { - BT_LOGE_STR("Cannot create empty stream class."); - goto error; - } - - /* - * Set packet context, event header, and event context to NULL to - * override the default ones. - */ - ret = reset_stream_decl_types(ctx, stream_class); - if (ret) { - goto error; - } - - return stream_class; - -error: - BT_PUT(stream_class); - return NULL; } @@ -3562,13 +3446,11 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node) { int ret = 0; int set = 0; - int64_t event_id; struct ctf_node *iter; - int64_t stream_id = -1; + uint64_t stream_id = 0; char *event_name = NULL; - struct bt_ctf_event_class *event_class = NULL; - struct bt_ctf_event_class *eevent_class; - struct bt_ctf_stream_class *stream_class = 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; @@ -3585,25 +3467,10 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node) goto error; } - event_class = bt_ctf_event_class_create(event_name); - - /* - * Unset context and fields to override the default ones. - */ - ret = reset_event_decl_types(ctx, event_class); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot reset event class's field types: " - "ret=%d", ret); - goto error; - } - - ret = ctx_push_scope(ctx); - if (ret) { - BT_LOGE_STR("Cannot push scope."); - 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) { @@ -3617,60 +3484,25 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node) } if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) { - GList *keys = NULL; - struct bt_ctf_stream_class *new_stream_class; - size_t stream_class_count = - g_hash_table_size(ctx->stream_classes) + - bt_ctf_trace_get_stream_class_count(ctx->trace); - /* * Allow missing stream_id if there is only a single * stream class. */ - switch (stream_class_count) { + switch (ctx->ctf_tc->stream_classes->len) { case 0: /* Create implicit stream class if there's none */ - new_stream_class = create_reset_stream_class(ctx); - if (!new_stream_class) { - _BT_LOGE_NODE(node, - "Cannot create empty stream class."); - ret = -EINVAL; - goto error; - } - - ret = bt_ctf_stream_class_set_id(new_stream_class, 0); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot set stream class's ID: " - "id=0, ret=%d", ret); - BT_PUT(new_stream_class); - goto error; - } - stream_id = 0; - - /* Move reference to visitor's context */ - g_hash_table_insert(ctx->stream_classes, - (gpointer) stream_id, new_stream_class); - new_stream_class = NULL; + 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); + stream_class = stream_class; break; case 1: /* Single stream class: get its ID */ - if (g_hash_table_size(ctx->stream_classes) == 1) { - keys = g_hash_table_get_keys(ctx->stream_classes); - stream_id = (int64_t) keys->data; - g_list_free(keys); - } else { - assert(bt_ctf_trace_get_stream_class_count( - ctx->trace) == 1); - stream_class = - bt_ctf_trace_get_stream_class_by_index( - ctx->trace, 0); - assert(stream_class); - stream_id = bt_ctf_stream_class_get_id( - stream_class); - BT_PUT(stream_class); - } + stream_class = ctx->ctf_tc->stream_classes->pdata[0]; + stream_id = stream_class->id; break; default: _BT_LOGE_NODE(node, @@ -3680,15 +3512,10 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node) } } - assert(stream_id >= 0); - /* We have the stream ID now; get the stream class if found */ - stream_class = g_hash_table_lookup(ctx->stream_classes, - (gpointer) stream_id); - bt_get(stream_class); if (!stream_class) { - stream_class = bt_ctf_trace_get_stream_class_by_id(ctx->trace, - stream_id); + stream_class = ctf_trace_class_borrow_stream_class_by_id( + ctx->ctf_tc, stream_id); if (!stream_class) { _BT_LOGE_NODE(node, "Cannot find stream class at this point: " @@ -3698,12 +3525,11 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node) } } - assert(stream_class); + BT_ASSERT(stream_class); if (!_IS_SET(&set, _EVENT_ID_SET)) { /* Allow only one event without ID per stream */ - if (bt_ctf_stream_class_get_event_class_count(stream_class) != - 0) { + if (stream_class->event_classes->len != 0) { _BT_LOGE_NODE(node, "Missing `id` attribute in event class."); ret = -EPERM; @@ -3711,141 +3537,195 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node) } /* Automatic ID */ - ret = bt_ctf_event_class_set_id(event_class, 0); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot set event class's ID: id=0, ret=%d", - ret); - goto error; - } - } - - event_id = bt_ctf_event_class_get_id(event_class); - if (event_id < 0) { - _BT_LOGE_NODE(node, "Cannot get event class's ID."); - ret = -EINVAL; - goto error; + event_class->id = 0; } - eevent_class = bt_ctf_stream_class_get_event_class_by_id(stream_class, - event_id); - if (eevent_class) { - BT_PUT(eevent_class); + if (ctf_stream_class_borrow_event_class_by_id(stream_class, + event_class->id)) { _BT_LOGE_NODE(node, "Duplicate event class (same ID) in the same stream class: " - "id=%" PRId64, event_id); + "id=%" PRId64, event_class->id); ret = -EEXIST; goto error; } - ret = bt_ctf_stream_class_add_event_class(stream_class, event_class); - BT_PUT(event_class); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot add event class to stream class: ret=%d", ret); - goto error; - } - + ctf_stream_class_append_event_class(stream_class, event_class); + event_class = NULL; goto end; error: - bt_put(event_class); + ctf_event_class_destroy(event_class); + event_class = NULL; + + if (ret >= 0) { + ret = -1; + } end: if (pop_scope) { ctx_pop_scope(ctx); } - g_free(event_name); - bt_put(stream_class); + if (event_name) { + g_free(event_name); + } + return ret; } static -int auto_map_fields_to_trace_clock_class(struct ctx *ctx, - struct bt_ctf_field_type *packet_context_field_type, - const char **field_names) +int auto_map_field_to_trace_clock_class(struct ctx *ctx, + struct ctf_field_class *fc) { - _BT_CTF_FIELD_TYPE_INIT(ft); - struct bt_ctf_clock_class *clock_class = NULL; - struct bt_ctf_clock_class *mapped_clock_class = NULL; + struct bt_clock_class *clock_class_to_map_to = NULL; + struct ctf_field_class_int *int_fc = (void *) fc; int ret = 0; - const char **field_name; + uint64_t clock_class_count; + + if (!fc) { + goto end; + } - if (ctx->decoder_config.strict) { + if (fc->type != CTF_FIELD_CLASS_TYPE_INT && + fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { goto end; } - if (!packet_context_field_type) { + if (int_fc->mapped_clock_class) { + /* Already mapped */ goto end; } - if (!bt_ctf_field_type_is_structure(packet_context_field_type)) { + 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 = bt_clock_class_create(); + BT_ASSERT(clock_class_to_map_to); + bt_clock_class_set_frequency(clock_class_to_map_to, + UINT64_C(1000000000)); + ret = bt_clock_class_set_name(clock_class_to_map_to, + "default"); + BT_ASSERT(ret == 0); + g_ptr_array_add(ctx->ctf_tc->clock_classes, + clock_class_to_map_to); + bt_object_get_ref(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 = ctx->ctf_tc->clock_classes->pdata[0]; + bt_object_get_ref(clock_class_to_map_to); + 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_LOGE_STR("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; } - if (bt_ctf_trace_get_clock_class_count(ctx->trace) != 1) { + BT_ASSERT(clock_class_to_map_to); + int_fc->mapped_clock_class = clock_class_to_map_to; + bt_object_get_ref(int_fc->mapped_clock_class); + +end: + bt_object_put_ref(clock_class_to_map_to); + return ret; +} + +static +int auto_map_fields_to_trace_clock_class(struct ctx *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 = (void *) root_fc; + struct ctf_field_class_variant *var_fc = (void *) root_fc; + + if (!root_fc) { goto end; } - clock_class = bt_ctf_trace_get_clock_class_by_index(ctx->trace, 0); - assert(clock_class); + if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT && + root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) { + goto end; + } - for (field_name = field_names; *field_name; field_name++) { - ft = bt_ctf_field_type_structure_get_field_type_by_name( - packet_context_field_type, *field_name); + if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) { + count = struct_fc->members->len; + } else { + count = var_fc->options->len; + } - if (ft && bt_ctf_field_type_is_integer(ft)) { - mapped_clock_class = - bt_ctf_field_type_integer_get_mapped_clock_class(ft); + for (i = 0; i < count; i++) { + struct ctf_named_field_class *named_fc = NULL; - if (!mapped_clock_class) { - ret = bt_ctf_field_type_integer_set_mapped_clock_class( - ft, clock_class); - if (ret) { - BT_LOGE("Cannot map field type's field to trace's clock class: " - "field-name=\"%s\", ret=%d", - *field_name, ret); - goto end; - } + 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); + } + + if (strcmp(named_fc->name->str, field_name) == 0) { + ret = auto_map_field_to_trace_clock_class(ctx, + named_fc->fc); + if (ret) { + BT_LOGE("Cannot automatically map field to trace's clock class: " + "field-name=\"%s\"", field_name); + goto end; } } - BT_PUT(mapped_clock_class); - BT_PUT(ft); + ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc, + field_name); + if (ret) { + BT_LOGE("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: - bt_put(mapped_clock_class); - bt_put(clock_class); - bt_put(ft); return ret; } static int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, - struct bt_ctf_stream_class *stream_class, int *set) + struct ctf_stream_class *stream_class, int *set) { int ret = 0; char *left = NULL; - _BT_CTF_FIELD_TYPE_INIT(decl); switch (node->type) { case NODE_TYPEDEF: - ret = visit_typedef(ctx, node->u._typedef.type_specifier_list, - &node->u._typedef.type_declarators); + 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_LOGE_NODE(node, - "Cannot add type definition found in stream class."); + "Cannot add field class found in stream class."); goto error; } break; case NODE_TYPEALIAS: - ret = visit_typealias(ctx, node->u.typealias.target, - node->u.typealias.alias); + ret = visit_field_class_alias(ctx, node->u.field_class_alias.target, + node->u.field_class_alias.alias); if (ret) { _BT_LOGE_NODE(node, - "Cannot add type alias found in stream class."); + "Cannot add field class alias found in stream class."); goto error; } break; @@ -3860,7 +3740,6 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, if (!strcmp(left, "id")) { int64_t id; - gpointer ptr; if (_IS_SET(set, _STREAM_ID_SET)) { _BT_LOGE_DUP_ATTR(node, "id", @@ -3871,6 +3750,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, ret = get_unary_unsigned(&node->u.ctf_expression.right, (uint64_t *) &id); + /* Only read "id" if get_unary_unsigned() succeeded. */ if (ret || (!ret && id < 0)) { _BT_LOGE_NODE(node, @@ -3879,9 +3759,8 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - ptr = g_hash_table_lookup(ctx->stream_classes, - (gpointer) id); - if (ptr) { + if (ctf_trace_class_borrow_stream_class_by_id( + ctx->ctf_tc, id)) { _BT_LOGE_NODE(node, "Duplicate stream class (same ID): id=%" PRId64, id); @@ -3889,22 +3768,9 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - ret = bt_ctf_stream_class_set_id(stream_class, id); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot set stream class's ID: " - "id=%" PRId64 ", ret=%d", id, ret); - goto error; - } - + stream_class->id = id; _SET(set, _STREAM_ID_SET); } else if (!strcmp(left, "event.header")) { - const char *field_names[] = { - "timestamp", - "ts", - NULL, - }; - if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) { _BT_LOGE_NODE(node, "Duplicate `event.header` entry in stream class."); @@ -3912,32 +3778,23 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - ret = visit_type_specifier_list(ctx, + ret = visit_field_class_specifier_list(ctx, _BT_LIST_FIRST_ENTRY( &node->u.ctf_expression.right, struct ctf_node, siblings), - &decl); + &stream_class->event_header_fc); if (ret) { _BT_LOGE_NODE(node, - "Cannot create stream class's event header field type."); + "Cannot create stream class's event header field class."); goto error; } - assert(decl); + BT_ASSERT(stream_class->event_header_fc); ret = auto_map_fields_to_trace_clock_class(ctx, - decl, field_names); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot automatically map specific event header field type fields to trace's clock class."); - goto error; - } - - ret = bt_ctf_stream_class_set_event_header_type( - stream_class, decl); - BT_PUT(decl); + stream_class->event_header_fc, "timestamp"); if (ret) { _BT_LOGE_NODE(node, - "Cannot set stream class's event header field type."); + "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class."); goto error; } @@ -3950,36 +3807,20 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - ret = visit_type_specifier_list(ctx, + ret = visit_field_class_specifier_list(ctx, _BT_LIST_FIRST_ENTRY( &node->u.ctf_expression.right, struct ctf_node, siblings), - &decl); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot create stream class's event context field type."); - goto error; - } - - assert(decl); - - ret = bt_ctf_stream_class_set_event_context_type( - stream_class, decl); - BT_PUT(decl); + &stream_class->event_common_context_fc); if (ret) { _BT_LOGE_NODE(node, - "Cannot set stream class's event context field type."); + "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")) { - const char *field_names[] = { - "timestamp_begin", - "timestamp_end", - NULL, - }; - if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) { _BT_LOGE_NODE(node, "Duplicate `packet.context` entry in stream class."); @@ -3987,32 +3828,33 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, goto error; } - ret = visit_type_specifier_list(ctx, + ret = visit_field_class_specifier_list(ctx, _BT_LIST_FIRST_ENTRY( &node->u.ctf_expression.right, struct ctf_node, siblings), - &decl); + &stream_class->packet_context_fc); if (ret) { _BT_LOGE_NODE(node, - "Cannot create stream class's packet context field type."); + "Cannot create stream class's packet context field class."); goto error; } - assert(decl); + BT_ASSERT(stream_class->packet_context_fc); ret = auto_map_fields_to_trace_clock_class(ctx, - decl, field_names); + stream_class->packet_context_fc, + "timestamp_begin"); if (ret) { _BT_LOGE_NODE(node, - "Cannot automatically map specific packet context field type fields to trace's clock class."); + "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class."); goto error; } - ret = bt_ctf_stream_class_set_packet_context_type( - stream_class, decl); - BT_PUT(decl); + ret = auto_map_fields_to_trace_clock_class(ctx, + stream_class->packet_context_fc, + "timestamp_end"); if (ret) { _BT_LOGE_NODE(node, - "Cannot set stream class's packet context field type."); + "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class."); goto error; } @@ -4037,20 +3879,16 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, error: g_free(left); - BT_PUT(decl); - return ret; } static int visit_stream_decl(struct ctx *ctx, struct ctf_node *node) { - int64_t id; int set = 0; int ret = 0; struct ctf_node *iter; - struct bt_ctf_stream_class *stream_class = NULL; - struct bt_ctf_stream_class *existing_stream_class = NULL; + struct ctf_stream_class *stream_class = NULL; struct bt_list_head *decl_list = &node->u.stream.declaration_list; if (node->visited) { @@ -4058,18 +3896,9 @@ int visit_stream_decl(struct ctx *ctx, struct ctf_node *node) } node->visited = TRUE; - stream_class = create_reset_stream_class(ctx); - if (!stream_class) { - _BT_LOGE_NODE(node, "Cannot create empty stream class."); - ret = -EINVAL; - goto error; - } - - ret = ctx_push_scope(ctx); - if (ret) { - BT_LOGE_STR("Cannot push scope."); - goto error; - } + 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); @@ -4085,42 +3914,35 @@ int visit_stream_decl(struct ctx *ctx, struct ctf_node *node) ctx_pop_scope(ctx); if (_IS_SET(&set, _STREAM_ID_SET)) { - /* Check that packet header has stream_id field */ - _BT_CTF_FIELD_TYPE_INIT(stream_id_decl); - _BT_CTF_FIELD_TYPE_INIT(packet_header_decl); + /* Check that packet header has `stream_id` field */ + struct ctf_named_field_class *named_fc = NULL; - packet_header_decl = - bt_ctf_trace_get_packet_header_type(ctx->trace); - if (!packet_header_decl) { + if (!ctx->ctf_tc->packet_header_fc) { _BT_LOGE_NODE(node, "Stream class has a `id` attribute, " - "but trace has no packet header field type."); + "but trace has no packet header field class."); goto error; } - stream_id_decl = - bt_ctf_field_type_structure_get_field_type_by_name( - packet_header_decl, "stream_id"); - BT_PUT(packet_header_decl); - if (!stream_id_decl) { + named_fc = ctf_field_class_struct_borrow_member_by_name( + (void *) ctx->ctf_tc->packet_header_fc, "stream_id"); + if (!named_fc) { _BT_LOGE_NODE(node, "Stream class has a `id` attribute, " - "but trace's packet header field type has no `stream_id` field."); + "but trace's packet header field class has no `stream_id` field."); goto error; } - if (!bt_ctf_field_type_is_integer(stream_id_decl)) { - BT_PUT(stream_id_decl); + if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT && + named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { _BT_LOGE_NODE(node, "Stream class has a `id` attribute, " - "but trace's packet header field type's `stream_id` field is not an integer field type."); + "but trace's packet header field class's `stream_id` field is not an integer field class."); goto error; } - - BT_PUT(stream_id_decl); } else { /* Allow only _one_ ID-less stream */ - if (g_hash_table_size(ctx->stream_classes) != 0) { + if (ctx->ctf_tc->stream_classes->len != 0) { _BT_LOGE_NODE(node, "Missing `id` attribute in stream class as there's more than one stream class in the trace."); ret = -EPERM; @@ -4128,44 +3950,31 @@ int visit_stream_decl(struct ctx *ctx, struct ctf_node *node) } /* Automatic ID: 0 */ - ret = bt_ctf_stream_class_set_id(stream_class, 0); - assert(ret == 0); - } - - id = bt_ctf_stream_class_get_id(stream_class); - if (id < 0) { - _BT_LOGE_NODE(node, - "Cannot get stream class's ID."); - ret = -EINVAL; - goto error; + stream_class->id = 0; } /* * Make sure that this stream class's ID is currently unique in * the trace. */ - existing_stream_class = bt_ctf_trace_get_stream_class_by_id(ctx->trace, - id); - if (g_hash_table_lookup(ctx->stream_classes, (gpointer) id) || - existing_stream_class) { + if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, + stream_class->id)) { _BT_LOGE_NODE(node, "Duplicate stream class (same ID): id=%" PRId64, - id); + stream_class->id); ret = -EINVAL; goto error; } - /* Move reference to visitor's context */ - g_hash_table_insert(ctx->stream_classes, (gpointer) (int64_t) id, - stream_class); + g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class); stream_class = NULL; goto end; error: - bt_put(stream_class); + ctf_stream_class_destroy(stream_class); + stream_class = NULL; end: - bt_put(existing_stream_class); return ret; } @@ -4174,24 +3983,24 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) { int ret = 0; char *left = NULL; - _BT_CTF_FIELD_TYPE_INIT(packet_header_decl); + uint64_t val; switch (node->type) { case NODE_TYPEDEF: - ret = visit_typedef(ctx, node->u._typedef.type_specifier_list, - &node->u._typedef.type_declarators); + 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_LOGE_NODE(node, - "Cannot add type definition found in trace (`trace` block)."); + "Cannot add field class found in trace (`trace` block)."); goto error; } break; case NODE_TYPEALIAS: - ret = visit_typealias(ctx, node->u.typealias.target, - node->u.typealias.alias); + ret = visit_field_class_alias(ctx, node->u.field_class_alias.target, + node->u.field_class_alias.alias); if (ret) { _BT_LOGE_NODE(node, - "Cannot add type alias found in trace (`trace` block)."); + "Cannot add field class alias found in trace (`trace` block)."); goto error; } break; @@ -4212,7 +4021,7 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) } ret = get_unary_unsigned(&node->u.ctf_expression.right, - &ctx->trace_major); + &val); if (ret) { _BT_LOGE_NODE(node, "Unexpected unary expression for trace's `major` attribute."); @@ -4220,6 +4029,13 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) goto error; } + if (val != 1) { + _BT_LOGE_NODE(node, + "Invalid trace's `minor` attribute: expecting 1."); + goto error; + } + + ctx->ctf_tc->major = val; _SET(set, _TRACE_MAJOR_SET); } else if (!strcmp(left, "minor")) { if (_IS_SET(set, _TRACE_MINOR_SET)) { @@ -4229,7 +4045,7 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) } ret = get_unary_unsigned(&node->u.ctf_expression.right, - &ctx->trace_minor); + &val); if (ret) { _BT_LOGE_NODE(node, "Unexpected unary expression for trace's `minor` attribute."); @@ -4237,6 +4053,13 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) goto error; } + if (val != 8) { + _BT_LOGE_NODE(node, + "Invalid trace's `minor` attribute: expecting 8."); + goto error; + } + + ctx->ctf_tc->minor = val; _SET(set, _TRACE_MINOR_SET); } else if (!strcmp(left, "uuid")) { if (_IS_SET(set, _TRACE_UUID_SET)) { @@ -4246,22 +4069,17 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) } ret = get_unary_uuid(&node->u.ctf_expression.right, - ctx->trace_uuid); + ctx->ctf_tc->uuid); if (ret) { _BT_LOGE_NODE(node, "Invalid trace's `uuid` attribute."); goto error; } - ret = bt_ctf_trace_set_uuid(ctx->trace, ctx->trace_uuid); - if (ret) { - _BT_LOGE_NODE(node, "Cannot set trace's UUID."); - goto error; - } - + ctx->ctf_tc->is_uuid_set = true; _SET(set, _TRACE_UUID_SET); } else if (!strcmp(left, "byte_order")) { - /* Native byte order is already known at this stage */ + /* Default byte order is already known at this stage */ if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) { _BT_LOGE_DUP_ATTR(node, "byte_order", "trace"); @@ -4269,6 +4087,7 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) goto error; } + BT_ASSERT(ctx->ctf_tc->default_byte_order != -1); _SET(set, _TRACE_BYTE_ORDER_SET); } else if (!strcmp(left, "packet.header")) { if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) { @@ -4278,27 +4097,18 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) goto error; } - ret = visit_type_specifier_list(ctx, + ret = visit_field_class_specifier_list(ctx, _BT_LIST_FIRST_ENTRY( &node->u.ctf_expression.right, struct ctf_node, siblings), - &packet_header_decl); + &ctx->ctf_tc->packet_header_fc); if (ret) { _BT_LOGE_NODE(node, - "Cannot create trace's packet header field type."); - goto error; - } - - assert(packet_header_decl); - ret = bt_ctf_trace_set_packet_header_type(ctx->trace, - packet_header_decl); - BT_PUT(packet_header_decl); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot set trace's packet header field type."); + "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_LOGW_NODE(node, @@ -4320,8 +4130,6 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) error: g_free(left); - BT_PUT(packet_header_decl); - return ret; } @@ -4345,11 +4153,7 @@ int visit_trace_decl(struct ctx *ctx, struct ctf_node *node) goto error; } - ret = ctx_push_scope(ctx); - if (ret) { - BT_LOGE_STR("Cannot push scope."); - 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); @@ -4384,7 +4188,7 @@ int visit_trace_decl(struct ctx *ctx, struct ctf_node *node) goto error; } - ctx->is_trace_visited = TRUE; + ctx->is_trace_visited = true; end: return 0; @@ -4439,27 +4243,19 @@ int visit_env(struct ctx *ctx, struct ctf_node *node) goto error; } - if (!ctx->decoder_config.strict) { - if (strcmp(left, "tracer_name") == 0) { - if (strncmp(right, "lttng", 5) == 0) { - BT_LOGI("Non-strict mode: detected LTTng trace from `%s` environment value: " - "tracer-name=\"%s\"", - left, right); - ctx->is_lttng = 1; - } + if (strcmp(left, "tracer_name") == 0) { + if (strncmp(right, "lttng", 5) == 0) { + BT_LOGI("Detected LTTng trace from `%s` environment value: " + "tracer-name=\"%s\"", + left, right); + ctx->is_lttng = true; } } - ret = bt_ctf_trace_set_environment_field_string( - ctx->trace, left, right); + ctf_trace_class_append_env_entry(ctx->ctf_tc, + left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR, + right, 0); g_free(right); - - if (ret) { - _BT_LOGE_NODE(entry_node, - "Cannot add string environment entry to trace: " - "name=\"%s\", ret=%d", left, ret); - goto error; - } } else if (is_unary_unsigned(right_head) || is_unary_signed(right_head)) { int64_t v; @@ -4478,14 +4274,9 @@ int visit_env(struct ctx *ctx, struct ctf_node *node) goto error; } - ret = bt_ctf_trace_set_environment_field_integer( - ctx->trace, left, v); - if (ret) { - _BT_LOGE_NODE(entry_node, - "Cannot add integer environment entry to trace: " - "name=\"%s\", ret=%d", left, ret); - goto error; - } + ctf_trace_class_append_env_entry(ctx->ctf_tc, + left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT, + NULL, v); } else { _BT_LOGW_NODE(entry_node, "Environment entry has unknown type: " @@ -4501,7 +4292,6 @@ end: error: g_free(left); - return ret; } @@ -4528,7 +4318,7 @@ int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node) } if (!strcmp(left, "byte_order")) { - enum bt_ctf_byte_order bo; + enum ctf_byte_order bo; if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { _BT_LOGE_DUP_ATTR(node, "byte_order", @@ -4542,13 +4332,13 @@ int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node) &node->u.ctf_expression.right, struct ctf_node, siblings); bo = byte_order_from_unary_expr(right_node); - if (bo == BT_CTF_BYTE_ORDER_UNKNOWN) { + if (bo == -1) { _BT_LOGE_NODE(node, "Invalid `byte_order` attribute in trace (`trace` block): " "expecting `le`, `be`, or `network`."); ret = -EINVAL; goto error; - } else if (bo == BT_CTF_BYTE_ORDER_NATIVE) { + } else if (bo == CTF_BYTE_ORDER_DEFAULT) { _BT_LOGE_NODE(node, "Invalid `byte_order` attribute in trace (`trace` block): " "cannot be set to `native` here."); @@ -4556,15 +4346,7 @@ int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node) goto error; } - ctx->trace_bo = bo; - ret = bt_ctf_trace_set_native_byte_order( - ctx->trace, bo); - if (ret) { - _BT_LOGE_NODE(node, - "Cannot set trace's byte order: " - "ret=%d", ret); - goto error; - } + ctx->ctf_tc->default_byte_order = bo; } g_free(left); @@ -4583,13 +4365,13 @@ int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node) error: g_free(left); - return ret; } static int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, - struct bt_ctf_clock_class *clock, int *set) + struct bt_clock_class *clock, int *set, int64_t *offset_seconds, + uint64_t *offset_cycles) { int ret = 0; char *left = NULL; @@ -4627,7 +4409,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, goto error; } - ret = bt_ctf_clock_class_set_name(clock, right); + ret = bt_clock_class_set_name(clock, right); if (ret) { _BT_LOGE_NODE(entry_node, "cannot set clock class's name"); @@ -4638,7 +4420,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, g_free(right); _SET(set, _CLOCK_NAME_SET); } else if (!strcmp(left, "uuid")) { - unsigned char uuid[BABELTRACE_UUID_LEN]; + uint8_t uuid[BABELTRACE_UUID_LEN]; if (_IS_SET(set, _CLOCK_UUID_SET)) { _BT_LOGE_DUP_ATTR(entry_node, "uuid", "clock class"); @@ -4653,13 +4435,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, goto error; } - ret = bt_ctf_clock_class_set_uuid(clock, uuid); - if (ret) { - _BT_LOGE_NODE(entry_node, - "Cannot set clock class's UUID."); - goto error; - } - + bt_clock_class_set_uuid(clock, uuid); _SET(set, _CLOCK_UUID_SET); } else if (!strcmp(left, "description")) { char *right; @@ -4680,7 +4456,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, goto error; } - ret = bt_ctf_clock_class_set_description(clock, right); + ret = bt_clock_class_set_description(clock, right); if (ret) { _BT_LOGE_NODE(entry_node, "Cannot set clock class's description."); @@ -4691,7 +4467,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, g_free(right); _SET(set, _CLOCK_DESCRIPTION_SET); } else if (!strcmp(left, "freq")) { - uint64_t freq; + uint64_t freq = UINT64_C(-1); if (_IS_SET(set, _CLOCK_FREQ_SET)) { _BT_LOGE_DUP_ATTR(entry_node, "freq", "clock class"); @@ -4708,13 +4484,15 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, goto error; } - ret = bt_ctf_clock_class_set_frequency(clock, freq); - if (ret) { + if (freq == UINT64_C(-1) || freq == 0) { _BT_LOGE_NODE(entry_node, - "Cannot set clock class's frequency."); + "Invalid clock class frequency: freq=%" PRIu64, + freq); + ret = -EINVAL; goto error; } + bt_clock_class_set_frequency(clock, freq); _SET(set, _CLOCK_FREQ_SET); } else if (!strcmp(left, "precision")) { uint64_t precision; @@ -4735,17 +4513,9 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, goto error; } - ret = bt_ctf_clock_class_set_precision(clock, precision); - if (ret) { - _BT_LOGE_NODE(entry_node, - "Cannot set clock class's precision."); - goto error; - } - + bt_clock_class_set_precision(clock, precision); _SET(set, _CLOCK_PRECISION_SET); } else if (!strcmp(left, "offset_s")) { - uint64_t offset_s; - if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) { _BT_LOGE_DUP_ATTR(entry_node, "offset_s", "clock class"); @@ -4753,8 +4523,8 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, goto error; } - ret = get_unary_unsigned( - &entry_node->u.ctf_expression.right, &offset_s); + ret = get_unary_signed( + &entry_node->u.ctf_expression.right, offset_seconds); if (ret) { _BT_LOGE_NODE(entry_node, "Unexpected unary expression for clock class's `offset_s` attribute."); @@ -4762,17 +4532,8 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, goto error; } - ret = bt_ctf_clock_class_set_offset_s(clock, offset_s); - if (ret) { - _BT_LOGE_NODE(entry_node, - "Cannot set clock class's offset in seconds."); - goto error; - } - _SET(set, _CLOCK_OFFSET_S_SET); } else if (!strcmp(left, "offset")) { - uint64_t offset; - if (_IS_SET(set, _CLOCK_OFFSET_SET)) { _BT_LOGE_DUP_ATTR(entry_node, "offset", "clock class"); ret = -EPERM; @@ -4780,7 +4541,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, } ret = get_unary_unsigned( - &entry_node->u.ctf_expression.right, &offset); + &entry_node->u.ctf_expression.right, offset_cycles); if (ret) { _BT_LOGE_NODE(entry_node, "Unexpected unary expression for clock class's `offset` attribute."); @@ -4788,13 +4549,6 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, goto error; } - ret = bt_ctf_clock_class_set_offset_cycles(clock, offset); - if (ret) { - _BT_LOGE_NODE(entry_node, - "Cannot set clock class's offset in cycles."); - goto error; - } - _SET(set, _CLOCK_OFFSET_SET); } else if (!strcmp(left, "absolute")) { struct ctf_node *right; @@ -4817,13 +4571,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, goto error; } - ret = bt_ctf_clock_class_set_is_absolute(clock, ret); - if (ret) { - _BT_LOGE_NODE(entry_node, - "Cannot set clock class's absolute flag."); - goto error; - } - + bt_clock_class_set_is_absolute(clock, ret); _SET(set, _CLOCK_ABSOLUTE_SET); } else { _BT_LOGW_NODE(entry_node, @@ -4833,22 +4581,20 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, g_free(left); left = NULL; - return 0; error: g_free(left); - return ret; } -static -int64_t cycles_from_ns(uint64_t frequency, int64_t ns) +static inline +uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns) { - int64_t cycles; + uint64_t cycles; /* 1GHz */ - if (frequency == 1000000000ULL) { + if (frequency == UINT64_C(1000000000)) { cycles = ns; } else { cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9); @@ -4858,35 +4604,73 @@ int64_t cycles_from_ns(uint64_t frequency, int64_t ns) } static -int apply_clock_class_offset(struct ctx *ctx, struct bt_ctf_clock_class *clock) +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; + + *offset_seconds += (int64_t) s_in_offset_cycles; + *offset_cycles -= (s_in_offset_cycles * freq); + } +} + +static +void apply_clock_class_offset(struct ctx *ctx, + struct bt_clock_class *clock) { - int ret; uint64_t freq; - int64_t offset_cycles; - int64_t offset_to_apply; + 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; - freq = bt_ctf_clock_class_get_frequency(clock); - if (freq == -1ULL) { - BT_LOGE_STR("Cannot get clock class's frequency."); - ret = -1; + if (ctx->decoder_config.clock_class_offset_s == 0 && + ctx->decoder_config.clock_class_offset_ns == 0) { goto end; } - ret = bt_ctf_clock_class_get_offset_cycles(clock, &offset_cycles); - if (ret) { - BT_LOGE_STR("Cannot get clock class's offset in cycles."); - ret = -1; - 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; } - offset_to_apply = - ctx->decoder_config.clock_class_offset_s * 1000000000LL + - ctx->decoder_config.clock_class_offset_ns; - offset_cycles += cycles_from_ns(freq, offset_to_apply); - ret = bt_ctf_clock_class_set_offset_cycles(clock, offset_cycles); + freq = bt_clock_class_get_frequency(clock); + bt_clock_class_get_offset(clock, + &cur_offset_s, &cur_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 */ + bt_clock_class_set_offset(clock, cur_offset_s, cur_offset_cycles); end: - return ret; + return; } static @@ -4894,31 +4678,40 @@ int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node) { int ret = 0; int set = 0; - struct bt_ctf_clock_class *clock; + struct bt_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; - clock = bt_ctf_clock_class_create(NULL); + + /* CTF 1.8's default frequency for a clock class is 1 GHz */ + clock = bt_clock_class_create(); if (!clock) { _BT_LOGE_NODE(clock_node, "Cannot create default clock class."); ret = -ENOMEM; - goto error; + goto end; } + /* CTF: not absolute by default */ + bt_clock_class_set_is_absolute(clock, BT_FALSE); + bt_list_for_each_entry(entry_node, decl_list, siblings) { - ret = visit_clock_decl_entry(ctx, entry_node, clock, &set); + ret = visit_clock_decl_entry(ctx, entry_node, clock, &set, + &offset_seconds, &offset_cycles); if (ret) { _BT_LOGE_NODE(entry_node, "Cannot visit clock class's entry: ret=%d", ret); - goto error; + goto end; } } @@ -4926,11 +4719,11 @@ int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node) _BT_LOGE_NODE(clock_node, "Missing `name` attribute in clock class."); ret = -EPERM; - goto error; + goto end; } - clock_class_name = bt_ctf_clock_class_get_name(clock); - assert(clock_class_name); + clock_class_name = bt_clock_class_get_name(clock); + 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 @@ -4938,31 +4731,23 @@ int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node) * it's a condition to be able to sort notifications * from different sources. */ - ret = bt_ctf_clock_class_set_is_absolute(clock, 1); - if (ret) { - _BT_LOGE_NODE(clock_node, - "Cannot set clock class's absolute flag."); - goto error; - } + bt_clock_class_set_is_absolute(clock, BT_TRUE); } - ret = apply_clock_class_offset(ctx, clock); - if (ret) { - _BT_LOGE_NODE(clock_node, - "Cannot apply clock class's custom offset."); - goto error; - } - - ret = bt_ctf_trace_add_clock_class(ctx->trace, clock); - if (ret) { - _BT_LOGE_NODE(clock_node, - "Cannot add clock class to trace."); - goto error; - } - -error: - BT_PUT(clock); + /* + * Adjust offsets so that the part in cycles is less than the + * frequency (move to the part in seconds). + */ + freq = bt_clock_class_get_frequency(clock); + calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq); + BT_ASSERT(offset_cycles < bt_clock_class_get_frequency(clock)); + bt_clock_class_set_offset(clock, offset_seconds, offset_cycles); + apply_clock_class_offset(ctx, clock); + g_ptr_array_add(ctx->ctf_tc->clock_classes, clock); + bt_object_get_ref(clock); +end: + BT_OBJECT_PUT_REF_AND_RESET(clock); return ret; } @@ -4979,42 +4764,43 @@ int visit_root_decl(struct ctx *ctx, struct ctf_node *root_decl_node) switch (root_decl_node->type) { case NODE_TYPEDEF: - ret = visit_typedef(ctx, - root_decl_node->u._typedef.type_specifier_list, - &root_decl_node->u._typedef.type_declarators); + 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_LOGE_NODE(root_decl_node, - "Cannot add type definition found in root scope."); + "Cannot add field class found in root scope."); goto end; } break; case NODE_TYPEALIAS: - ret = visit_typealias(ctx, root_decl_node->u.typealias.target, - root_decl_node->u.typealias.alias); + 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_LOGE_NODE(root_decl_node, - "Cannot add type alias found in root scope."); + "Cannot add field class alias found in root scope."); goto end; } break; case NODE_TYPE_SPECIFIER_LIST: { - _BT_CTF_FIELD_TYPE_INIT(decl); + struct ctf_field_class *decl = NULL; /* - * Just add the type specifier to the root + * Just add the field class specifier to the root * declaration scope. Put local reference. */ - ret = visit_type_specifier_list(ctx, root_decl_node, &decl); + ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl); if (ret) { _BT_LOGE_NODE(root_decl_node, - "Cannot visit root scope's field type: " + "Cannot visit root scope's field class: " "ret=%d", ret); - assert(!decl); + BT_ASSERT(!decl); goto end; } - BT_PUT(decl); + ctf_field_class_destroy(decl); + decl = NULL; break; } default: @@ -5030,13 +4816,17 @@ end: } static -int set_trace_name(struct ctx *ctx) +int try_set_trace_class_name(struct ctx *ctx) { - GString *name; + GString *name = NULL; int ret = 0; - struct bt_value *value = NULL; + struct ctf_trace_class_env_entry *env_entry; + + if (ctx->ctf_tc->name->len > 0) { + /* Already set */ + goto end; + } - assert(bt_ctf_trace_get_stream_class_count(ctx->trace) == 0); name = g_string_new(NULL); if (!name) { BT_LOGE_STR("Failed to allocate a GString."); @@ -5048,38 +4838,25 @@ int set_trace_name(struct ctx *ctx) * Check if we have a trace environment string value named `hostname`. * If so, use it as the trace name's prefix. */ - value = bt_ctf_trace_get_environment_field_value_by_name(ctx->trace, + env_entry = ctf_trace_class_borrow_env_entry_by_name(ctx->ctf_tc, "hostname"); - if (bt_value_is_string(value)) { - const char *hostname; - - ret = bt_value_string_get(value, &hostname); - assert(ret == 0); - g_string_append(name, hostname); + if (env_entry && + env_entry->type == CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR) { + g_string_append(name, env_entry->value.str->str); - if (ctx->trace_name_suffix) { + if (ctx->trace_class_name_suffix) { g_string_append_c(name, G_DIR_SEPARATOR); } } - if (ctx->trace_name_suffix) { - g_string_append(name, ctx->trace_name_suffix); - } - - ret = bt_ctf_trace_set_name(ctx->trace, name->str); - if (ret) { - BT_LOGE("Cannot set trace's name: name=\"%s\"", name->str); - goto error; + if (ctx->trace_class_name_suffix) { + g_string_append(name, ctx->trace_class_name_suffix); } + g_string_assign(ctx->ctf_tc->name, name->str); goto end; -error: - ret = -1; - end: - bt_put(value); - if (name) { g_string_free(name, TRUE); } @@ -5087,77 +4864,20 @@ end: return ret; } -static -int move_ctx_stream_classes_to_trace(struct ctx *ctx) -{ - int ret = 0; - GHashTableIter iter; - gpointer key, stream_class; - - if (g_hash_table_size(ctx->stream_classes) > 0 && - bt_ctf_trace_get_stream_class_count(ctx->trace) == 0) { - /* - * We're about to add the first stream class to the - * trace. This will freeze the trace, and after this - * we cannot set the name anymore. At this point, - * set the trace name. - */ - ret = set_trace_name(ctx); - if (ret) { - BT_LOGE_STR("Cannot set trace's name."); - goto end; - } - } - - g_hash_table_iter_init(&iter, ctx->stream_classes); - - while (g_hash_table_iter_next(&iter, &key, &stream_class)) { - ret = bt_ctf_trace_add_stream_class(ctx->trace, - stream_class); - if (ret) { - int64_t id = bt_ctf_stream_class_get_id(stream_class); - BT_LOGE("Cannot add stream class to trace: id=%" PRId64, - id); - goto end; - } - } - - g_hash_table_remove_all(ctx->stream_classes); - -end: - return ret; -} - BT_HIDDEN struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create( const struct ctf_metadata_decoder_config *decoder_config, const char *name) { - int ret; struct ctx *ctx = NULL; - struct bt_ctf_trace *trace; - - trace = bt_ctf_trace_create(); - if (!trace) { - BT_LOGE_STR("Cannot create empty trace."); - goto error; - } - - /* Set packet header to NULL to override the default one */ - ret = bt_ctf_trace_set_packet_header_type(trace, NULL); - if (ret) { - BT_LOGE_STR("Cannot reset initial trace's packet header field type."); - goto error; - } /* Create visitor's context */ - ctx = ctx_create(trace, decoder_config, name); + ctx = ctx_create(decoder_config, name); if (!ctx) { BT_LOGE_STR("Cannot create visitor's context."); goto error; } - trace = NULL; goto end; error: @@ -5165,7 +4885,6 @@ error: ctx = NULL; end: - bt_put(trace); return (void *) ctx; } @@ -5176,14 +4895,26 @@ void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor) } BT_HIDDEN -struct bt_ctf_trace *ctf_visitor_generate_ir_get_trace( +struct bt_trace *ctf_visitor_generate_ir_get_ir_trace( struct ctf_visitor_generate_ir *visitor) { struct ctx *ctx = (void *) visitor; - assert(ctx); - assert(ctx->trace); - return bt_get(ctx->trace); + BT_ASSERT(ctx); + BT_ASSERT(ctx->trace); + bt_object_get_ref(ctx->trace); + return ctx->trace; +} + +BT_HIDDEN +struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class( + struct ctf_visitor_generate_ir *visitor) +{ + struct ctx *ctx = (void *) visitor; + + BT_ASSERT(ctx); + BT_ASSERT(ctx->ctf_tc); + return ctx->ctf_tc; } BT_HIDDEN @@ -5199,16 +4930,16 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, case NODE_ROOT: { struct ctf_node *iter; - int got_trace_decl = FALSE; + bool got_trace_decl = false; /* * The first thing we need is the native byte order of - * the trace block, because early type aliases can have + * 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->trace_bo == BT_CTF_BYTE_ORDER_NATIVE) { + if (ctx->ctf_tc->default_byte_order == -1) { bt_list_for_each_entry(iter, &node->u.root.trace, siblings) { if (got_trace_decl) { _BT_LOGE_NODE(node, @@ -5225,7 +4956,7 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, goto end; } - got_trace_decl = TRUE; + got_trace_decl = true; } if (!got_trace_decl) { @@ -5235,10 +4966,10 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, } } - assert(ctx->trace_bo == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN || - ctx->trace_bo == BT_CTF_BYTE_ORDER_BIG_ENDIAN); - assert(ctx->current_scope && - ctx->current_scope->parent_scope == NULL); + 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 == NULL); /* Environment */ bt_list_for_each_entry(iter, &node->u.root.env, siblings) { @@ -5251,7 +4982,7 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, } } - assert(ctx->current_scope && + BT_ASSERT(ctx->current_scope && ctx->current_scope->parent_scope == NULL); /* @@ -5267,7 +4998,7 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, } } - assert(ctx->current_scope && + BT_ASSERT(ctx->current_scope && ctx->current_scope->parent_scope == NULL); /* @@ -5285,7 +5016,7 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, } } - assert(ctx->current_scope && + BT_ASSERT(ctx->current_scope && ctx->current_scope->parent_scope == NULL); /* Callsite blocks are not supported */ @@ -5294,7 +5025,7 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, "\"callsite\" blocks are not supported as of this version."); } - assert(ctx->current_scope && + BT_ASSERT(ctx->current_scope && ctx->current_scope->parent_scope == NULL); /* Trace */ @@ -5308,7 +5039,7 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, } } - assert(ctx->current_scope && + BT_ASSERT(ctx->current_scope && ctx->current_scope->parent_scope == NULL); /* Streams */ @@ -5322,7 +5053,7 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, } } - assert(ctx->current_scope && + BT_ASSERT(ctx->current_scope && ctx->current_scope->parent_scope == NULL); /* Events */ @@ -5336,7 +5067,7 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, } } - assert(ctx->current_scope && + BT_ASSERT(ctx->current_scope && ctx->current_scope->parent_scope == NULL); break; } @@ -5348,10 +5079,67 @@ int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, goto end; } - /* Move decoded stream classes to trace, if any */ - ret = move_ctx_stream_classes_to_trace(ctx); + /* Update default clock classes */ + ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc); if (ret) { - BT_LOGE("Cannot move stream classes to trace: ret=%d", ret); + ret = -EINVAL; + goto end; + } + + /* Set trace's name, if not already done */ + ret = try_set_trace_class_name(ctx); + 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 text arrays and sequences */ + ret = ctf_trace_class_update_text_array_sequence(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); + if (ret) { + ret = -EINVAL; + goto end; + } + + /* Update "in IR" for field classes */ + 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); + if (ret) { + ret = -EINVAL; + goto end; + } + + /* Copy new CTF metadata -> new IR metadata */ + ret = ctf_trace_class_translate(ctx->trace, ctx->ctf_tc); + if (ret) { + ret = -EINVAL; + goto end; } end: