X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=plugins%2Fctf%2Fcommon%2Fmetadata%2Fvisitor-generate-ir.c;h=388c76f926e89560984357ddf85e2a65f2d3182d;hb=3dca22768a95bef664012559aa9ac977091de6ac;hp=da979078956216f84bf97e5b1f005c94c82ee0b1;hpb=9254077337fdd8431b4434fbfb066a1309de44ea;p=babeltrace.git diff --git a/plugins/ctf/common/metadata/visitor-generate-ir.c b/plugins/ctf/common/metadata/visitor-generate-ir.c index da979078..388c76f9 100644 --- a/plugins/ctf/common/metadata/visitor-generate-ir.c +++ b/plugins/ctf/common/metadata/visitor-generate-ir.c @@ -27,29 +27,28 @@ * SOFTWARE. */ +#define BT_LOG_TAG "PLUGIN-CTF-METADATA-IR-VISITOR" +#include "logging.h" + #include #include #include +#include #include #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" /* Bit value (left shift) */ #define _BV(_val) (1 << (_val)) @@ -147,39 +146,21 @@ enum loglevel { #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; - -/* Error printing wrappers */ -#define _PERROR(_fmt, ...) \ - do { \ - fprintf(ctx->efd, "[error] %s: " _fmt "\n", \ - __func__, __VA_ARGS__); \ - } while (0) - -#define _PWARNING(_fmt, ...) \ - do { \ - fprintf(ctx->efd, "[warning] %s: " _fmt "\n", \ - __func__, __VA_ARGS__); \ - } while (0) - -#define _FPERROR(_stream, _fmt, ...) \ - do { \ - fprintf(_stream, "[error] %s: " _fmt "\n", \ - __func__, __VA_ARGS__); \ - } while (0) - -#define _FPWARNING(_stream, _fmt, ...) \ - do { \ - fprintf(_stream, "[warning] %s: " _fmt "\n", \ - __func__, __VA_ARGS__); \ - } while (0) - -#define _PERROR_DUP_ATTR(_attr, _entity) \ - do { \ - fprintf(ctx->efd, \ - "[error] %s: duplicate attribute \"" \ - _attr "\" in " _entity "\n", __func__); \ - } while (0) +#define _BT_FIELD_TYPE_INIT(_name) struct bt_field_type *_name = NULL; + +#define _BT_LOGE_DUP_ATTR(_node, _attr, _entity) \ + _BT_LOGE_LINENO((_node)->lineno, \ + "Duplicate attribute in %s: attr-name=\"%s\"", \ + _entity, _attr) + +#define _BT_LOGE_NODE(_node, _msg, args...) \ + _BT_LOGE_LINENO((_node)->lineno, _msg, ## args) + +#define _BT_LOGW_NODE(_node, _msg, args...) \ + _BT_LOGW_LINENO((_node)->lineno, _msg, ## args) + +#define _BT_LOGV_NODE(_node, _msg, args...) \ + _BT_LOGV_LINENO((_node)->lineno, _msg, ## args) /* * Declaration scope of a visitor context. This represents a TSDL @@ -190,7 +171,7 @@ struct ctx_decl_scope { /* * Alias name to field type. * - * GQuark -> struct bt_ctf_field_type * + * GQuark -> struct bt_field_type * */ GHashTable *decl_map; @@ -199,14 +180,11 @@ struct ctx_decl_scope { }; /* - * Visitor context. + * Visitor context (private). */ struct ctx { - /* Trace being filled (weak ref.) */ - struct bt_ctf_trace *trace; - - /* Error stream to use during visit */ - FILE *efd; + /* Trace being filled (owned by this) */ + struct bt_trace *trace; /* Current declaration scope (top of the stack) */ struct ctx_decl_scope *current_scope; @@ -214,7 +192,14 @@ struct ctx { /* 1 if trace declaration is visited */ int is_trace_visited; + /* 1 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_byte_order trace_bo; uint64_t trace_major; uint64_t trace_minor; unsigned char trace_uuid[BABELTRACE_UUID_LEN]; @@ -222,41 +207,18 @@ struct ctx { /* * Stream IDs to stream classes. * - * int64_t -> struct bt_ctf_stream_class * + * int64_t -> struct bt_stream_class * */ GHashTable *stream_classes; -}; -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", + /* Config passed by the user */ + struct ctf_metadata_decoder_config decoder_config; }; -static -const char *print_loglevel(int64_t value) -{ - if (value < 0) { - return NULL; - } - if (value >= _NR_LOGLEVELS) { - return "<>"; - } - return loglevel_str[value]; -} +/* + * Visitor (public). + */ +struct ctf_visitor_generate_ir { }; /** * Creates a new declaration scope. @@ -271,11 +233,12 @@ struct ctx_decl_scope *ctx_decl_scope_create(struct ctx_decl_scope *par_scope) scope = g_new(struct ctx_decl_scope, 1); if (!scope) { + BT_LOGE_STR("Failed to allocate one declaration scope."); goto end; } scope->decl_map = g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify) bt_ctf_field_type_put); + NULL, (GDestroyNotify) bt_put); scope->parent_scope = par_scope; end: @@ -315,11 +278,12 @@ 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); if (!prname) { + BT_LOGE_STR("Failed to allocate a string."); goto end; } @@ -341,17 +305,17 @@ end: * @returns Declaration, or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_prefix_alias( +struct bt_field_type *ctx_decl_scope_lookup_prefix_alias( struct ctx_decl_scope *scope, char prefix, const char *name, int levels) { GQuark qname = 0; int cur_levels = 0; - _BT_CTF_FIELD_TYPE_INIT(decl); + _BT_FIELD_TYPE_INIT(decl); 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; @@ -363,7 +327,7 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_prefix_alias( while (cur_scope && cur_levels < levels) { decl = g_hash_table_lookup(cur_scope->decl_map, - (gconstpointer) (unsigned long) qname); + (gconstpointer) GUINT_TO_POINTER(qname)); if (decl) { /* Caller's reference */ bt_get(decl); @@ -389,7 +353,7 @@ error: * @returns Declaration, or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_alias( +struct bt_field_type *ctx_decl_scope_lookup_alias( struct ctx_decl_scope *scope, const char *name, int levels) { return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ALIAS, @@ -405,7 +369,7 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_alias( * @returns Declaration, or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_enum( +struct bt_field_type *ctx_decl_scope_lookup_enum( struct ctx_decl_scope *scope, const char *name, int levels) { return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ENUM, @@ -421,7 +385,7 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_enum( * @returns Declaration, or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_struct( +struct bt_field_type *ctx_decl_scope_lookup_struct( struct ctx_decl_scope *scope, const char *name, int levels) { return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_STRUCT, @@ -437,7 +401,7 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_struct( * @returns Declaration, or NULL if not found */ static -struct bt_ctf_field_type *ctx_decl_scope_lookup_variant( +struct bt_field_type *ctx_decl_scope_lookup_variant( struct ctx_decl_scope *scope, const char *name, int levels) { return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_VARIANT, @@ -455,15 +419,15 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_variant( */ 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 bt_field_type *decl) { int ret = 0; GQuark qname = 0; - _BT_CTF_FIELD_TYPE_INIT(edecl); + _BT_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; @@ -479,7 +443,7 @@ int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope *scope, } g_hash_table_insert(scope->decl_map, - (gpointer) (unsigned long) qname, decl); + GUINT_TO_POINTER(qname), decl); /* Hash table's reference */ bt_get(decl); @@ -500,7 +464,7 @@ error: */ 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 bt_field_type *decl) { return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ALIAS, name, decl); @@ -516,7 +480,7 @@ int ctx_decl_scope_register_alias(struct ctx_decl_scope *scope, */ 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 bt_field_type *decl) { return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ENUM, name, decl); @@ -532,7 +496,7 @@ int ctx_decl_scope_register_enum(struct ctx_decl_scope *scope, */ 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 bt_field_type *decl) { return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_STRUCT, name, decl); @@ -548,87 +512,106 @@ int ctx_decl_scope_register_struct(struct ctx_decl_scope *scope, */ 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 bt_field_type *decl) { return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_VARIANT, name, decl); } /** - * Creates a new visitor context. + * Destroys a visitor context. * - * @param trace Associated trace - * @param efd Error stream - * @returns New visitor context, or NULL on error + * @param ctx Visitor context to destroy */ static -struct ctx *ctx_create(struct bt_ctf_trace *trace, FILE *efd) +void ctx_destroy(struct ctx *ctx) { - struct ctx *ctx = NULL; - struct ctx_decl_scope *scope = NULL; + struct ctx_decl_scope *scope; + /* + * Destroy all scopes, from current one to the root scope. + */ - ctx = g_new(struct ctx, 1); if (!ctx) { - goto error; + goto end; } - /* Root declaration scope */ - scope = ctx_decl_scope_create(NULL); - if (!scope) { - goto error; - } + scope = ctx->current_scope; - ctx->stream_classes = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, (GDestroyNotify) bt_put); - if (!ctx->stream_classes) { - goto error; + while (scope) { + struct ctx_decl_scope *parent_scope = scope->parent_scope; + + ctx_decl_scope_destroy(scope); + scope = parent_scope; } - ctx->trace = trace; - ctx->efd = efd; - ctx->current_scope = scope; - ctx->is_trace_visited = FALSE; + bt_put(ctx->trace); - return ctx; + if (ctx->stream_classes) { + g_hash_table_destroy(ctx->stream_classes); + } -error: + free(ctx->trace_name_suffix); g_free(ctx); - ctx_decl_scope_destroy(scope); - return NULL; +end: + return; } /** - * Destroys a visitor context. + * Creates a new visitor context. * - * @param ctx Visitor context to destroy + * @param trace Associated trace + * @returns New visitor context, or NULL on error */ static -void ctx_destroy(struct ctx *ctx) +struct ctx *ctx_create(struct bt_trace *trace, + const struct ctf_metadata_decoder_config *decoder_config, + const char *trace_name_suffix) { - struct ctx_decl_scope *scope; - /* - * Destroy all scopes, from current one to the root scope. - */ + struct ctx *ctx = NULL; + struct ctx_decl_scope *scope = NULL; + + BT_ASSERT(decoder_config); + ctx = g_new0(struct ctx, 1); if (!ctx) { - goto end; + BT_LOGE_STR("Failed to allocate one visitor context."); + goto error; } - scope = ctx->current_scope; + /* Root declaration scope */ + scope = ctx_decl_scope_create(NULL); + if (!scope) { + BT_LOGE_STR("Cannot create declaration scope."); + goto error; + } - while (scope) { - struct ctx_decl_scope *parent_scope = scope->parent_scope; + ctx->stream_classes = g_hash_table_new_full(g_int64_hash, + g_int64_equal, g_free, (GDestroyNotify) bt_put); + if (!ctx->stream_classes) { + BT_LOGE_STR("Failed to allocate a GHashTable."); + goto error; + } - ctx_decl_scope_destroy(scope); - scope = parent_scope; + if (trace_name_suffix) { + ctx->trace_name_suffix = strdup(trace_name_suffix); + if (!ctx->trace_name_suffix) { + BT_LOGE_STR("Failed to copy string."); + goto error; + } } - g_hash_table_destroy(ctx->stream_classes); - g_free(ctx); + ctx->trace = trace; + ctx->current_scope = scope; + scope = NULL; + ctx->trace_bo = BT_BYTE_ORDER_NATIVE; + ctx->decoder_config = *decoder_config; + return ctx; -end: - return; +error: + ctx_destroy(ctx); + ctx_decl_scope_destroy(scope); + return NULL; } /** @@ -644,9 +627,10 @@ 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."); ret = -ENOMEM; goto end; } @@ -662,7 +646,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; @@ -678,7 +662,62 @@ end: static int visit_type_specifier_list(struct ctx *ctx, struct ctf_node *ts_list, - struct bt_ctf_field_type **decl); + struct bt_field_type **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) @@ -707,6 +746,7 @@ char *concatenate_unary_strings(struct bt_list_head *head) struct ctf_node *node; str = g_string_new(NULL); + BT_ASSERT(str); bt_list_for_each_entry(node, head, siblings) { char *src_string; @@ -836,6 +876,11 @@ int get_unary_unsigned(struct bt_list_head *head, uint64_t *value) int ret = 0; struct ctf_node *node; + if (bt_list_empty(head)) { + ret = -1; + goto end; + } + bt_list_for_each_entry(node, head, siblings) { int uexpr_type = node->u.unary_expression.type; int uexpr_link = node->u.unary_expression.link; @@ -843,6 +888,7 @@ int get_unary_unsigned(struct bt_list_head *head, uint64_t *value) uexpr_type != UNARY_UNSIGNED_CONSTANT || uexpr_link != UNARY_LINK_UNKNOWN || i != 0; if (cond) { + _BT_LOGE_NODE(node, "Invalid constant unsigned integer."); ret = -EINVAL; goto end; } @@ -885,7 +931,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; @@ -894,7 +939,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; @@ -937,6 +982,8 @@ int get_unary_uuid(struct bt_list_head *head, unsigned char *uuid) src_string = node->u.unary_expression.u.string; ret = bt_uuid_parse(src_string, uuid); if (ret) { + _BT_LOGE_NODE(node, + "Cannot parse UUID: uuid=\"%s\"", src_string); goto end; } } @@ -946,12 +993,14 @@ end: } static -int get_boolean(FILE *efd, struct ctf_node *unary_expr) +int get_boolean(struct ctf_node *unary_expr) { int ret = 0; if (unary_expr->type != NODE_UNARY_EXPRESSION) { - _FPERROR(efd, "%s", "expecting unary expression"); + _BT_LOGE_NODE(unary_expr, + "Expecting unary expression: node-type=%d", + unary_expr->type); ret = -EINVAL; goto end; } @@ -972,14 +1021,17 @@ int get_boolean(FILE *efd, struct ctf_node *unary_expr) } else if (!strcmp(str, "false") || !strcmp(str, "FALSE")) { ret = FALSE; } else { - _FPERROR(efd, "unexpected string \"%s\"", str); + _BT_LOGE_NODE(unary_expr, + "Unexpected boolean value: value=\"%s\"", str); ret = -EINVAL; goto end; } break; } default: - _FPERROR(efd, "%s", "unexpected unary expression type"); + _BT_LOGE_NODE(unary_expr, + "Unexpected unary expression type: node-type=%d", + unary_expr->u.unary_expression.type); ret = -EINVAL; goto end; } @@ -989,28 +1041,29 @@ end: } static -enum bt_ctf_byte_order byte_order_from_unary_expr(FILE *efd, - struct ctf_node *unary_expr) +enum bt_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 bt_byte_order bo = BT_BYTE_ORDER_UNKNOWN; if (unary_expr->u.unary_expression.type != UNARY_STRING) { - _FPERROR(efd, "%s", - "\"byte_order\" attribute: expecting string"); + _BT_LOGE_NODE(unary_expr, + "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`."); goto end; } str = unary_expr->u.unary_expression.u.string; if (!strcmp(str, "be") || !strcmp(str, "network")) { - bo = BT_CTF_BYTE_ORDER_BIG_ENDIAN; + bo = BT_BYTE_ORDER_BIG_ENDIAN; } else if (!strcmp(str, "le")) { - bo = BT_CTF_BYTE_ORDER_LITTLE_ENDIAN; + bo = BT_BYTE_ORDER_LITTLE_ENDIAN; } else if (!strcmp(str, "native")) { - bo = BT_CTF_BYTE_ORDER_NATIVE; + bo = BT_BYTE_ORDER_NATIVE; } else { - _FPERROR(efd, "unexpected \"byte_order\" attribute value \"%s\"; should be \"be\", \"le\", \"network\", or \"native\"", + _BT_LOGE_NODE(unary_expr, + "Unexpected \"byte_order\" attribute value: " + "expecting `be`, `le`, `network`, or `native`: value=\"%s\"", str); goto end; } @@ -1020,13 +1073,13 @@ end: } static -enum bt_ctf_byte_order get_real_byte_order(struct ctx *ctx, +enum bt_byte_order get_real_byte_order(struct ctx *ctx, struct ctf_node *uexpr) { - enum bt_ctf_byte_order bo = byte_order_from_unary_expr(ctx->efd, uexpr); + enum bt_byte_order bo = byte_order_from_unary_expr(uexpr); - if (bo == BT_CTF_BYTE_ORDER_NATIVE) { - bo = bt_ctf_trace_get_byte_order(ctx->trace); + if (bo == BT_BYTE_ORDER_NATIVE) { + bo = bt_trace_get_native_byte_order(ctx->trace); } return bo; @@ -1035,7 +1088,7 @@ 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 - 1ULL)); } static @@ -1045,6 +1098,9 @@ int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, int ret = 0; if (type_specifier->type != NODE_TYPE_SPECIFIER) { + _BT_LOGE_NODE(type_specifier, + "Unexpected node type: node-type=%d", + type_specifier->type); ret = -EINVAL; goto end; } @@ -1100,7 +1156,7 @@ int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, struct ctf_node *node = type_specifier->u.type_specifier.node; if (!node->u._struct.name) { - _PERROR("%s", "unexpected empty structure name"); + _BT_LOGE_NODE(node, "Unexpected empty structure field type name."); ret = -EINVAL; goto end; } @@ -1114,7 +1170,7 @@ int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, struct ctf_node *node = type_specifier->u.type_specifier.node; if (!node->u.variant.name) { - _PERROR("%s", "unexpected empty variant name"); + _BT_LOGE_NODE(node, "Unexpected empty variant field type name."); ret = -EINVAL; goto end; } @@ -1128,7 +1184,8 @@ int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, struct ctf_node *node = type_specifier->u.type_specifier.node; if (!node->u._enum.enum_id) { - _PERROR("%s", "unexpected empty enum name"); + _BT_LOGE_NODE(node, + "Unexpected empty enumeration field type (`enum`) name."); ret = -EINVAL; goto end; } @@ -1141,7 +1198,9 @@ int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier, case TYPESPEC_INTEGER: case TYPESPEC_STRING: default: - _PERROR("%s", "unknown specifier"); + _BT_LOGE_NODE(type_specifier->u.type_specifier.node, + "Unexpected type specifier type: %d", + type_specifier->u.type_specifier.type); ret = -EINVAL; goto end; } @@ -1154,7 +1213,7 @@ static int get_type_specifier_list_name(struct ctx *ctx, struct ctf_node *type_specifier_list, GString *str) { - int ret; + int ret = 0; struct ctf_node *iter; int alias_item_nr = 0; struct bt_list_head *head = @@ -1215,8 +1274,8 @@ 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) + struct bt_field_type **field_decl, + struct bt_field_type *nested_decl) { /* * During this whole function, nested_decl is always OURS, @@ -1231,6 +1290,9 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, if (node_type_declarator) { if (node_type_declarator->u.type_declarator.type == TYPEDEC_UNKNOWN) { + _BT_LOGE_NODE(node_type_declarator, + "Unexpected type declarator type: type=%d", + node_type_declarator->u.type_declarator.type); ret = -EINVAL; goto error; } @@ -1238,7 +1300,8 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, /* TODO: GCC bitfields not supported yet */ if (node_type_declarator->u.type_declarator.bitfield_len != NULL) { - _PERROR("%s", "GCC bitfields are not supported as of this version"); + _BT_LOGE_NODE(node_type_declarator, + "GCC bitfields are not supported as of this version."); ret = -EPERM; goto error; } @@ -1251,7 +1314,7 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, if (node_type_declarator && !bt_list_empty(pointers)) { GQuark qalias; - _BT_CTF_FIELD_TYPE_INIT(nested_decl_copy); + _BT_FIELD_TYPE_INIT(nested_decl_copy); /* * If we have a pointer declarator, it HAS to @@ -1263,17 +1326,19 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, ctx_decl_scope_lookup_alias(ctx->current_scope, g_quark_to_string(qalias), -1); if (!nested_decl) { - _PERROR("cannot find typealias \"%s\"", + _BT_LOGE_NODE(node_type_declarator, + "Cannot find type 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); + nested_decl_copy = bt_field_type_copy(nested_decl); BT_PUT(nested_decl); if (!nested_decl_copy) { - _PERROR("%s", "cannot copy nested declaration"); + _BT_LOGE_NODE(node_type_declarator, + "Cannot copy nested field type."); ret = -EINVAL; goto error; } @@ -1281,21 +1346,23 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, BT_MOVE(nested_decl, nested_decl_copy); /* Force integer's base to 16 since it's a pointer */ - if (bt_ctf_field_type_is_integer(nested_decl)) { - bt_ctf_field_type_integer_set_base(nested_decl, - BT_CTF_INTEGER_BASE_HEXADECIMAL); + if (bt_field_type_is_integer(nested_decl)) { + ret = bt_field_type_integer_set_base( + nested_decl, + BT_INTEGER_BASE_HEXADECIMAL); + BT_ASSERT(ret == 0); } } else { ret = visit_type_specifier_list(ctx, type_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); @@ -1307,6 +1374,10 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, const char *id = node_type_declarator->u.type_declarator.u.id; + if (id[0] == '_') { + id++; + } + *field_name = g_quark_from_string(id); } else { *field_name = 0; @@ -1316,22 +1387,25 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, goto end; } else { struct ctf_node *first; - _BT_CTF_FIELD_TYPE_INIT(decl); - _BT_CTF_FIELD_TYPE_INIT(outer_field_decl); + _BT_FIELD_TYPE_INIT(decl); + _BT_FIELD_TYPE_INIT(outer_field_decl); struct bt_list_head *length = &node_type_declarator-> u.type_declarator.u.nested.length; /* Create array/sequence, pass nested_decl as child */ if (bt_list_empty(length)) { - _PERROR("%s", - "expecting length field reference or value"); + _BT_LOGE_NODE(node_type_declarator, + "Expecting length field reference or value."); ret = -EINVAL; goto error; } first = _BT_LIST_FIRST_ENTRY(length, struct ctf_node, siblings); if (first->type != NODE_UNARY_EXPRESSION) { + _BT_LOGE_NODE(first, + "Unexpected node type: node-type=%d", + first->type); ret = -EINVAL; goto error; } @@ -1340,15 +1414,15 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, case UNARY_UNSIGNED_CONSTANT: { size_t len; - _BT_CTF_FIELD_TYPE_INIT(array_decl); + _BT_FIELD_TYPE_INIT(array_decl); len = first->u.unary_expression.u.unsigned_constant; - array_decl = bt_ctf_field_type_array_create(nested_decl, + array_decl = bt_field_type_array_create(nested_decl, len); BT_PUT(nested_decl); if (!array_decl) { - _PERROR("%s", - "cannot create array declaration"); + _BT_LOGE_NODE(first, + "Cannot create array field type."); ret = -ENOMEM; goto error; } @@ -1359,21 +1433,32 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, case UNARY_STRING: { /* Lookup unsigned integer definition, create seq. */ - _BT_CTF_FIELD_TYPE_INIT(seq_decl); + _BT_FIELD_TYPE_INIT(seq_decl); char *length_name = concatenate_unary_strings(length); + char *length_name_no_underscore; if (!length_name) { + _BT_LOGE_NODE(node_type_declarator, + "Cannot concatenate unary strings."); ret = -EINVAL; goto error; } - seq_decl = bt_ctf_field_type_sequence_create( - nested_decl, length_name); + 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 = bt_field_type_sequence_create( + nested_decl, length_name_no_underscore); + free(length_name_no_underscore); g_free(length_name); BT_PUT(nested_decl); if (!seq_decl) { - _PERROR("%s", - "cannot create sequence declaration"); + _BT_LOGE_NODE(node_type_declarator, + "Cannot create sequence field type."); ret = -ENOMEM; goto error; } @@ -1386,9 +1471,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. @@ -1404,18 +1489,18 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list, &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_ASSERT(outer_field_decl); BT_MOVE(*field_decl, outer_field_decl); } end: BT_PUT(nested_decl); - assert(*field_decl); + BT_ASSERT(*field_decl); return 0; @@ -1428,50 +1513,54 @@ error: static int visit_struct_decl_field(struct ctx *ctx, - struct bt_ctf_field_type *struct_decl, + struct bt_field_type *struct_decl, struct ctf_node *type_specifier_list, struct bt_list_head *type_declarators) { int ret = 0; struct ctf_node *iter; - _BT_CTF_FIELD_TYPE_INIT(field_decl); + _BT_FIELD_TYPE_INIT(field_decl); bt_list_for_each_entry(iter, type_declarators, siblings) { field_decl = NULL; GQuark qfield_name; const char *field_name; - _BT_CTF_FIELD_TYPE_INIT(efield_decl); + _BT_FIELD_TYPE_INIT(efield_decl); ret = visit_type_declarator(ctx, type_specifier_list, &qfield_name, iter, &field_decl, NULL); if (ret) { - assert(!field_decl); - _PERROR("%s", "unable to find structure field declaration type"); + BT_ASSERT(!field_decl); + _BT_LOGE_NODE(type_specifier_list, + "Cannot visit type 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( + bt_field_type_structure_get_field_type_by_name( struct_decl, field_name); if (efield_decl) { BT_PUT(efield_decl); - _PERROR("duplicate field \"%s\" in structure", - field_name); + _BT_LOGE_NODE(type_specifier_list, + "Duplicate field in structure field type: " + "field-name=\"%s\"", field_name); ret = -EINVAL; goto error; } /* Add field to structure */ - ret = bt_ctf_field_type_structure_add_field(struct_decl, + ret = bt_field_type_structure_add_field(struct_decl, field_decl, field_name); BT_PUT(field_decl); if (ret) { - _PERROR("cannot add field \"%s\" to structure", - g_quark_to_string(qfield_name)); + _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; } } @@ -1486,51 +1575,54 @@ error: static int visit_variant_decl_field(struct ctx *ctx, - struct bt_ctf_field_type *variant_decl, + struct bt_field_type *variant_decl, struct ctf_node *type_specifier_list, struct bt_list_head *type_declarators) { int ret = 0; struct ctf_node *iter; - _BT_CTF_FIELD_TYPE_INIT(field_decl); + _BT_FIELD_TYPE_INIT(field_decl); bt_list_for_each_entry(iter, type_declarators, siblings) { field_decl = NULL; GQuark qfield_name; const char *field_name; - _BT_CTF_FIELD_TYPE_INIT(efield_decl); + _BT_FIELD_TYPE_INIT(efield_decl); ret = visit_type_declarator(ctx, type_specifier_list, &qfield_name, iter, &field_decl, NULL); if (ret) { - assert(!field_decl); - _PERROR("%s", - "unable to find variant field declaration type"); + BT_ASSERT(!field_decl); + _BT_LOGE_NODE(type_specifier_list, + "Cannot visit type 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( + bt_field_type_variant_get_field_type_by_name( variant_decl, field_name); if (efield_decl) { BT_PUT(efield_decl); - _PERROR("duplicate field \"%s\" in variant", - field_name); + _BT_LOGE_NODE(type_specifier_list, + "Duplicate field in variant field type: " + "field-name=\"%s\"", field_name); ret = -EINVAL; goto error; } /* Add field to structure */ - ret = bt_ctf_field_type_variant_add_field(variant_decl, + ret = bt_field_type_variant_add_field(variant_decl, field_decl, field_name); BT_PUT(field_decl); if (ret) { - _PERROR("cannot add field \"%s\" to variant", - g_quark_to_string(qfield_name)); + _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; } } @@ -1550,21 +1642,23 @@ int visit_typedef(struct ctx *ctx, struct ctf_node *type_specifier_list, int ret = 0; GQuark qidentifier; struct ctf_node *iter; - _BT_CTF_FIELD_TYPE_INIT(type_decl); + _BT_FIELD_TYPE_INIT(type_decl); bt_list_for_each_entry(iter, type_declarators, siblings) { ret = visit_type_declarator(ctx, type_specifier_list, &qidentifier, iter, &type_decl, NULL); if (ret) { - _PERROR("%s", "problem creating type declaration"); + _BT_LOGE_NODE(iter, + "Cannot visit type 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)) { - _PERROR("%s", "typedef of untagged variant is not allowed"); + if (bt_field_type_is_variant(type_decl)) { + if (bt_field_type_variant_get_tag_name(type_decl)) { + _BT_LOGE_NODE(iter, + "Type definition of untagged variant field type is not allowed."); ret = -EPERM; goto end; } @@ -1573,7 +1667,8 @@ int visit_typedef(struct ctx *ctx, struct ctf_node *type_specifier_list, ret = ctx_decl_scope_register_alias(ctx->current_scope, g_quark_to_string(qidentifier), type_decl); if (ret) { - _PERROR("cannot register typedef \"%s\"", + _BT_LOGE_NODE(iter, + "Cannot register type definition: name=\"%s\"", g_quark_to_string(qidentifier)); goto end; } @@ -1593,7 +1688,7 @@ int visit_typealias(struct ctx *ctx, struct ctf_node *target, GQuark qalias; struct ctf_node *node; GQuark qdummy_field_name; - _BT_CTF_FIELD_TYPE_INIT(type_decl); + _BT_FIELD_TYPE_INIT(type_decl); /* Create target type declaration */ if (bt_list_empty(&target->u.typealias_target.type_declarators)) { @@ -1608,16 +1703,17 @@ int visit_typealias(struct ctx *ctx, struct ctf_node *target, target->u.typealias_target.type_specifier_list, &qdummy_field_name, node, &type_decl, NULL); if (ret) { - assert(!type_decl); - _PERROR("%s", "problem creating type declaration"); + BT_ASSERT(!type_decl); + _BT_LOGE_NODE(node, + "Cannot visit type 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)) { - _PERROR("%s", - "typealias of untagged variant is not allowed"); + if (bt_field_type_is_variant(type_decl)) { + if (bt_field_type_variant_get_tag_name(type_decl)) { + _BT_LOGE_NODE(target, + "Type definition of untagged variant field type is not allowed."); ret = -EPERM; goto end; } @@ -1628,7 +1724,9 @@ 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) { - _PERROR("%s", "expecting empty identifier"); + _BT_LOGE_NODE(target, + "Expecting empty identifier: id=\"%s\"", + g_quark_to_string(qdummy_field_name)); ret = -EINVAL; goto end; } @@ -1641,7 +1739,8 @@ int visit_typealias(struct ctx *ctx, struct ctf_node *target, ret = ctx_decl_scope_register_alias(ctx->current_scope, g_quark_to_string(qalias), type_decl); if (ret) { - _PERROR("cannot register typealias \"%s\"", + _BT_LOGE_NODE(node, + "Cannot register type alias: name=\"%s\"", g_quark_to_string(qalias)); goto end; } @@ -1654,7 +1753,7 @@ end: static int visit_struct_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, - struct bt_ctf_field_type *struct_decl) + struct bt_field_type *struct_decl) { int ret = 0; @@ -1664,8 +1763,9 @@ int visit_struct_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, entry_node->u._typedef.type_specifier_list, &entry_node->u._typedef.type_declarators); if (ret) { - _PERROR("%s", - "cannot add typedef in \"struct\" declaration"); + _BT_LOGE_NODE(entry_node, + "Cannot add type definition found in structure field type: ret=%d", + ret); goto end; } break; @@ -1673,8 +1773,9 @@ int visit_struct_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, ret = visit_typealias(ctx, entry_node->u.typealias.target, entry_node->u.typealias.alias); if (ret) { - _PERROR("%s", - "cannot add typealias in \"struct\" declaration"); + _BT_LOGE_NODE(entry_node, + "Cannot add type alias found in structure field type: ret=%d", + ret); goto end; } break; @@ -1690,7 +1791,8 @@ int visit_struct_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, } break; default: - _PERROR("unexpected node type: %d", (int) entry_node->type); + _BT_LOGE_NODE(entry_node, + "Unexpected node type: node-type=%d", entry_node->type); ret = -EINVAL; goto end; } @@ -1701,7 +1803,7 @@ end: static int visit_variant_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, - struct bt_ctf_field_type *variant_decl) + struct bt_field_type *variant_decl) { int ret = 0; @@ -1711,8 +1813,9 @@ int visit_variant_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, entry_node->u._typedef.type_specifier_list, &entry_node->u._typedef.type_declarators); if (ret) { - _PERROR("%s", - "cannot add typedef in \"variant\" declaration"); + _BT_LOGE_NODE(entry_node, + "Cannot add type definition found in variant field type: ret=%d", + ret); goto end; } break; @@ -1720,8 +1823,9 @@ int visit_variant_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, ret = visit_typealias(ctx, entry_node->u.typealias.target, entry_node->u.typealias.alias); if (ret) { - _PERROR("%s", - "cannot add typealias in \"variant\" declaration"); + _BT_LOGE_NODE(entry_node, + "Cannot add type alias found in variant field type: ret=%d", + ret); goto end; } break; @@ -1737,7 +1841,9 @@ int visit_variant_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, } break; default: - _PERROR("unexpected node type: %d", (int) entry_node->type); + _BT_LOGE_NODE(entry_node, + "Unexpected node type: node-type=%d", + entry_node->type); ret = -EINVAL; goto end; } @@ -1750,7 +1856,7 @@ 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_field_type **struct_decl) { int ret = 0; @@ -1758,9 +1864,10 @@ int visit_struct_decl(struct ctx *ctx, const char *name, /* For named struct (without body), lookup in declaration scope */ if (!has_body) { - _BT_CTF_FIELD_TYPE_INIT(struct_decl_copy); + _BT_FIELD_TYPE_INIT(struct_decl_copy); if (!name) { + BT_LOGE_STR("Bodyless structure field type: missing name."); ret = -EPERM; goto error; } @@ -1768,16 +1875,16 @@ int visit_struct_decl(struct ctx *ctx, const char *name, *struct_decl = ctx_decl_scope_lookup_struct(ctx->current_scope, name, -1); if (!*struct_decl) { - _PERROR("cannot find \"struct %s\"", name); + BT_LOGE("Cannot find structure field type: name=\"struct %s\"", + name); ret = -EINVAL; goto error; } /* Make a copy of it */ - struct_decl_copy = bt_ctf_field_type_copy(*struct_decl); + struct_decl_copy = bt_field_type_copy(*struct_decl); if (!struct_decl_copy) { - _PERROR("%s", - "cannot create copy of structure declaration"); + BT_LOGE_STR("Cannot create copy of structure field type."); ret = -EINVAL; goto error; } @@ -1788,14 +1895,14 @@ int visit_struct_decl(struct ctx *ctx, const char *name, uint64_t min_align_value = 0; if (name) { - _BT_CTF_FIELD_TYPE_INIT(estruct_decl); + _BT_FIELD_TYPE_INIT(estruct_decl); estruct_decl = ctx_decl_scope_lookup_struct( ctx->current_scope, name, 1); if (estruct_decl) { BT_PUT(estruct_decl); - _PERROR("\"struct %s\" already declared in local scope", - name); + BT_LOGE("Structure field type already declared in local scope: " + "name=\"struct %s\"", name); ret = -EINVAL; goto error; } @@ -1804,30 +1911,32 @@ 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) { - _PERROR("%s", "unexpected unary expression for structure declaration's \"align\" attribute"); + BT_LOGE("Unexpected unary expression for structure field type's `align` attribute: " + "ret=%d", ret); goto error; } } - *struct_decl = bt_ctf_field_type_structure_create(); + *struct_decl = bt_field_type_structure_create(); if (!*struct_decl) { - _PERROR("%s", "cannot create structure declaration"); + BT_LOGE_STR("Cannot create empty structure field type."); ret = -ENOMEM; goto error; } if (min_align_value != 0) { - ret = bt_ctf_field_type_set_alignment(*struct_decl, + ret = bt_field_type_set_alignment(*struct_decl, min_align_value); if (ret) { - _PERROR("%s", "failed to set structure's minimal alignment"); + BT_LOGE("Cannot set structure field type's alignment: " + "ret=%d", ret); goto error; } } ret = ctx_push_scope(ctx); if (ret) { - _PERROR("%s", "cannot push scope"); + BT_LOGE_STR("Cannot push scope."); goto error; } @@ -1835,6 +1944,9 @@ int visit_struct_decl(struct ctx *ctx, const char *name, ret = visit_struct_decl_entry(ctx, entry_node, *struct_decl); if (ret) { + _BT_LOGE_NODE(entry_node, + "Cannot visit structure field type entry: " + "ret=%d", ret); ctx_pop_scope(ctx); goto error; } @@ -1846,8 +1958,8 @@ int visit_struct_decl(struct ctx *ctx, const char *name, ret = ctx_decl_scope_register_struct(ctx->current_scope, name, *struct_decl); if (ret) { - _PERROR("cannot register \"struct %s\" in declaration scope", - name); + BT_LOGE("Cannot register structure field type in declaration scope: " + "name=\"struct %s\", ret=%d", name, ret); goto error; } } @@ -1864,18 +1976,19 @@ error: 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 bt_field_type **variant_decl) { int ret = 0; - _BT_CTF_FIELD_TYPE_INIT(untagged_variant_decl); + _BT_FIELD_TYPE_INIT(untagged_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); + _BT_FIELD_TYPE_INIT(variant_decl_copy); if (!name) { + BT_LOGE_STR("Bodyless variant field type: missing name."); ret = -EPERM; goto error; } @@ -1884,17 +1997,17 @@ int visit_variant_decl(struct ctx *ctx, const char *name, ctx_decl_scope_lookup_variant(ctx->current_scope, name, -1); if (!untagged_variant_decl) { - _PERROR("cannot find \"variant %s\"", name); + BT_LOGE("Cannot find variant field type: name=\"variant %s\"", + name); ret = -EINVAL; goto error; } /* Make a copy of it */ - variant_decl_copy = bt_ctf_field_type_copy( + variant_decl_copy = bt_field_type_copy( untagged_variant_decl); if (!variant_decl_copy) { - _PERROR("%s", - "cannot create copy of structure declaration"); + BT_LOGE_STR("Cannot create copy of variant field type."); ret = -EINVAL; goto error; } @@ -1904,30 +2017,30 @@ int visit_variant_decl(struct ctx *ctx, const char *name, struct ctf_node *entry_node; if (name) { - struct bt_ctf_field_type *evariant_decl = + struct bt_field_type *evariant_decl = ctx_decl_scope_lookup_struct(ctx->current_scope, name, 1); if (evariant_decl) { BT_PUT(evariant_decl); - _PERROR("\"variant %s\" already declared in local scope", - name); + BT_LOGE("Variant field type already declared in local scope: " + "name=\"variant %s\"", name); ret = -EINVAL; goto error; } } - untagged_variant_decl = bt_ctf_field_type_variant_create(NULL, + untagged_variant_decl = bt_field_type_variant_create(NULL, NULL); if (!untagged_variant_decl) { - _PERROR("%s", "cannot create variant declaration"); + BT_LOGE_STR("Cannot create empty variant field type."); ret = -ENOMEM; goto error; } ret = ctx_push_scope(ctx); if (ret) { - _PERROR("%s", "cannot push scope"); + BT_LOGE_STR("Cannot push scope."); goto error; } @@ -1935,6 +2048,9 @@ int visit_variant_decl(struct ctx *ctx, const char *name, ret = visit_variant_decl_entry(ctx, entry_node, untagged_variant_decl); if (ret) { + _BT_LOGE_NODE(entry_node, + "Cannot visit variant field type entry: " + "ret=%d", ret); ctx_pop_scope(ctx); goto error; } @@ -1947,8 +2063,8 @@ int visit_variant_decl(struct ctx *ctx, const char *name, ctx->current_scope, name, untagged_variant_decl); if (ret) { - _PERROR("cannot register \"variant %s\" in declaration scope", - name); + BT_LOGE("Cannot register variant field type in declaration scope: " + "name=\"variant %s\", ret=%d", name, ret); goto error; } } @@ -1965,17 +2081,28 @@ int visit_variant_decl(struct ctx *ctx, const char *name, * 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); + char *tag_no_underscore = + remove_underscores_from_field_ref(tag); + + if (!tag_no_underscore) { + /* remove_underscores_from_field_ref() logs errors */ + goto error; + } + + ret = bt_field_type_variant_set_tag_name( + untagged_variant_decl, tag_no_underscore); + free(tag_no_underscore); if (ret) { + BT_LOGE("Cannot set variant field type's tag name: " + "tag-name=\"%s\"", tag); goto error; } BT_MOVE(*variant_decl, untagged_variant_decl); } - assert(!untagged_variant_decl); - assert(*variant_decl); + BT_ASSERT(!untagged_variant_decl); + BT_ASSERT(*variant_decl); return 0; @@ -1988,20 +2115,23 @@ error: 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 bt_field_type *enum_decl, int64_t *last, bt_bool is_signed) { int ret = 0; int nr_vals = 0; struct ctf_node *iter; int64_t start = 0, end = 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; if (iter->type != NODE_UNARY_EXPRESSION) { - _PERROR("wrong unary expression for enumeration label \"%s\"", + _BT_LOGE_NODE(iter, + "Wrong expression for enumeration field type label: " + "node-type=%d, label=\"%s\"", iter->type, label); ret = -EINVAL; goto error; @@ -2022,14 +2152,18 @@ int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator, iter->u.unary_expression.u.unsigned_constant; break; default: - _PERROR("invalid enumeration entry: \"%s\"", - label); + _BT_LOGE_NODE(iter, + "Invalid enumeration field type entry: " + "expecting constant signed or unsigned integer: " + "node-type=%d, label=\"%s\"", + iter->u.unary_expression.type, label); ret = -EINVAL; goto error; } if (nr_vals > 1) { - _PERROR("invalid enumeration entry: \"%s\"", + _BT_LOGE_NODE(iter, + "Invalid enumeration field type entry: label=\"%s\"", label); ret = -EINVAL; goto error; @@ -2048,16 +2182,32 @@ int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator, *last = end + 1; + if (label[0] == '_') { + /* + * Strip the first underscore of any enumeration field + * type's label in case this enumeration FT is used as + * a variant FT tag later. The variant FT 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]; + } + if (is_signed) { - ret = bt_ctf_field_type_enumeration_add_mapping(enum_decl, label, - start, end); + ret = bt_field_type_enumeration_signed_add_mapping(enum_decl, + effective_label, start, end); } else { - ret = bt_ctf_field_type_enumeration_add_mapping_unsigned(enum_decl, - label, (uint64_t) start, (uint64_t) end); + ret = bt_field_type_enumeration_unsigned_add_mapping(enum_decl, + effective_label, (uint64_t) start, (uint64_t) end); } if (ret) { - _PERROR("cannot add mapping to enumeration for label \"%s\"", - label); + _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; } @@ -2072,19 +2222,20 @@ 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 bt_field_type **enum_decl) { int ret = 0; GQuark qdummy_id; - _BT_CTF_FIELD_TYPE_INIT(integer_decl); + _BT_FIELD_TYPE_INIT(integer_decl); *enum_decl = NULL; /* For named enum (without body), lookup in declaration scope */ if (!has_body) { - _BT_CTF_FIELD_TYPE_INIT(enum_decl_copy); + _BT_FIELD_TYPE_INIT(enum_decl_copy); if (!name) { + BT_LOGE_STR("Bodyless enumeration field type: missing name."); ret = -EPERM; goto error; } @@ -2092,16 +2243,16 @@ int visit_enum_decl(struct ctx *ctx, const char *name, *enum_decl = ctx_decl_scope_lookup_enum(ctx->current_scope, name, -1); if (!*enum_decl) { - _PERROR("cannot find \"enum %s\"", name); + BT_LOGE("Cannot find enumeration field type: " + "name=\"enum %s\"", name); ret = -EINVAL; goto error; } /* Make a copy of it */ - enum_decl_copy = bt_ctf_field_type_copy(*enum_decl); + enum_decl_copy = bt_field_type_copy(*enum_decl); if (!enum_decl_copy) { - _PERROR("%s", - "cannot create copy of enumeration declaration"); + BT_LOGE_STR("Cannot create copy of enumeration field type."); ret = -EINVAL; goto error; } @@ -2113,14 +2264,14 @@ int visit_enum_decl(struct ctx *ctx, const char *name, int64_t last_value = 0; if (name) { - _BT_CTF_FIELD_TYPE_INIT(eenum_decl); + _BT_FIELD_TYPE_INIT(eenum_decl); eenum_decl = ctx_decl_scope_lookup_enum( ctx->current_scope, name, 1); if (eenum_decl) { BT_PUT(eenum_decl); - _PERROR("\"enum %s\" already declared in local scope", - name); + BT_LOGE("Enumeration field type already declared in local scope: " + "name=\"enum %s\"", name); ret = -EINVAL; goto error; } @@ -2130,7 +2281,7 @@ int visit_enum_decl(struct ctx *ctx, const char *name, integer_decl = ctx_decl_scope_lookup_alias( ctx->current_scope, "int", -1); if (!integer_decl) { - _PERROR("%s", "cannot find \"int\" type for enumeration"); + BT_LOGE_STR("Cannot find implicit `int` field type alias for enumeration field type."); ret = -EINVAL; goto error; } @@ -2138,23 +2289,26 @@ int visit_enum_decl(struct ctx *ctx, const char *name, ret = visit_type_declarator(ctx, container_type, &qdummy_id, NULL, &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)) { - _PERROR("%s", "container type for enumeration is not an integer"); + if (!bt_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_common_field_type_id_string( + bt_field_type_get_type_id(integer_decl))); ret = -EINVAL; goto error; } - *enum_decl = bt_ctf_field_type_enumeration_create(integer_decl); + *enum_decl = bt_field_type_enumeration_create(integer_decl); if (!*enum_decl) { - _PERROR("%s", "cannot create enumeration declaration"); + BT_LOGE_STR("Cannot create enumeration field type."); ret = -ENOMEM; goto error; } @@ -2162,8 +2316,11 @@ int visit_enum_decl(struct ctx *ctx, const char *name, 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)); + bt_field_type_integer_is_signed(integer_decl)); if (ret) { + _BT_LOGE_NODE(iter, + "Cannot visit enumeration field type entry: " + "ret=%d", ret); goto error; } } @@ -2172,6 +2329,8 @@ 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: " + "ret=%d", ret); goto error; } } @@ -2191,30 +2350,34 @@ error: static int visit_type_specifier(struct ctx *ctx, struct ctf_node *type_specifier_list, - struct bt_ctf_field_type **decl) + struct bt_field_type **decl) { int ret = 0; GString *str = NULL; - _BT_CTF_FIELD_TYPE_INIT(decl_copy); + _BT_FIELD_TYPE_INIT(decl_copy); *decl = NULL; str = g_string_new(""); ret = get_type_specifier_list_name(ctx, type_specifier_list, str); if (ret) { + _BT_LOGE_NODE(type_specifier_list, + "Cannot get type specifier list's name: ret=%d", ret); goto error; } *decl = ctx_decl_scope_lookup_alias(ctx->current_scope, str->str, -1); if (!*decl) { - _PERROR("cannot find type alias \"%s\"", str->str); + _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); + decl_copy = bt_field_type_copy(*decl); if (!decl_copy) { - _PERROR("%s", "cannot create copy of type declaration"); + _BT_LOGE_NODE(type_specifier_list, + "Cannot create field type copy."); ret = -EINVAL; goto error; } @@ -2238,18 +2401,18 @@ error: static int visit_integer_decl(struct ctx *ctx, struct bt_list_head *expressions, - struct bt_ctf_field_type **integer_decl) + struct bt_field_type **integer_decl) { int set = 0; int ret = 0; - int signedness = 0; + bt_bool 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_byte_order(ctx->trace); + struct bt_clock_class *mapped_clock = NULL; + enum bt_string_encoding encoding = BT_STRING_ENCODING_NONE; + enum bt_integer_base base = BT_INTEGER_BASE_DECIMAL; + enum bt_byte_order byte_order = + bt_trace_get_native_byte_order(ctx->trace); *integer_decl = NULL; @@ -2263,20 +2426,26 @@ int visit_integer_decl(struct ctx *ctx, siblings); if (left->u.unary_expression.type != UNARY_STRING) { + _BT_LOGE_NODE(left, + "Unexpected unary expression type: type=%d", + left->u.unary_expression.type); ret = -EINVAL; goto error; } if (!strcmp(left->u.unary_expression.u.string, "signed")) { if (_IS_SET(&set, _INTEGER_SIGNED_SET)) { - _PERROR_DUP_ATTR("signed", - "integer declaration"); + _BT_LOGE_DUP_ATTR(left, "signed", + "integer field type"); ret = -EPERM; goto error; } - signedness = get_boolean(ctx->efd, right); + signedness = get_boolean(right); if (signedness < 0) { + _BT_LOGE_NODE(right, + "Invalid boolean value for integer field type's `signed` attribute: " + "ret=%d", ret); ret = -EINVAL; goto error; } @@ -2285,15 +2454,17 @@ int visit_integer_decl(struct ctx *ctx, } else if (!strcmp(left->u.unary_expression.u.string, "byte_order")) { if (_IS_SET(&set, _INTEGER_BYTE_ORDER_SET)) { - _PERROR_DUP_ATTR("byte_order", - "integer declaration"); + _BT_LOGE_DUP_ATTR(left, "byte_order", + "integer field type"); ret = -EPERM; goto error; } byte_order = get_real_byte_order(ctx, right); - if (byte_order == BT_CTF_BYTE_ORDER_UNKNOWN) { - _PERROR("%s", "invalid \"byte_order\" attribute in integer declaration"); + if (byte_order == BT_BYTE_ORDER_UNKNOWN) { + _BT_LOGE_NODE(right, + "Invalid `byte_order` attribute in integer field type: " + "ret=%d", ret); ret = -EINVAL; goto error; } @@ -2301,26 +2472,36 @@ int visit_integer_decl(struct ctx *ctx, _SET(&set, _INTEGER_BYTE_ORDER_SET); } else if (!strcmp(left->u.unary_expression.u.string, "size")) { if (_IS_SET(&set, _INTEGER_SIZE_SET)) { - _PERROR_DUP_ATTR("size", - "integer declaration"); + _BT_LOGE_DUP_ATTR(left, "size", + "integer field type"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { - _PERROR("%s", "invalid \"size\" attribute in integer declaration: expecting unsigned constant"); + _BT_LOGE_NODE(right, + "Invalid `size` attribute in integer field type: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); ret = -EINVAL; goto error; } size = right->u.unary_expression.u.unsigned_constant; if (size == 0) { - _PERROR("%s", "invalid \"size\" attribute in integer declaration: expecting positive constant"); + _BT_LOGE_NODE(right, + "Invalid `size` attribute in integer field type: " + "expecting positive constant integer: " + "size=%" PRIu64, size); ret = -EINVAL; goto error; } else if (size > 64) { - _PERROR("%s", "invalid \"size\" attribute in integer declaration: integers over 64-bit are not supported as of this version"); + _BT_LOGE_NODE(right, + "Invalid `size` attribute in integer field type: " + "integer fields over 64 bits are not supported as of this version: " + "size=%" PRIu64, size); ret = -EINVAL; goto error; } @@ -2329,15 +2510,19 @@ int visit_integer_decl(struct ctx *ctx, } else if (!strcmp(left->u.unary_expression.u.string, "align")) { if (_IS_SET(&set, _INTEGER_ALIGN_SET)) { - _PERROR_DUP_ATTR("align", - "integer declaration"); + _BT_LOGE_DUP_ATTR(left, "align", + "integer field type"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { - _PERROR("%s", "invalid \"align\" attribute in integer declaration: expecting unsigned constant"); + _BT_LOGE_NODE(right, + "Invalid `align` attribute in integer field type: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); ret = -EINVAL; goto error; } @@ -2345,7 +2530,10 @@ int visit_integer_decl(struct ctx *ctx, alignment = right->u.unary_expression.u.unsigned_constant; if (!is_align_valid(alignment)) { - _PERROR("%s", "invalid \"align\" attribute in integer declaration: expecting power of two"); + _BT_LOGE_NODE(right, + "Invalid `align` attribute in integer field type: " + "expecting power of two: " + "align=%" PRIu64, alignment); ret = -EINVAL; goto error; } @@ -2353,7 +2541,8 @@ int visit_integer_decl(struct ctx *ctx, _SET(&set, _INTEGER_ALIGN_SET); } else if (!strcmp(left->u.unary_expression.u.string, "base")) { if (_IS_SET(&set, _INTEGER_BASE_SET)) { - _PERROR_DUP_ATTR("base", "integer declaration"); + _BT_LOGE_DUP_ATTR(left, "base", + "integer field type"); ret = -EPERM; goto error; } @@ -2366,19 +2555,21 @@ int visit_integer_decl(struct ctx *ctx, switch (constant) { case 2: - base = BT_CTF_INTEGER_BASE_BINARY; + base = BT_INTEGER_BASE_BINARY; break; case 8: - base = BT_CTF_INTEGER_BASE_OCTAL; + base = BT_INTEGER_BASE_OCTAL; break; case 10: - base = BT_CTF_INTEGER_BASE_DECIMAL; + base = BT_INTEGER_BASE_DECIMAL; break; case 16: - base = BT_CTF_INTEGER_BASE_HEXADECIMAL; + base = BT_INTEGER_BASE_HEXADECIMAL; break; default: - _PERROR("invalid \"base\" attribute in integer declaration: %" PRIu64, + _BT_LOGE_NODE(right, + "Invalid `base` attribute in integer field type: " + "base=%" PRIu64, right->u.unary_expression.u.unsigned_constant); ret = -EINVAL; goto error; @@ -2390,7 +2581,8 @@ int visit_integer_decl(struct ctx *ctx, char *s_right = concatenate_unary_strings( &expression->u.ctf_expression.right); if (!s_right) { - _PERROR("%s", "unexpected unary expression for integer declaration's \"base\" attribute"); + _BT_LOGE_NODE(right, + "Unexpected unary expression for integer field type's `base` attribute."); ret = -EINVAL; goto error; } @@ -2400,23 +2592,24 @@ 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_INTEGER_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_INTEGER_BASE_HEXADECIMAL; } else if (!strcmp(s_right, "octal") || !strcmp(s_right, "oct") || !strcmp(s_right, "o")) { - base = BT_CTF_INTEGER_BASE_OCTAL; + base = BT_INTEGER_BASE_OCTAL; } else if (!strcmp(s_right, "binary") || !strcmp(s_right, "b")) { - base = BT_CTF_INTEGER_BASE_BINARY; + base = BT_INTEGER_BASE_BINARY; } else { - _PERROR("unexpected unary expression for integer declaration's \"base\" attribute: \"%s\"", - s_right); + _BT_LOGE_NODE(right, + "Unexpected unary expression for integer field type's `base` attribute: " + "base=\"%s\"", s_right); g_free(s_right); ret = -EINVAL; goto error; @@ -2426,7 +2619,9 @@ int visit_integer_decl(struct ctx *ctx, break; } default: - _PERROR("%s", "invalid \"base\" attribute in integer declaration: expecting unsigned constant or unary string"); + _BT_LOGE_NODE(right, + "Invalid `base` attribute in integer field type: " + "expecting unsigned constant integer or unary string."); ret = -EINVAL; goto error; } @@ -2437,14 +2632,16 @@ int visit_integer_decl(struct ctx *ctx, char *s_right; if (_IS_SET(&set, _INTEGER_ENCODING_SET)) { - _PERROR_DUP_ATTR("encoding", - "integer declaration"); + _BT_LOGE_DUP_ATTR(left, "encoding", + "integer field type"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_STRING) { - _PERROR("%s", "invalid \"encoding\" attribute in integer declaration: expecting unary string"); + _BT_LOGE_NODE(right, + "Invalid `encoding` attribute in integer field type: " + "expecting unary string."); ret = -EINVAL; goto error; } @@ -2452,7 +2649,8 @@ int visit_integer_decl(struct ctx *ctx, s_right = concatenate_unary_strings( &expression->u.ctf_expression.right); if (!s_right) { - _PERROR("%s", "unexpected unary expression for integer declaration's \"encoding\" attribute"); + _BT_LOGE_NODE(right, + "Unexpected unary expression for integer field type's `encoding` attribute."); ret = -EINVAL; goto error; } @@ -2461,14 +2659,16 @@ int visit_integer_decl(struct ctx *ctx, !strcmp(s_right, "utf8") || !strcmp(s_right, "utf-8") || !strcmp(s_right, "UTF-8")) { - encoding = BT_CTF_STRING_ENCODING_UTF8; + encoding = BT_STRING_ENCODING_UTF8; } else if (!strcmp(s_right, "ASCII") || !strcmp(s_right, "ascii")) { - encoding = BT_CTF_STRING_ENCODING_ASCII; + encoding = BT_STRING_ENCODING_ASCII; } else if (!strcmp(s_right, "none")) { - encoding = BT_CTF_STRING_ENCODING_NONE; + encoding = BT_STRING_ENCODING_NONE; } else { - _PERROR("invalid \"encoding\" attribute in integer declaration: unknown encoding \"%s\"", + _BT_LOGE_NODE(right, + "Invalid `encoding` attribute in integer field type: " + "unknown encoding: encoding=\"%s\"", s_right); g_free(s_right); ret = -EINVAL; @@ -2481,13 +2681,16 @@ int visit_integer_decl(struct ctx *ctx, const char *clock_name; if (_IS_SET(&set, _INTEGER_MAP_SET)) { - _PERROR_DUP_ATTR("map", "integer declaration"); + _BT_LOGE_DUP_ATTR(left, "map", + "integer field type"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_STRING) { - _PERROR("%s", "invalid \"map\" attribute in integer declaration: expecting unary string"); + _BT_LOGE_NODE(right, + "Invalid `map` attribute in integer field type: " + "expecting unary string."); ret = -EINVAL; goto error; } @@ -2500,22 +2703,27 @@ int visit_integer_decl(struct ctx *ctx, &expression->u.ctf_expression.right); if (!s_right) { - _PERROR("%s", "unexpected unary expression for integer declaration's \"map\" attribute"); + _BT_LOGE_NODE(right, + "Unexpected unary expression for integer field type's `map` attribute."); ret = -EINVAL; goto error; } - _PWARNING("invalid \"map\" attribute in integer declaration: unknown clock: \"%s\"", + _BT_LOGE_NODE(right, + "Invalid `map` attribute in integer field type: " + "cannot find clock class at this point: name=\"%s\"", s_right); _SET(&set, _INTEGER_MAP_SET); g_free(s_right); continue; } - mapped_clock = bt_ctf_trace_get_clock_class_by_name( + mapped_clock = bt_trace_get_clock_class_by_name( ctx->trace, clock_name); if (!mapped_clock) { - _PERROR("invalid \"map\" attribute in integer declaration: cannot find clock \"%s\"", + _BT_LOGE_NODE(right, + "Invalid `map` attribute in integer field type: " + "cannot find clock class at this point: name=\"%s\"", clock_name); ret = -EINVAL; goto error; @@ -2523,14 +2731,15 @@ int visit_integer_decl(struct ctx *ctx, _SET(&set, _INTEGER_MAP_SET); } else { - _PWARNING("unknown attribute \"%s\" in integer declaration", + _BT_LOGW_NODE(left, + "Unknown attribute in integer field type: " + "attr-name=\"%s\"", left->u.unary_expression.u.string); } } if (!_IS_SET(&set, _INTEGER_SIZE_SET)) { - _PERROR("%s", - "missing \"size\" attribute in integer declaration"); + BT_LOGE_STR("Missing `size` attribute in integer field type."); ret = -EPERM; goto error; } @@ -2545,30 +2754,30 @@ int visit_integer_decl(struct ctx *ctx, } } - *integer_decl = bt_ctf_field_type_integer_create((unsigned int) size); + *integer_decl = bt_field_type_integer_create((unsigned int) size); if (!*integer_decl) { - _PERROR("%s", "cannot create integer declaration"); + 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, + ret = bt_field_type_integer_set_is_signed(*integer_decl, signedness); + ret |= bt_field_type_integer_set_base(*integer_decl, base); + ret |= bt_field_type_integer_set_encoding(*integer_decl, encoding); + ret |= bt_field_type_set_alignment(*integer_decl, (unsigned int) alignment); - ret |= bt_ctf_field_type_set_byte_order(*integer_decl, byte_order); + ret |= bt_field_type_set_byte_order(*integer_decl, byte_order); if (mapped_clock) { /* Move clock */ - ret |= bt_ctf_field_type_integer_set_mapped_clock_class( + ret |= bt_field_type_integer_set_mapped_clock_class( *integer_decl, mapped_clock); bt_put(mapped_clock); mapped_clock = NULL; } if (ret) { - _PERROR("%s", "cannot configure integer declaration"); + BT_LOGE_STR("Cannot configure integer field type."); ret = -EINVAL; goto error; } @@ -2588,14 +2797,14 @@ error: static int visit_floating_point_number_decl(struct ctx *ctx, struct bt_list_head *expressions, - struct bt_ctf_field_type **float_decl) + struct bt_field_type **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_byte_order(ctx->trace); + enum bt_byte_order byte_order = + bt_trace_get_native_byte_order(ctx->trace); *float_decl = NULL; @@ -2609,21 +2818,26 @@ int visit_floating_point_number_decl(struct ctx *ctx, siblings); if (left->u.unary_expression.type != UNARY_STRING) { + _BT_LOGE_NODE(left, + "Unexpected unary expression type: type=%d", + left->u.unary_expression.type); ret = -EINVAL; goto error; } if (!strcmp(left->u.unary_expression.u.string, "byte_order")) { if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) { - _PERROR_DUP_ATTR("byte_order", - "floating point number declaration"); + _BT_LOGE_DUP_ATTR(left, "byte_order", + "floating point number field type"); ret = -EPERM; goto error; } byte_order = get_real_byte_order(ctx, right); - if (byte_order == BT_CTF_BYTE_ORDER_UNKNOWN) { - _PERROR("%s", "invalid \"byte_order\" attribute in floating point number declaration"); + if (byte_order == BT_BYTE_ORDER_UNKNOWN) { + _BT_LOGE_NODE(right, + "Invalid `byte_order` attribute in floating point number field type: " + "ret=%d", ret); ret = -EINVAL; goto error; } @@ -2632,15 +2846,19 @@ int visit_floating_point_number_decl(struct ctx *ctx, } else if (!strcmp(left->u.unary_expression.u.string, "exp_dig")) { if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) { - _PERROR_DUP_ATTR("exp_dig", - "floating point number declaration"); + _BT_LOGE_DUP_ATTR(left, "exp_dig", + "floating point number field type"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { - _PERROR("%s", "invalid \"exp_dig\" attribute in floating point number declaration: expecting unsigned constant"); + _BT_LOGE_NODE(right, + "Invalid `exp_dig` attribute in floating point number field type: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); ret = -EINVAL; goto error; } @@ -2650,15 +2868,19 @@ int visit_floating_point_number_decl(struct ctx *ctx, } else if (!strcmp(left->u.unary_expression.u.string, "mant_dig")) { if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) { - _PERROR_DUP_ATTR("mant_dig", - "floating point number declaration"); + _BT_LOGE_DUP_ATTR(left, "mant_dig", + "floating point number field type"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { - _PERROR("%s", "invalid \"mant_dig\" attribute in floating point number declaration: expecting unsigned constant"); + _BT_LOGE_NODE(right, + "Invalid `mant_dig` attribute in floating point number field type: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); ret = -EINVAL; goto error; } @@ -2669,15 +2891,19 @@ int visit_floating_point_number_decl(struct ctx *ctx, } else if (!strcmp(left->u.unary_expression.u.string, "align")) { if (_IS_SET(&set, _FLOAT_ALIGN_SET)) { - _PERROR_DUP_ATTR("align", - "floating point number declaration"); + _BT_LOGE_DUP_ATTR(left, "align", + "floating point number field type"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { - _PERROR("%s", "invalid \"align\" attribute in floating point number declaration: expecting unsigned constant"); + _BT_LOGE_NODE(right, + "Invalid `align` attribute in floating point number field type: " + "expecting unsigned constant integer: " + "node-type=%d", + right->u.unary_expression.type); ret = -EINVAL; goto error; } @@ -2686,26 +2912,31 @@ int visit_floating_point_number_decl(struct ctx *ctx, unsigned_constant; if (!is_align_valid(alignment)) { - _PERROR("%s", "invalid \"align\" attribute in floating point number declaration: expecting power of two"); + _BT_LOGE_NODE(right, + "Invalid `align` attribute in floating point number field type: " + "expecting power of two: " + "align=%" PRIu64, alignment); ret = -EINVAL; goto error; } _SET(&set, _FLOAT_ALIGN_SET); } else { - _PWARNING("unknown attribute \"%s\" in floating point number declaration", + _BT_LOGW_NODE(left, + "Unknown attribute in floating point number field type: " + "attr-name=\"%s\"", left->u.unary_expression.u.string); } } if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) { - _PERROR("%s", "missing \"mant_dig\" attribute in floating point number declaration"); + BT_LOGE_STR("Missing `mant_dig` attribute in floating point number field type."); ret = -EPERM; goto error; } if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) { - _PERROR("%s", "missing \"exp_dig\" attribute in floating point number declaration"); + BT_LOGE_STR("Missing `exp_dig` attribute in floating point number field type."); ret = -EPERM; goto error; } @@ -2720,23 +2951,21 @@ int visit_floating_point_number_decl(struct ctx *ctx, } } - *float_decl = bt_ctf_field_type_floating_point_create(); + *float_decl = bt_field_type_floating_point_create(); if (!*float_decl) { - _PERROR("%s", - "cannot create floating point number declaration"); + BT_LOGE_STR("Cannot create floating point number field type."); ret = -ENOMEM; goto error; } - ret = bt_ctf_field_type_floating_point_set_exponent_digits( + ret = bt_field_type_floating_point_set_exponent_digits( *float_decl, exp_dig); - ret |= bt_ctf_field_type_floating_point_set_mantissa_digits( + ret |= bt_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); + ret |= bt_field_type_set_byte_order(*float_decl, byte_order); + ret |= bt_field_type_set_alignment(*float_decl, alignment); if (ret) { - _PERROR("%s", - "cannot configure floating point number declaration"); + BT_LOGE_STR("Cannot configure floating point number field type."); ret = -EINVAL; goto error; } @@ -2752,12 +2981,12 @@ error: static int visit_string_decl(struct ctx *ctx, struct bt_list_head *expressions, - struct bt_ctf_field_type **string_decl) + struct bt_field_type **string_decl) { int set = 0; int ret = 0; struct ctf_node *expression; - enum bt_ctf_string_encoding encoding = BT_CTF_STRING_ENCODING_UTF8; + enum bt_string_encoding encoding = BT_STRING_ENCODING_UTF8; *string_decl = NULL; @@ -2771,6 +3000,9 @@ int visit_string_decl(struct ctx *ctx, siblings); if (left->u.unary_expression.type != UNARY_STRING) { + _BT_LOGE_NODE(left, + "Unexpected unary expression type: type=%d", + left->u.unary_expression.type); ret = -EINVAL; goto error; } @@ -2779,14 +3011,16 @@ int visit_string_decl(struct ctx *ctx, char *s_right; if (_IS_SET(&set, _STRING_ENCODING_SET)) { - _PERROR_DUP_ATTR("encoding", - "string declaration"); + _BT_LOGE_DUP_ATTR(left, "encoding", + "string field type"); ret = -EPERM; goto error; } if (right->u.unary_expression.type != UNARY_STRING) { - _PERROR("%s", "invalid \"encoding\" attribute in string declaration: expecting unary string"); + _BT_LOGE_NODE(right, + "Invalid `encoding` attribute in string field type: " + "expecting unary string."); ret = -EINVAL; goto error; } @@ -2794,7 +3028,8 @@ int visit_string_decl(struct ctx *ctx, s_right = concatenate_unary_strings( &expression->u.ctf_expression.right); if (!s_right) { - _PERROR("%s", "unexpected unary expression for string declaration's \"encoding\" attribute"); + _BT_LOGE_NODE(right, + "Unexpected unary expression for string field type's `encoding` attribute."); ret = -EINVAL; goto error; } @@ -2803,14 +3038,16 @@ int visit_string_decl(struct ctx *ctx, !strcmp(s_right, "utf8") || !strcmp(s_right, "utf-8") || !strcmp(s_right, "UTF-8")) { - encoding = BT_CTF_STRING_ENCODING_UTF8; + encoding = BT_STRING_ENCODING_UTF8; } else if (!strcmp(s_right, "ASCII") || !strcmp(s_right, "ascii")) { - encoding = BT_CTF_STRING_ENCODING_ASCII; + encoding = BT_STRING_ENCODING_ASCII; } else if (!strcmp(s_right, "none")) { - encoding = BT_CTF_STRING_ENCODING_NONE; + encoding = BT_STRING_ENCODING_NONE; } else { - _PERROR("invalid \"encoding\" attribute in string declaration: unknown encoding \"%s\"", + _BT_LOGE_NODE(right, + "Invalid `encoding` attribute in string field type: " + "unknown encoding: encoding=\"%s\"", s_right); g_free(s_right); ret = -EINVAL; @@ -2820,21 +3057,23 @@ int visit_string_decl(struct ctx *ctx, g_free(s_right); _SET(&set, _STRING_ENCODING_SET); } else { - _PWARNING("unknown attribute \"%s\" in string declaration", + _BT_LOGW_NODE(left, + "Unknown attribute in string field type: " + "attr-name=\"%s\"", left->u.unary_expression.u.string); } } - *string_decl = bt_ctf_field_type_string_create(); + *string_decl = bt_field_type_string_create(); if (!*string_decl) { - _PERROR("%s", "cannot create string declaration"); + BT_LOGE_STR("Cannot create string field type."); ret = -ENOMEM; goto error; } - ret = bt_ctf_field_type_string_set_encoding(*string_decl, encoding); + ret = bt_field_type_string_set_encoding(*string_decl, encoding); if (ret) { - _PERROR("%s", "cannot configure string declaration"); + BT_LOGE_STR("Cannot configure string field type."); ret = -EINVAL; goto error; } @@ -2850,7 +3089,7 @@ error: static int visit_type_specifier_list(struct ctx *ctx, struct ctf_node *ts_list, - struct bt_ctf_field_type **decl) + struct bt_field_type **decl) { int ret = 0; struct ctf_node *first, *node; @@ -2858,6 +3097,8 @@ int visit_type_specifier_list(struct ctx *ctx, *decl = NULL; if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) { + _BT_LOGE_NODE(ts_list, + "Unexpected node type: node-type=%d", ts_list->type); ret = -EINVAL; goto error; } @@ -2865,6 +3106,8 @@ int visit_type_specifier_list(struct ctx *ctx, first = _BT_LIST_FIRST_ENTRY(&ts_list->u.type_specifier_list.head, struct ctf_node, siblings); if (first->type != NODE_TYPE_SPECIFIER) { + _BT_LOGE_NODE(first, + "Unexpected node type: node-type=%d", first->type); ret = -EINVAL; goto error; } @@ -2876,7 +3119,7 @@ int visit_type_specifier_list(struct ctx *ctx, ret = visit_integer_decl(ctx, &node->u.integer.expressions, decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; @@ -2884,7 +3127,7 @@ int visit_type_specifier_list(struct ctx *ctx, ret = visit_floating_point_number_decl(ctx, &node->u.floating_point.expressions, decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; @@ -2892,7 +3135,7 @@ int visit_type_specifier_list(struct ctx *ctx, ret = visit_string_decl(ctx, &node->u.string.expressions, decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; @@ -2902,7 +3145,7 @@ int visit_type_specifier_list(struct ctx *ctx, node->u._struct.has_body, &node->u._struct.min_align, decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; @@ -2912,7 +3155,7 @@ int visit_type_specifier_list(struct ctx *ctx, &node->u.variant.declaration_list, node->u.variant.has_body, decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; @@ -2922,7 +3165,7 @@ int visit_type_specifier_list(struct ctx *ctx, &node->u._enum.enumerator_list, node->u._enum.has_body, decl); if (ret) { - assert(!*decl); + BT_ASSERT(!*decl); goto error; } break; @@ -2942,18 +3185,22 @@ int visit_type_specifier_list(struct ctx *ctx, case TYPESPEC_ID_TYPE: ret = visit_type_specifier(ctx, ts_list, decl); if (ret) { - assert(!*decl); + _BT_LOGE_NODE(first, + "Cannot visit type specifier: ret=%d", + ret); + BT_ASSERT(!*decl); goto error; } break; default: - _PERROR("unexpected node type: %d", - (int) first->u.type_specifier.type); + _BT_LOGE_NODE(first, + "Unexpected type specifier type: node-type=%d", + first->u.type_specifier.type); ret = -EINVAL; goto error; } - assert(*decl); + BT_ASSERT(*decl); return 0; @@ -2965,20 +3212,20 @@ error: static int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, - struct bt_ctf_event_class *event_class, int64_t *stream_id, + struct bt_event_class *event_class, int64_t *stream_id, int *set) { int ret = 0; char *left = NULL; - _BT_CTF_FIELD_TYPE_INIT(decl); + _BT_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); if (ret) { - _PERROR("%s", - "cannot add typedef in \"event\" declaration"); + _BT_LOGE_NODE(node, + "Cannot add type definition found in event class."); goto error; } break; @@ -2986,7 +3233,8 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, ret = visit_typealias(ctx, node->u.typealias.target, node->u.typealias.alias); if (ret) { - _PERROR("%s", "cannot add typealias in \"event\" declaration"); + _BT_LOGE_NODE(node, + "Cannot add type alias found in event class."); goto error; } break; @@ -2994,6 +3242,7 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, { left = concatenate_unary_strings(&node->u.ctf_expression.left); if (!left) { + _BT_LOGE_NODE(node, "Cannot concatenate unary strings."); ret = -EINVAL; goto error; } @@ -3001,49 +3250,59 @@ 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)) { - _PERROR_DUP_ATTR("name", "event declaration"); + _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)) { - _PERROR_DUP_ATTR("id", "event declaration"); + _BT_LOGE_DUP_ATTR(node, "id", + "event class"); ret = -EPERM; goto error; } ret = get_unary_unsigned(&node->u.ctf_expression.right, (uint64_t *) &id); - if (ret || id < 0) { - _PERROR("%s", "unexpected unary expression for event declaration's \"id\" attribute"); + /* Only read "id" if get_unary_unsigned() succeeded. */ + if (ret || (!ret && id < 0)) { + _BT_LOGE_NODE(node, + "Unexpected unary expression for event class's `id` attribute."); ret = -EINVAL; goto error; } - ret = bt_ctf_event_class_set_id(event_class, id); + ret = bt_event_class_set_id(event_class, id); if (ret) { - _PERROR("%s", - "cannot set event declaration's ID"); + _BT_LOGE_NODE(node, + "Cannot set event class's ID: " + "id=%" PRId64, id); goto error; } _SET(set, _EVENT_ID_SET); } else if (!strcmp(left, "stream_id")) { if (_IS_SET(set, _EVENT_STREAM_ID_SET)) { - _PERROR_DUP_ATTR("stream_id", - "event declaration"); + _BT_LOGE_DUP_ATTR(node, "stream_id", + "event class"); ret = -EPERM; goto error; } ret = get_unary_unsigned(&node->u.ctf_expression.right, (uint64_t *) stream_id); - if (ret || *stream_id < 0) { - _PERROR("%s", "unexpected unary expression for event declaration's \"stream_id\" attribute"); + /* + * Only read "stream_id" if get_unary_unsigned() + * succeeded. + */ + if (ret || (!ret && *stream_id < 0)) { + _BT_LOGE_NODE(node, + "Unexpected unary expression for event class's `stream_id` attribute."); ret = -EINVAL; goto error; } @@ -3051,7 +3310,8 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, _SET(set, _EVENT_STREAM_ID_SET); } else if (!strcmp(left, "context")) { if (_IS_SET(set, _EVENT_CONTEXT_SET)) { - _PERROR("%s", "duplicate \"context\" entry in event declaration"); + _BT_LOGE_NODE(node, + "Duplicate `context` entry in event class."); ret = -EPERM; goto error; } @@ -3062,23 +3322,26 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, struct ctf_node, siblings), &decl); if (ret) { - _PERROR("%s", "cannot create event context declaration"); + _BT_LOGE_NODE(node, + "Cannot create event class's context field type."); goto error; } - assert(decl); - ret = bt_ctf_event_class_set_context_type( + BT_ASSERT(decl); + ret = bt_event_class_set_context_field_type( event_class, decl); BT_PUT(decl); if (ret) { - _PERROR("%s", "cannot set event's context declaration"); + _BT_LOGE_NODE(node, + "Cannot set event class's context field type."); goto error; } _SET(set, _EVENT_CONTEXT_SET); } else if (!strcmp(left, "fields")) { if (_IS_SET(set, _EVENT_FIELDS_SET)) { - _PERROR("%s", "duplicate \"fields\" entry in event declaration"); + _BT_LOGE_NODE(node, + "Duplicate `fields` entry in event class."); ret = -EPERM; goto error; } @@ -3089,28 +3352,30 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, struct ctf_node, siblings), &decl); if (ret) { - _PERROR("%s", "cannot create event payload declaration"); + _BT_LOGE_NODE(node, + "Cannot create event class's payload field type."); goto error; } - assert(decl); - ret = bt_ctf_event_class_set_payload_type( + BT_ASSERT(decl); + ret = bt_event_class_set_payload_field_type( event_class, decl); BT_PUT(decl); if (ret) { - _PERROR("%s", "cannot set event's payload declaration"); + _BT_LOGE_NODE(node, + "Cannot set event class's payload field type."); goto error; } _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 = + BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED; if (_IS_SET(set, _EVENT_LOGLEVEL_SET)) { - _PERROR_DUP_ATTR("loglevel", - "event declaration"); + _BT_LOGE_DUP_ATTR(node, "loglevel", + "event class"); ret = -EPERM; goto error; } @@ -3118,43 +3383,80 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, ret = get_unary_unsigned(&node->u.ctf_expression.right, &loglevel_value); if (ret) { - _PERROR("%s", "unexpected unary expression for event declaration's \"loglevel\" attribute"); + _BT_LOGE_NODE(node, + "Unexpected unary expression for event class's `loglevel` attribute."); ret = -EINVAL; goto error; } - value_obj = bt_value_integer_create_init(loglevel_value); - if (!value_obj) { - _PERROR("%s", "cannot allocate memory for loglevel value object"); - ret = -ENOMEM; - goto error; - } - if (bt_ctf_event_class_set_attribute(event_class, - "loglevel", value_obj) != BT_VALUE_STATUS_OK) { - _PERROR("%s", "cannot set loglevel value"); - 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) { - _PERROR("%s", "cannot set loglevel string"); - ret = -EINVAL; - bt_put(str_obj); + + if (log_level != BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) { + ret = bt_event_class_set_log_level( + event_class, log_level); + if (ret) { + _BT_LOGE_NODE(node, + "Cannot set event class's log level."); goto error; } - bt_put(str_obj); } - bt_put(value_obj); + _SET(set, _EVENT_LOGLEVEL_SET); } else if (!strcmp(left, "model.emf.uri")) { char *right; if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) { - _PERROR_DUP_ATTR("model.emf.uri", - "event declaration"); + _BT_LOGE_DUP_ATTR(node, "model.emf.uri", + "event class"); ret = -EPERM; goto error; } @@ -3162,18 +3464,31 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node, right = concatenate_unary_strings( &node->u.ctf_expression.right); if (!right) { - _PERROR("%s", "unexpected unary expression for event declaration's \"model.emf.uri\" attribute"); + _BT_LOGE_NODE(node, + "Unexpected unary expression for event class's `model.emf.uri` attribute."); ret = -EINVAL; goto error; } - // TODO: FIXME: set model EMF URI here + if (strlen(right) == 0) { + _BT_LOGW_NODE(node, + "Not setting event class's EMF URI because it's empty."); + } else { + ret = bt_event_class_set_emf_uri( + event_class, right); + if (ret) { + _BT_LOGE_NODE(node, + "Cannot set event class's EMF URI."); + goto error; + } + } g_free(right); _SET(set, _EVENT_MODEL_EMF_URI_SET); } else { - _PWARNING("unknown attribute \"%s\" in event declaration", - left); + _BT_LOGW_NODE(node, + "Unknown attribute in event class: " + "attr-name=\"%s\"", left); } g_free(left); @@ -3212,6 +3527,8 @@ char *get_event_decl_name(struct ctx *ctx, struct ctf_node *node) left = concatenate_unary_strings(&iter->u.ctf_expression.left); if (!left) { + _BT_LOGE_NODE(iter, + "Cannot concatenate unary strings."); goto error; } @@ -3219,7 +3536,8 @@ char *get_event_decl_name(struct ctx *ctx, struct ctf_node *node) name = concatenate_unary_strings( &iter->u.ctf_expression.right); if (!name) { - _PERROR("%s", "unexpected unary expression for event declaration's \"name\" attribute"); + _BT_LOGE_NODE(iter, + "Unexpected unary expression for event class's `name` attribute."); goto error; } } @@ -3242,21 +3560,25 @@ error: static int reset_event_decl_types(struct ctx *ctx, - struct bt_ctf_event_class *event_class) + struct bt_event_class *event_class) { int ret = 0; /* Context type. */ - ret = bt_ctf_event_class_set_context_type(event_class, NULL); + ret = bt_event_class_set_context_field_type(event_class, NULL); if (ret) { - _PERROR("%s", "cannot set initial NULL event context"); + BT_LOGE("Cannot reset initial event class's context field type: " + "event-name=\"%s\"", + bt_event_class_get_name(event_class)); goto end; } /* Event payload. */ - ret = bt_ctf_event_class_set_payload_type(event_class, NULL); + ret = bt_event_class_set_payload_field_type(event_class, NULL); if (ret) { - _PERROR("%s", "cannot set initial NULL event payload"); + BT_LOGE("Cannot reset initial event class's payload field type: " + "event-name=\"%s\"", + bt_event_class_get_name(event_class)); goto end; } end: @@ -3265,28 +3587,28 @@ end: static int reset_stream_decl_types(struct ctx *ctx, - struct bt_ctf_stream_class *stream_class) + struct bt_stream_class *stream_class) { int ret = 0; /* Packet context. */ - ret = bt_ctf_stream_class_set_packet_context_type(stream_class, NULL); + ret = bt_stream_class_set_packet_context_field_type(stream_class, NULL); if (ret) { - _PERROR("%s", "cannot set initial empty packet context"); + 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); + ret = bt_stream_class_set_event_header_field_type(stream_class, NULL); if (ret) { - _PERROR("%s", "cannot set initial empty event header"); + 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); + ret = bt_stream_class_set_event_context_field_type(stream_class, NULL); if (ret) { - _PERROR("%s", "cannot set initial empty stream event context"); + BT_LOGE_STR("Cannot reset initial stream class's event context field type."); goto end; } end: @@ -3294,14 +3616,14 @@ end: } static -struct bt_ctf_stream_class *create_reset_stream_class(struct ctx *ctx) +struct bt_stream_class *create_reset_stream_class(struct ctx *ctx) { int ret; - struct bt_ctf_stream_class *stream_class; + struct bt_stream_class *stream_class; - stream_class = bt_ctf_stream_class_create(NULL); + stream_class = bt_stream_class_create(NULL); if (!stream_class) { - _PERROR("%s", "cannot create stream class"); + BT_LOGE_STR("Cannot create empty stream class."); goto error; } @@ -3331,10 +3653,11 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node) struct ctf_node *iter; int64_t stream_id = -1; 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; + struct bt_event_class *event_class = NULL; + struct bt_event_class *eevent_class; + struct bt_stream_class *stream_class = NULL; struct bt_list_head *decl_list = &node->u.event.declaration_list; + bool pop_scope = false; if (node->visited) { goto end; @@ -3343,176 +3666,357 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node) node->visited = TRUE; event_name = get_event_decl_name(ctx, node); if (!event_name) { - _PERROR("%s", - "missing \"name\" attribute in event declaration"); + _BT_LOGE_NODE(node, + "Missing `name` attribute in event class."); ret = -EPERM; goto error; } - event_class = bt_ctf_event_class_create(event_name); + event_class = bt_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) { - _PERROR("%s", "cannot push scope"); + BT_LOGE_STR("Cannot push scope."); goto error; } + pop_scope = true; + bt_list_for_each_entry(iter, decl_list, siblings) { ret = visit_event_decl_entry(ctx, iter, event_class, &stream_id, &set); if (ret) { + _BT_LOGE_NODE(iter, "Cannot visit event class's entry: " + "ret=%d", ret); goto error; } } if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) { GList *keys = NULL; - struct bt_ctf_stream_class *new_stream_class; + int64_t *new_stream_id; + struct bt_stream_class *new_stream_class; + size_t stream_class_count = + g_hash_table_size(ctx->stream_classes) + + bt_trace_get_stream_class_count(ctx->trace); - /* Allow missing stream_id if there is only a single stream */ - switch (g_hash_table_size(ctx->stream_classes)) { + /* + * Allow missing stream_id if there is only a single + * stream class. + */ + switch (stream_class_count) { case 0: - /* Create stream if there's none */ + /* Create implicit stream class if there's none */ + stream_id = 0; 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); + ret = bt_stream_class_set_id(new_stream_class, + stream_id); if (ret) { - _PERROR("%s", "cannot set stream's ID"); + _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; + new_stream_id = g_new0(int64_t, 1); + if (!new_stream_id) { + BT_LOGE_STR("Failed to allocate a int64_t."); + ret = -ENOMEM; + goto error; + } + + *new_stream_id = stream_id; /* Move reference to visitor's context */ g_hash_table_insert(ctx->stream_classes, - (gpointer) stream_id, new_stream_class); + new_stream_id, new_stream_class); + new_stream_id = NULL; new_stream_class = NULL; - break; case 1: - /* Single stream: get its ID */ - keys = g_hash_table_get_keys(ctx->stream_classes); - stream_id = (int64_t) keys->data; - g_list_free(keys); - keys = NULL; + /* 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 { + BT_ASSERT(bt_trace_get_stream_class_count( + ctx->trace) == 1); + stream_class = + bt_trace_get_stream_class_by_index( + ctx->trace, 0); + BT_ASSERT(stream_class); + stream_id = bt_stream_class_get_id( + stream_class); + BT_PUT(stream_class); + } break; default: - _PERROR("%s", "missing \"stream_id\" attribute in event declaration"); + _BT_LOGE_NODE(node, + "Missing `stream_id` attribute in event class."); ret = -EPERM; goto error; } } + BT_ASSERT(stream_id >= 0); - - assert(stream_id >= 0); - - /* We have the stream ID now; borrow the stream class if found */ - stream_class = g_hash_table_lookup(ctx->stream_classes, - (gpointer) stream_id); + /* We have the stream ID now; get the stream class if found */ + stream_class = g_hash_table_lookup(ctx->stream_classes, &stream_id); + bt_get(stream_class); if (!stream_class) { - _PERROR("cannot find stream class with ID %" PRId64, + stream_class = bt_trace_get_stream_class_by_id(ctx->trace, stream_id); - ret = -EINVAL; - goto error; + if (!stream_class) { + _BT_LOGE_NODE(node, + "Cannot find stream class at this point: " + "id=%" PRId64, stream_id); + ret = -EINVAL; + goto error; + } } + BT_ASSERT(stream_class); + if (!_IS_SET(&set, _EVENT_ID_SET)) { /* Allow only one event without ID per stream */ - if (bt_ctf_stream_class_get_event_class_count(stream_class) != + if (bt_stream_class_get_event_class_count(stream_class) != 0) { - _PERROR("%s", - "missing \"id\" field in event declaration"); + _BT_LOGE_NODE(node, + "Missing `id` attribute in event class."); ret = -EPERM; goto error; } /* Automatic ID */ - ret = bt_ctf_event_class_set_id(event_class, 0); + ret = bt_event_class_set_id(event_class, 0); if (ret) { - _PERROR("%s", "cannot set event's ID"); + _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); + event_id = bt_event_class_get_id(event_class); if (event_id < 0) { - _PERROR("%s", "cannot get event's ID"); + _BT_LOGE_NODE(node, "Cannot get event class's ID."); ret = -EINVAL; goto error; } - eevent_class = bt_ctf_stream_class_get_event_class_by_id(stream_class, + eevent_class = bt_stream_class_get_event_class_by_id(stream_class, event_id); if (eevent_class) { BT_PUT(eevent_class); - _PERROR("%s", "duplicate event with ID %" PRId64 " in same stream"); + _BT_LOGE_NODE(node, + "Duplicate event class (same ID) in the same stream class: " + "id=%" PRId64, event_id); ret = -EEXIST; goto error; } - eevent_class = bt_ctf_stream_class_get_event_class_by_name(stream_class, - event_name); - if (eevent_class) { - BT_PUT(eevent_class); - eevent_class = NULL; - _PERROR("%s", - "duplicate event with name \"%s\" in same stream"); - ret = -EEXIST; + ret = bt_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; } + goto end; + +error: + bt_put(event_class); + +end: + if (pop_scope) { + ctx_pop_scope(ctx); + } + g_free(event_name); - ret = bt_ctf_stream_class_add_event_class(stream_class, event_class); - BT_PUT(event_class); - event_class = NULL; + bt_put(stream_class); + return ret; +} + +static +int auto_map_field_to_trace_clock_class(struct ctx *ctx, + struct bt_field_type *ft) +{ + struct bt_clock_class *clock_class_to_map_to = NULL; + struct bt_clock_class *mapped_clock_class = NULL; + int ret = 0; + int64_t clock_class_count; + + if (!ft || !bt_field_type_is_integer(ft)) { + goto end; + } + + mapped_clock_class = + bt_field_type_integer_get_mapped_clock_class(ft); + if (mapped_clock_class) { + goto end; + } + + clock_class_count = bt_trace_get_clock_class_count(ctx->trace); + BT_ASSERT(clock_class_count >= 0); + + 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("default", + 1000000000); + if (!clock_class_to_map_to) { + BT_LOGE_STR("Cannot create a clock class."); + ret = -1; + goto end; + } + + ret = bt_trace_add_clock_class(ctx->trace, + clock_class_to_map_to); + if (ret) { + BT_LOGE_STR("Cannot add clock class to trace."); + goto end; + } + break; + case 1: + /* + * Only one clock class exists in the trace at + * this point: use this one. + */ + clock_class_to_map_to = + bt_trace_get_clock_class_by_index(ctx->trace, 0); + BT_ASSERT(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; + } + BT_ASSERT(clock_class_to_map_to); + ret = bt_field_type_integer_set_mapped_clock_class(ft, + clock_class_to_map_to); if (ret) { - _PERROR("%s", "cannot add event class to stream class"); - goto error; + BT_LOGE("Cannot map field type's field to trace's clock class: " + "clock-class-name=\"%s\", ret=%d", + bt_clock_class_get_name(clock_class_to_map_to), + ret); + goto end; } end: - return 0; + bt_put(clock_class_to_map_to); + bt_put(mapped_clock_class); + return ret; +} -error: - g_free(event_name); - BT_PUT(event_class); +static +int auto_map_fields_to_trace_clock_class(struct ctx *ctx, + struct bt_field_type *root_ft, const char *field_name) +{ + int ret = 0; + int64_t i, count; - /* stream_class is borrowed; it still belongs to the hash table */ + if (!root_ft) { + goto end; + } + if (!bt_field_type_is_structure(root_ft) && + !bt_field_type_is_variant(root_ft)) { + goto end; + } + + if (bt_field_type_is_structure(root_ft)) { + count = bt_field_type_structure_get_field_count(root_ft); + } else { + count = bt_field_type_variant_get_field_count(root_ft); + } + + BT_ASSERT(count >= 0); + + for (i = 0; i < count; i++) { + _BT_FIELD_TYPE_INIT(ft); + const char *name; + + if (bt_field_type_is_structure(root_ft)) { + ret = bt_field_type_structure_get_field_by_index( + root_ft, &name, &ft, i); + } else if (bt_field_type_is_variant(root_ft)) { + ret = bt_field_type_variant_get_field_by_index( + root_ft, &name, &ft, i); + } + + BT_ASSERT(ret == 0); + + if (strcmp(name, field_name) == 0) { + ret = auto_map_field_to_trace_clock_class(ctx, ft); + if (ret) { + BT_LOGE("Cannot automatically map field to trace's clock class: " + "field-name=\"%s\"", field_name); + bt_put(ft); + goto end; + } + } + + ret = auto_map_fields_to_trace_clock_class(ctx, ft, field_name); + bt_put(ft); + if (ret) { + BT_LOGE("Cannot automatically map structure or variant field type's fields to trace's clock class: " + "field-name=\"%s\", root-field-name=\"%s\"", + field_name, name); + goto end; + } + } + +end: 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 bt_stream_class *stream_class, int *set) { int ret = 0; char *left = NULL; - _BT_CTF_FIELD_TYPE_INIT(decl); + _BT_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); if (ret) { - _PERROR("%s", - "cannot add typedef in \"stream\" declaration"); + _BT_LOGE_NODE(node, + "Cannot add type definition found in stream class."); goto error; } break; @@ -3520,7 +4024,8 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, ret = visit_typealias(ctx, node->u.typealias.target, node->u.typealias.alias); if (ret) { - _PERROR("%s", "cannot add typealias in \"stream\" declaration"); + _BT_LOGE_NODE(node, + "Cannot add type alias found in stream class."); goto error; } break; @@ -3528,6 +4033,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, { left = concatenate_unary_strings(&node->u.ctf_expression.left); if (!left) { + _BT_LOGE_NODE(node, "Cannot concatenate unary strings."); ret = -EINVAL; goto error; } @@ -3537,39 +4043,44 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, gpointer ptr; if (_IS_SET(set, _STREAM_ID_SET)) { - _PERROR_DUP_ATTR("id", "stream declaration"); + _BT_LOGE_DUP_ATTR(node, "id", + "stream declaration"); ret = -EPERM; goto error; } ret = get_unary_unsigned(&node->u.ctf_expression.right, (uint64_t *) &id); - if (ret || id < 0) { - _PERROR("%s", "unexpected unary expression for stream declaration's \"id\" attribute"); + /* Only read "id" if get_unary_unsigned() succeeded. */ + if (ret || (!ret && id < 0)) { + _BT_LOGE_NODE(node, + "Unexpected unary expression for stream class's `id` attribute."); ret = -EINVAL; goto error; } - ptr = g_hash_table_lookup(ctx->stream_classes, - (gpointer) id); + ptr = g_hash_table_lookup(ctx->stream_classes, &id); if (ptr) { - _PERROR("duplicate stream with ID %" PRId64, + _BT_LOGE_NODE(node, + "Duplicate stream class (same ID): id=%" PRId64, id); ret = -EEXIST; goto error; } - ret = bt_ctf_stream_class_set_id(stream_class, id); + ret = bt_stream_class_set_id(stream_class, id); if (ret) { - _PERROR("%s", - "cannot set stream declaration's ID"); + _BT_LOGE_NODE(node, + "Cannot set stream class's ID: " + "id=%" PRId64 ", ret=%d", id, ret); goto error; } _SET(set, _STREAM_ID_SET); } else if (!strcmp(left, "event.header")) { if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) { - _PERROR("%s", "duplicate \"event.header\" entry in stream declaration"); + _BT_LOGE_NODE(node, + "Duplicate `event.header` entry in stream class."); ret = -EPERM; goto error; } @@ -3580,24 +4091,34 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, struct ctf_node, siblings), &decl); if (ret) { - _PERROR("%s", "cannot create event header declaration"); + _BT_LOGE_NODE(node, + "Cannot create stream class's event header field type."); goto error; } - assert(decl); + BT_ASSERT(decl); + ret = auto_map_fields_to_trace_clock_class(ctx, + decl, "timestamp"); + if (ret) { + _BT_LOGE_NODE(node, + "Cannot automatically map specific event header field type fields named `timestamp` to trace's clock class."); + goto error; + } - ret = bt_ctf_stream_class_set_event_header_type( + ret = bt_stream_class_set_event_header_field_type( stream_class, decl); BT_PUT(decl); if (ret) { - _PERROR("%s", "cannot set stream's event header declaration"); + _BT_LOGE_NODE(node, + "Cannot set stream class's event header field type."); goto error; } _SET(set, _STREAM_EVENT_HEADER_SET); } else if (!strcmp(left, "event.context")) { if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) { - _PERROR("%s", "duplicate \"event.context\" entry in stream declaration"); + _BT_LOGE_NODE(node, + "Duplicate `event.context` entry in stream class."); ret = -EPERM; goto error; } @@ -3608,24 +4129,27 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, struct ctf_node, siblings), &decl); if (ret) { - _PERROR("%s", "cannot create stream event context declaration"); + _BT_LOGE_NODE(node, + "Cannot create stream class's event context field type."); goto error; } - assert(decl); + BT_ASSERT(decl); - ret = bt_ctf_stream_class_set_event_context_type( + ret = bt_stream_class_set_event_context_field_type( stream_class, decl); BT_PUT(decl); if (ret) { - _PERROR("%s", "cannot set stream's event context declaration"); + _BT_LOGE_NODE(node, + "Cannot set stream class's event context field type."); goto error; } _SET(set, _STREAM_EVENT_CONTEXT_SET); } else if (!strcmp(left, "packet.context")) { if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) { - _PERROR("%s", "duplicate \"packet.context\" entry in stream declaration"); + _BT_LOGE_NODE(node, + "Duplicate `packet.context` entry in stream class."); ret = -EPERM; goto error; } @@ -3636,24 +4160,42 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node, struct ctf_node, siblings), &decl); if (ret) { - _PERROR("%s", "cannot create packet context declaration"); + _BT_LOGE_NODE(node, + "Cannot create stream class's packet context field type."); + goto error; + } + + BT_ASSERT(decl); + ret = auto_map_fields_to_trace_clock_class(ctx, + decl, "timestamp_begin"); + if (ret) { + _BT_LOGE_NODE(node, + "Cannot automatically map specific packet context field type fields named `timestamp_begin` to trace's clock class."); goto error; } - assert(decl); + ret = auto_map_fields_to_trace_clock_class(ctx, + decl, "timestamp_end"); + if (ret) { + _BT_LOGE_NODE(node, + "Cannot automatically map specific packet context field type fields named `timestamp_end` to trace's clock class."); + goto error; + } - ret = bt_ctf_stream_class_set_packet_context_type( + ret = bt_stream_class_set_packet_context_field_type( stream_class, decl); BT_PUT(decl); if (ret) { - _PERROR("%s", "cannot set stream's packet context declaration"); + _BT_LOGE_NODE(node, + "Cannot set stream class's packet context field type."); goto error; } _SET(set, _STREAM_PACKET_CONTEXT_SET); } else { - _PWARNING("unknown attribute \"%s\" in stream declaration", - left); + _BT_LOGW_NODE(node, + "Unknown attribute in stream class: " + "attr-name=\"%s\"", left); } g_free(left); @@ -3679,10 +4221,12 @@ static int visit_stream_decl(struct ctx *ctx, struct ctf_node *node) { int64_t id; + int64_t *new_id; int set = 0; int ret = 0; struct ctf_node *iter; - struct bt_ctf_stream_class *stream_class = NULL; + struct bt_stream_class *stream_class = NULL; + struct bt_stream_class *existing_stream_class = NULL; struct bt_list_head *decl_list = &node->u.stream.declaration_list; if (node->visited) { @@ -3692,19 +4236,23 @@ 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) { - _PERROR("%s", "cannot push scope"); + BT_LOGE_STR("Cannot push scope."); goto error; } bt_list_for_each_entry(iter, decl_list, siblings) { ret = visit_stream_decl_entry(ctx, iter, stream_class, &set); if (ret) { + _BT_LOGE_NODE(iter, + "Cannot visit stream class's entry: " + "ret=%d", ret); ctx_pop_scope(ctx); goto error; } @@ -3714,29 +4262,34 @@ int visit_stream_decl(struct ctx *ctx, struct ctf_node *node) 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); + _BT_FIELD_TYPE_INIT(stream_id_decl); + _BT_FIELD_TYPE_INIT(packet_header_decl); packet_header_decl = - bt_ctf_trace_get_packet_header_type(ctx->trace); + bt_trace_get_packet_header_field_type(ctx->trace); if (!packet_header_decl) { - _PERROR("%s", - "cannot get trace packet header declaration"); + _BT_LOGE_NODE(node, + "Stream class has a `id` attribute, " + "but trace has no packet header field type."); goto error; } stream_id_decl = - bt_ctf_field_type_structure_get_field_type_by_name( + bt_field_type_structure_get_field_type_by_name( packet_header_decl, "stream_id"); BT_PUT(packet_header_decl); if (!stream_id_decl) { - _PERROR("%s", "missing \"stream_id\" field in packet header declaration, but \"id\" attribute is declared for stream"); + _BT_LOGE_NODE(node, + "Stream class has a `id` attribute, " + "but trace's packet header field type has no `stream_id` field."); goto error; } - if (!bt_ctf_field_type_is_integer(stream_id_decl)) { + if (!bt_field_type_is_integer(stream_id_decl)) { BT_PUT(stream_id_decl); - _PERROR("%s", "\"stream_id\" field in packet header declaration is not an integer"); + _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."); goto error; } @@ -3744,34 +4297,59 @@ int visit_stream_decl(struct ctx *ctx, struct ctf_node *node) } else { /* Allow only _one_ ID-less stream */ if (g_hash_table_size(ctx->stream_classes) != 0) { - _PERROR("%s", - "missing \"id\" field in stream declaration"); + _BT_LOGE_NODE(node, + "Missing `id` attribute in stream class as there's more than one stream class in the trace."); ret = -EPERM; goto error; } /* Automatic ID: 0 */ - ret = bt_ctf_stream_class_set_id(stream_class, 0); + ret = bt_stream_class_set_id(stream_class, 0); + BT_ASSERT(ret == 0); } - id = bt_ctf_stream_class_get_id(stream_class); + id = bt_stream_class_get_id(stream_class); if (id < 0) { - _PERROR("wrong stream ID: %" PRId64, id); + _BT_LOGE_NODE(node, + "Cannot get stream class's ID."); + ret = -EINVAL; + goto error; + } + + /* + * Make sure that this stream class's ID is currently unique in + * the trace. + */ + existing_stream_class = bt_trace_get_stream_class_by_id(ctx->trace, + id); + if (g_hash_table_lookup(ctx->stream_classes, &id) || + existing_stream_class) { + _BT_LOGE_NODE(node, + "Duplicate stream class (same ID): id=%" PRId64, + id); ret = -EINVAL; goto error; } + new_id = g_new0(int64_t, 1); + if (!new_id) { + BT_LOGE_STR("Failed to allocate a int64_t."); + ret = -ENOMEM; + goto error; + } + *new_id = id; + /* Move reference to visitor's context */ - g_hash_table_insert(ctx->stream_classes, (gpointer) (int64_t) id, + g_hash_table_insert(ctx->stream_classes, new_id, stream_class); stream_class = NULL; - -end: - return 0; + goto end; error: - BT_PUT(stream_class); + bt_put(stream_class); +end: + bt_put(existing_stream_class); return ret; } @@ -3780,15 +4358,15 @@ 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); + _BT_FIELD_TYPE_INIT(packet_header_decl); switch (node->type) { case NODE_TYPEDEF: ret = visit_typedef(ctx, node->u._typedef.type_specifier_list, &node->u._typedef.type_declarators); if (ret) { - _PERROR("%s", - "cannot add typedef in \"trace\" declaration"); + _BT_LOGE_NODE(node, + "Cannot add type definition found in trace (`trace` block)."); goto error; } break; @@ -3796,8 +4374,8 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) ret = visit_typealias(ctx, node->u.typealias.target, node->u.typealias.alias); if (ret) { - _PERROR("%s", - "cannot add typealias in \"trace\" declaration"); + _BT_LOGE_NODE(node, + "Cannot add type alias found in trace (`trace` block)."); goto error; } break; @@ -3805,13 +4383,14 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) { left = concatenate_unary_strings(&node->u.ctf_expression.left); if (!left) { + _BT_LOGE_NODE(node, "Cannot concatenate unary strings."); ret = -EINVAL; goto error; } if (!strcmp(left, "major")) { if (_IS_SET(set, _TRACE_MAJOR_SET)) { - _PERROR_DUP_ATTR("major", "trace declaration"); + _BT_LOGE_DUP_ATTR(node, "major", "trace"); ret = -EPERM; goto error; } @@ -3819,7 +4398,8 @@ 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); if (ret) { - _PERROR("%s", "unexpected unary expression for trace's \"major\" attribute"); + _BT_LOGE_NODE(node, + "Unexpected unary expression for trace's `major` attribute."); ret = -EINVAL; goto error; } @@ -3827,7 +4407,7 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) _SET(set, _TRACE_MAJOR_SET); } else if (!strcmp(left, "minor")) { if (_IS_SET(set, _TRACE_MINOR_SET)) { - _PERROR_DUP_ATTR("minor", "trace declaration"); + _BT_LOGE_DUP_ATTR(node, "minor", "trace"); ret = -EPERM; goto error; } @@ -3835,7 +4415,8 @@ 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); if (ret) { - _PERROR("%s", "unexpected unary expression for trace's \"minor\" attribute"); + _BT_LOGE_NODE(node, + "Unexpected unary expression for trace's `minor` attribute."); ret = -EINVAL; goto error; } @@ -3843,7 +4424,7 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) _SET(set, _TRACE_MINOR_SET); } else if (!strcmp(left, "uuid")) { if (_IS_SET(set, _TRACE_UUID_SET)) { - _PERROR_DUP_ATTR("uuid", "trace declaration"); + _BT_LOGE_DUP_ATTR(node, "uuid", "trace"); ret = -EPERM; goto error; } @@ -3851,8 +4432,14 @@ 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); if (ret) { - _PERROR("%s", - "invalid trace declaration's UUID"); + _BT_LOGE_NODE(node, + "Invalid trace's `uuid` attribute."); + goto error; + } + + ret = bt_trace_set_uuid(ctx->trace, ctx->trace_uuid); + if (ret) { + _BT_LOGE_NODE(node, "Cannot set trace's UUID."); goto error; } @@ -3860,8 +4447,8 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) } else if (!strcmp(left, "byte_order")) { /* Native byte order is already known at this stage */ if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) { - _PERROR_DUP_ATTR("byte_order", - "trace declaration"); + _BT_LOGE_DUP_ATTR(node, "byte_order", + "trace"); ret = -EPERM; goto error; } @@ -3869,7 +4456,8 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) _SET(set, _TRACE_BYTE_ORDER_SET); } else if (!strcmp(left, "packet.header")) { if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) { - _PERROR("%s", "duplicate \"packet.header\" entry in trace declaration"); + _BT_LOGE_NODE(node, + "Duplicate `packet.header` entry in trace."); ret = -EPERM; goto error; } @@ -3880,22 +4468,26 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) struct ctf_node, siblings), &packet_header_decl); if (ret) { - _PERROR("%s", "cannot create packet header declaration"); + _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, + BT_ASSERT(packet_header_decl); + ret = bt_trace_set_packet_header_field_type(ctx->trace, packet_header_decl); BT_PUT(packet_header_decl); if (ret) { - _PERROR("%s", "cannot set trace declaration's packet header declaration"); + _BT_LOGE_NODE(node, + "Cannot set trace's packet header field type."); goto error; } _SET(set, _TRACE_PACKET_HEADER_SET); } else { - _PWARNING("%s", "unknown attribute \"%s\" in trace declaration"); + _BT_LOGW_NODE(node, + "Unknown attribute in stream class: " + "attr-name=\"%s\"", left); } g_free(left); @@ -3903,7 +4495,7 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set) break; } default: - _PERROR("%s", "unknown expression in trace declaration"); + _BT_LOGE_NODE(node, "Unknown expression in trace."); ret = -EINVAL; goto error; } @@ -3932,20 +4524,22 @@ int visit_trace_decl(struct ctx *ctx, struct ctf_node *node) node->visited = TRUE; if (ctx->is_trace_visited) { - _PERROR("%s", "duplicate \"trace\" block"); + _BT_LOGE_NODE(node, "Duplicate trace (`trace` block)."); ret = -EEXIST; goto error; } ret = ctx_push_scope(ctx); if (ret) { - _PERROR("%s", "cannot push scope"); + BT_LOGE_STR("Cannot push scope."); goto error; } bt_list_for_each_entry(iter, decl_list, siblings) { ret = visit_trace_decl_entry(ctx, iter, &set); if (ret) { + _BT_LOGE_NODE(iter, "Cannot visit trace's entry (`trace` block): " + "ret=%d", ret); ctx_pop_scope(ctx); goto error; } @@ -3954,21 +4548,22 @@ int visit_trace_decl(struct ctx *ctx, struct ctf_node *node) ctx_pop_scope(ctx); if (!_IS_SET(&set, _TRACE_MAJOR_SET)) { - _PERROR("%s", - "missing \"major\" attribute in trace declaration"); + _BT_LOGE_NODE(node, + "Missing `major` attribute in trace (`trace` block)."); ret = -EPERM; goto error; } if (!_IS_SET(&set, _TRACE_MINOR_SET)) { - _PERROR("%s", - "missing \"minor\" attribute in trace declaration"); + _BT_LOGE_NODE(node, + "Missing `minor` attribute in trace (`trace` block)."); ret = -EPERM; goto error; } if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { - _PERROR("%s", "missing \"byte_order\" attribute in trace declaration"); + _BT_LOGE_NODE(node, + "Missing `byte_order` attribute in trace (`trace` block)."); ret = -EPERM; goto error; } @@ -4001,7 +4596,9 @@ int visit_env(struct ctx *ctx, struct ctf_node *node) &entry_node->u.ctf_expression.right; if (entry_node->type != NODE_CTF_EXPRESSION) { - _PERROR("%s", "wrong expression in environment entry"); + _BT_LOGE_NODE(entry_node, + "Wrong expression in environment entry: " + "node-type=%d", entry_node->type); ret = -EPERM; goto error; } @@ -4009,7 +4606,8 @@ int visit_env(struct ctx *ctx, struct ctf_node *node) left = concatenate_unary_strings( &entry_node->u.ctf_expression.left); if (!left) { - _PERROR("%s", "cannot get environment entry name"); + _BT_LOGE_NODE(entry_node, + "Cannot get environment entry's name."); ret = -EINVAL; goto error; } @@ -4018,20 +4616,30 @@ int visit_env(struct ctx *ctx, struct ctf_node *node) char *right = concatenate_unary_strings(right_head); if (!right) { - _PERROR("unexpected unary expression for environment entry's value (\"%s\")", - left); + _BT_LOGE_NODE(entry_node, + "Unexpected unary expression for environment entry's value: " + "name=\"%s\"", left); ret = -EINVAL; goto error; } - printf_verbose("env.%s = \"%s\"\n", left, right); - ret = bt_ctf_trace_set_environment_field_string( + 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 = 1; + } + } + + ret = bt_trace_set_environment_field_string( ctx->trace, left, right); g_free(right); if (ret) { - _PERROR("environment: cannot add entry \"%s\" to trace", - left); + _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) || @@ -4045,23 +4653,25 @@ int visit_env(struct ctx *ctx, struct ctf_node *node) ret = get_unary_signed(right_head, &v); } if (ret) { - _PERROR("unexpected unary expression for environment entry's value (\"%s\")", - left); + _BT_LOGE_NODE(entry_node, + "Unexpected unary expression for environment entry's value: " + "name=\"%s\"", left); ret = -EINVAL; goto error; } - printf_verbose("env.%s = %" PRId64 "\n", left, v); - ret = bt_ctf_trace_set_environment_field_integer( + ret = bt_trace_set_environment_field_integer( ctx->trace, left, v); if (ret) { - _PERROR("environment: cannot add entry \"%s\" to trace", - left); + _BT_LOGE_NODE(entry_node, + "Cannot add integer environment entry to trace: " + "name=\"%s\", ret=%d", left, ret); goto error; } } else { - printf_verbose("%s: environment entry \"%s\" has unknown type\n", - __func__, left); + _BT_LOGW_NODE(entry_node, + "Environment entry has unknown type: " + "name=\"%s\"", left); } g_free(left); @@ -4093,16 +4703,18 @@ int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node) left = concatenate_unary_strings( &node->u.ctf_expression.left); if (!left) { + _BT_LOGE_NODE(node, + "Cannot concatenate unary strings."); ret = -EINVAL; goto error; } if (!strcmp(left, "byte_order")) { - enum bt_ctf_byte_order bo; + enum bt_byte_order bo; if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { - _PERROR_DUP_ATTR("byte_order", - "trace declaration"); + _BT_LOGE_DUP_ATTR(node, "byte_order", + "trace"); ret = -EPERM; goto error; } @@ -4111,23 +4723,28 @@ int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node) right_node = _BT_LIST_FIRST_ENTRY( &node->u.ctf_expression.right, struct ctf_node, siblings); - bo = byte_order_from_unary_expr(ctx->efd, - right_node); - if (bo == BT_CTF_BYTE_ORDER_UNKNOWN) { - _PERROR("%s", "unknown \"byte_order\" attribute in trace declaration"); + bo = byte_order_from_unary_expr(right_node); + if (bo == BT_BYTE_ORDER_UNKNOWN) { + _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) { - _PERROR("%s", "\"byte_order\" attribute cannot be set to \"native\" in trace declaration"); + } else if (bo == BT_BYTE_ORDER_NATIVE) { + _BT_LOGE_NODE(node, + "Invalid `byte_order` attribute in trace (`trace` block): " + "cannot be set to `native` here."); ret = -EPERM; goto error; } - ret = bt_ctf_trace_set_byte_order( + ctx->trace_bo = bo; + ret = bt_trace_set_native_byte_order( ctx->trace, bo); if (ret) { - _PERROR("cannot set trace's byte order (%d)", - ret); + _BT_LOGE_NODE(node, + "Cannot set trace's byte order: " + "ret=%d", ret); goto error; } } @@ -4138,7 +4755,8 @@ int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node) } if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) { - _PERROR("%s", "missing \"byte_order\" attribute in trace declaration"); + _BT_LOGE_NODE(trace_node, + "Missing `byte_order` attribute in trace (`trace` block)."); ret = -EINVAL; goto error; } @@ -4153,18 +4771,22 @@ error: 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) { int ret = 0; char *left = NULL; if (entry_node->type != NODE_CTF_EXPRESSION) { + _BT_LOGE_NODE(entry_node, + "Unexpected node type: node-type=%d", + entry_node->type); ret = -EPERM; goto error; } left = concatenate_unary_strings(&entry_node->u.ctf_expression.left); if (!left) { + _BT_LOGE_NODE(entry_node, "Cannot concatenate unary strings."); ret = -EINVAL; goto error; } @@ -4173,7 +4795,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, char *right; if (_IS_SET(set, _CLOCK_NAME_SET)) { - _PERROR_DUP_ATTR("name", "clock declaration"); + _BT_LOGE_DUP_ATTR(entry_node, "name", "clock class"); ret = -EPERM; goto error; } @@ -4181,14 +4803,16 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, right = concatenate_unary_strings( &entry_node->u.ctf_expression.right); if (!right) { - _PERROR("%s", "unexpected unary expression for clock declaration's \"name\" attribute"); + _BT_LOGE_NODE(entry_node, + "Unexpected unary expression for clock class's `name` attribute."); ret = -EINVAL; goto error; } - ret = bt_ctf_clock_class_set_name(clock, right); + ret = bt_clock_class_set_name(clock, right); if (ret) { - _PERROR("%s", "cannot set clock's name"); + _BT_LOGE_NODE(entry_node, + "cannot set clock class's name"); g_free(right); goto error; } @@ -4199,20 +4823,22 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, unsigned char uuid[BABELTRACE_UUID_LEN]; if (_IS_SET(set, _CLOCK_UUID_SET)) { - _PERROR_DUP_ATTR("uuid", "clock declaration"); + _BT_LOGE_DUP_ATTR(entry_node, "uuid", "clock class"); ret = -EPERM; goto error; } ret = get_unary_uuid(&entry_node->u.ctf_expression.right, uuid); if (ret) { - _PERROR("%s", "invalid clock UUID"); + _BT_LOGE_NODE(entry_node, + "Invalid clock class's `uuid` attribute."); goto error; } - ret = bt_ctf_clock_class_set_uuid(clock, uuid); + ret = bt_clock_class_set_uuid(clock, uuid); if (ret) { - _PERROR("%s", "cannot set clock's UUID"); + _BT_LOGE_NODE(entry_node, + "Cannot set clock class's UUID."); goto error; } @@ -4221,7 +4847,8 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, char *right; if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) { - _PERROR_DUP_ATTR("description", "clock declaration"); + _BT_LOGE_DUP_ATTR(entry_node, "description", + "clock class"); ret = -EPERM; goto error; } @@ -4229,14 +4856,16 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, right = concatenate_unary_strings( &entry_node->u.ctf_expression.right); if (!right) { - _PERROR("%s", "unexpected unary expression for clock's \"description\" attribute"); + _BT_LOGE_NODE(entry_node, + "Unexpected unary expression for clock class's `description` attribute."); ret = -EINVAL; goto error; } - ret = bt_ctf_clock_class_set_description(clock, right); + ret = bt_clock_class_set_description(clock, right); if (ret) { - _PERROR("%s", "cannot set clock's description"); + _BT_LOGE_NODE(entry_node, + "Cannot set clock class's description."); g_free(right); goto error; } @@ -4244,10 +4873,10 @@ 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 = -1ULL; if (_IS_SET(set, _CLOCK_FREQ_SET)) { - _PERROR_DUP_ATTR("freq", "clock declaration"); + _BT_LOGE_DUP_ATTR(entry_node, "freq", "clock class"); ret = -EPERM; goto error; } @@ -4255,14 +4884,24 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, ret = get_unary_unsigned( &entry_node->u.ctf_expression.right, &freq); if (ret) { - _PERROR("%s", "unexpected unary expression for clock declaration's \"freq\" attribute"); + _BT_LOGE_NODE(entry_node, + "Unexpected unary expression for clock class's `freq` attribute."); ret = -EINVAL; goto error; } - ret = bt_ctf_clock_class_set_frequency(clock, freq); + if (freq == -1ULL || freq == 0) { + _BT_LOGE_NODE(entry_node, + "Invalid clock class frequency: freq=%" PRIu64, + freq); + ret = -EINVAL; + goto error; + } + + ret = bt_clock_class_set_frequency(clock, freq); if (ret) { - _PERROR("%s", "cannot set clock's frequency"); + _BT_LOGE_NODE(entry_node, + "Cannot set clock class's frequency."); goto error; } @@ -4271,7 +4910,8 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, uint64_t precision; if (_IS_SET(set, _CLOCK_PRECISION_SET)) { - _PERROR_DUP_ATTR("precision", "clock declaration"); + _BT_LOGE_DUP_ATTR(entry_node, "precision", + "clock class"); ret = -EPERM; goto error; } @@ -4279,62 +4919,69 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, ret = get_unary_unsigned( &entry_node->u.ctf_expression.right, &precision); if (ret) { - _PERROR("%s", "unexpected unary expression for clock declaration's \"precision\" attribute"); + _BT_LOGE_NODE(entry_node, + "Unexpected unary expression for clock class's `precision` attribute."); ret = -EINVAL; goto error; } - ret = bt_ctf_clock_class_set_precision(clock, precision); + ret = bt_clock_class_set_precision(clock, precision); if (ret) { - _PERROR("%s", "cannot set clock's precision"); + _BT_LOGE_NODE(entry_node, + "Cannot set clock class's precision."); goto error; } _SET(set, _CLOCK_PRECISION_SET); } else if (!strcmp(left, "offset_s")) { - uint64_t offset_s; + int64_t offset_s; if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) { - _PERROR_DUP_ATTR("offset_s", "clock declaration"); + _BT_LOGE_DUP_ATTR(entry_node, "offset_s", + "clock class"); ret = -EPERM; goto error; } - ret = get_unary_unsigned( + ret = get_unary_signed( &entry_node->u.ctf_expression.right, &offset_s); if (ret) { - _PERROR("%s", "unexpected unary expression for clock declaration's \"offset_s\" attribute"); + _BT_LOGE_NODE(entry_node, + "Unexpected unary expression for clock class's `offset_s` attribute."); ret = -EINVAL; goto error; } - ret = bt_ctf_clock_class_set_offset_s(clock, offset_s); + ret = bt_clock_class_set_offset_s(clock, offset_s); if (ret) { - _PERROR("%s", "cannot set clock's offset in seconds"); + _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; + int64_t offset; if (_IS_SET(set, _CLOCK_OFFSET_SET)) { - _PERROR_DUP_ATTR("offset", "clock declaration"); + _BT_LOGE_DUP_ATTR(entry_node, "offset", "clock class"); ret = -EPERM; goto error; } - ret = get_unary_unsigned( + ret = get_unary_signed( &entry_node->u.ctf_expression.right, &offset); if (ret) { - _PERROR("%s", "unexpected unary expression for clock declaration's \"offset\" attribute"); + _BT_LOGE_NODE(entry_node, + "Unexpected unary expression for clock class's `offset` attribute."); ret = -EINVAL; goto error; } - ret = bt_ctf_clock_class_set_offset_cycles(clock, offset); + ret = bt_clock_class_set_offset_cycles(clock, offset); if (ret) { - _PERROR("%s", "cannot set clock's offset in cycles"); + _BT_LOGE_NODE(entry_node, + "Cannot set clock class's offset in cycles."); goto error; } @@ -4343,7 +4990,8 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, struct ctf_node *right; if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) { - _PERROR_DUP_ATTR("absolute", "clock declaration"); + _BT_LOGE_DUP_ATTR(entry_node, "absolute", + "clock class"); ret = -EPERM; goto error; } @@ -4351,22 +4999,25 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node, right = _BT_LIST_FIRST_ENTRY( &entry_node->u.ctf_expression.right, struct ctf_node, siblings); - ret = get_boolean(ctx->efd, right); + ret = get_boolean(right); if (ret < 0) { - _PERROR("%s", "unexpected unary expression for clock declaration's \"absolute\" attribute"); + _BT_LOGE_NODE(entry_node, + "Unexpected unary expression for clock class's `absolute` attribute."); ret = -EINVAL; goto error; } - ret = bt_ctf_clock_class_set_is_absolute(clock, ret); + ret = bt_clock_class_set_is_absolute(clock, ret); if (ret) { - _PERROR("%s", "cannot set clock's absolute option"); + _BT_LOGE_NODE(entry_node, + "Cannot set clock class's absolute flag."); goto error; } _SET(set, _CLOCK_ABSOLUTE_SET); } else { - _PWARNING("unknown attribute \"%s\" in clock declaration", + _BT_LOGW_NODE(entry_node, + "Unknown attribute in clock class: attr-name=\"%s\"", left); } @@ -4382,9 +5033,9 @@ error: } static -uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns) +int64_t cycles_from_ns(uint64_t frequency, int64_t ns) { - uint64_t cycles; + int64_t cycles; /* 1GHz */ if (frequency == 1000000000ULL) { @@ -4397,53 +5048,58 @@ uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns) } static -int apply_clock_offset(struct ctx *ctx, struct bt_ctf_clock_class *clock, - uint64_t clock_offset_ns) +int 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; - freq = bt_ctf_clock_class_get_frequency(clock); + freq = bt_clock_class_get_frequency(clock); if (freq == -1ULL) { - _PERROR("%s", "No clock frequency"); + BT_LOGE_STR("Cannot get clock class's frequency."); ret = -1; goto end; } - ret = bt_ctf_clock_class_get_offset_cycles(clock, &offset_cycles); + ret = bt_clock_class_get_offset_cycles(clock, &offset_cycles); if (ret) { - _PERROR("%s", "Getting offset cycles"); + BT_LOGE_STR("Cannot get clock class's offset in cycles."); ret = -1; goto end; } - offset_cycles += cycles_from_ns(freq, clock_offset_ns); - - ret = bt_ctf_clock_class_set_offset_cycles(clock, offset_cycles); + 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_clock_class_set_offset_cycles(clock, offset_cycles); end: return ret; } static -int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node, - uint64_t clock_offset_ns) +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; 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(NULL, 1000000000); if (!clock) { - _PERROR("%s", "cannot create clock"); + _BT_LOGE_NODE(clock_node, + "Cannot create default clock class."); ret = -ENOMEM; goto error; } @@ -4451,32 +5107,48 @@ int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node, bt_list_for_each_entry(entry_node, decl_list, siblings) { ret = visit_clock_decl_entry(ctx, entry_node, clock, &set); if (ret) { + _BT_LOGE_NODE(entry_node, + "Cannot visit clock class's entry: ret=%d", + ret); goto error; } } if (!_IS_SET(&set, _CLOCK_NAME_SET)) { - _PERROR("%s", - "missing \"name\" attribute in clock declaration"); + _BT_LOGE_NODE(clock_node, + "Missing `name` attribute in clock class."); ret = -EPERM; goto error; } - if (bt_ctf_trace_get_clock_class_count(ctx->trace) != 0) { - _PERROR("%s", "only CTF traces with a single clock declaration are supported as of this version"); - ret = -EINVAL; - goto error; + 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 + * as absolute, even if it is. This is important because + * it's a condition to be able to sort notifications + * from different sources. + */ + ret = bt_clock_class_set_is_absolute(clock, 1); + if (ret) { + _BT_LOGE_NODE(clock_node, + "Cannot set clock class's absolute flag."); + goto error; + } } - ret = apply_clock_offset(ctx, clock, clock_offset_ns); + ret = apply_clock_class_offset(ctx, clock); if (ret) { - _PERROR("%s", "cannot apply clock offset "); + _BT_LOGE_NODE(clock_node, + "Cannot apply clock class's custom offset."); goto error; } - ret = bt_ctf_trace_add_clock_class(ctx->trace, clock); + ret = bt_trace_add_clock_class(ctx->trace, clock); if (ret) { - _PERROR("%s", "cannot add clock to trace"); + _BT_LOGE_NODE(clock_node, + "Cannot add clock class to trace."); goto error; } @@ -4503,7 +5175,8 @@ int visit_root_decl(struct ctx *ctx, struct ctf_node *root_decl_node) root_decl_node->u._typedef.type_specifier_list, &root_decl_node->u._typedef.type_declarators); if (ret) { - _PERROR("%s", "cannot add typedef in root scope"); + _BT_LOGE_NODE(root_decl_node, + "Cannot add type definition found in root scope."); goto end; } break; @@ -4511,13 +5184,14 @@ int visit_root_decl(struct ctx *ctx, struct ctf_node *root_decl_node) ret = visit_typealias(ctx, root_decl_node->u.typealias.target, root_decl_node->u.typealias.alias); if (ret) { - _PERROR("%s", "cannot add typealias in root scope"); + _BT_LOGE_NODE(root_decl_node, + "Cannot add type alias found in root scope."); goto end; } break; case NODE_TYPE_SPECIFIER_LIST: { - _BT_CTF_FIELD_TYPE_INIT(decl); + _BT_FIELD_TYPE_INIT(decl); /* * Just add the type specifier to the root @@ -4525,7 +5199,10 @@ int visit_root_decl(struct ctx *ctx, struct ctf_node *root_decl_node) */ ret = visit_type_specifier_list(ctx, root_decl_node, &decl); if (ret) { - assert(!decl); + _BT_LOGE_NODE(root_decl_node, + "Cannot visit root scope's field type: " + "ret=%d", ret); + BT_ASSERT(!decl); goto end; } @@ -4533,6 +5210,9 @@ int visit_root_decl(struct ctx *ctx, struct ctf_node *root_decl_node) break; } default: + _BT_LOGE_NODE(root_decl_node, + "Unexpected node type: node-type=%d", + root_decl_node->type); ret = -EPERM; goto end; } @@ -4542,106 +5222,246 @@ end: } static -int add_stream_classes_to_trace(struct ctx *ctx) +int set_trace_name(struct ctx *ctx) { - int ret; + GString *name; + int ret = 0; + struct bt_value *value = NULL; + + BT_ASSERT(bt_trace_get_stream_class_count(ctx->trace) == 0); + name = g_string_new(NULL); + if (!name) { + BT_LOGE_STR("Failed to allocate a GString."); + ret = -1; + goto end; + } + + /* + * Check if we have a trace environment string value named `hostname`. + * If so, use it as the trace name's prefix. + */ + value = bt_trace_get_environment_field_value_by_name(ctx->trace, + "hostname"); + if (value && bt_value_is_string(value)) { + const char *hostname; + + ret = bt_value_string_get(value, &hostname); + BT_ASSERT(ret == 0); + g_string_append(name, hostname); + + if (ctx->trace_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_trace_set_name(ctx->trace, name->str); + if (ret) { + BT_LOGE("Cannot set trace's name: name=\"%s\"", name->str); + goto error; + } + + goto end; + +error: + ret = -1; + +end: + bt_put(value); + + if (name) { + g_string_free(name, TRUE); + } + + 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_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, + ret = bt_trace_add_stream_class(ctx->trace, stream_class); if (ret) { - int64_t id = bt_ctf_stream_class_get_id(stream_class); - _PERROR("cannot add stream class %" PRId64 " to trace", + int64_t id = bt_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; } -int ctf_visitor_generate_ir(FILE *efd, struct ctf_node *node, - struct bt_ctf_trace **trace, uint64_t clock_offset_ns) +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 = 0; + int ret; struct ctx *ctx = NULL; + struct bt_trace *trace; - printf_verbose("CTF visitor: AST -> CTF IR...\n"); - - *trace = bt_ctf_trace_create(); - if (!*trace) { - _FPERROR(efd, "%s", "cannot create trace"); - ret = -ENOMEM; + trace = bt_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); + ret = bt_trace_set_packet_header_field_type(trace, NULL); if (ret) { - _FPERROR(efd, - "%s", - "cannot set initial, empty packet header structure"); + BT_LOGE_STR("Cannot reset initial trace's packet header field type."); goto error; } - ctx = ctx_create(*trace, efd); + /* Create visitor's context */ + ctx = ctx_create(trace, decoder_config, name); if (!ctx) { - _FPERROR(efd, "%s", "cannot create visitor context"); - ret = -ENOMEM; + BT_LOGE_STR("Cannot create visitor's context."); goto error; } + trace = NULL; + goto end; + +error: + ctx_destroy(ctx); + ctx = NULL; + +end: + bt_put(trace); + return (void *) ctx; +} + +BT_HIDDEN +void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor) +{ + ctx_destroy((void *) visitor); +} + +BT_HIDDEN +struct bt_trace *ctf_visitor_generate_ir_get_trace( + struct ctf_visitor_generate_ir *visitor) +{ + struct ctx *ctx = (void *) visitor; + + BT_ASSERT(ctx); + BT_ASSERT(ctx->trace); + return bt_get(ctx->trace); +} + +BT_HIDDEN +int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor, + struct ctf_node *node) +{ + int ret = 0; + struct ctx *ctx = (void *) visitor; + + BT_LOGI_STR("Visiting metadata's AST to generate CTF IR objects."); + switch (node->type) { case NODE_ROOT: { struct ctf_node *iter; int got_trace_decl = FALSE; - int found_callsite = FALSE; /* - * Find trace declaration's byte order first (for early - * type aliases). + * The first thing we need is the native byte order of + * the trace block, because early type 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. */ - bt_list_for_each_entry(iter, &node->u.root.trace, siblings) { - if (got_trace_decl) { - _PERROR("%s", "duplicate trace declaration"); - goto error; - } + if (ctx->trace_bo == BT_BYTE_ORDER_NATIVE) { + bt_list_for_each_entry(iter, &node->u.root.trace, siblings) { + if (got_trace_decl) { + _BT_LOGE_NODE(node, + "Duplicate trace (`trace` block)."); + ret = -1; + goto end; + } - ret = set_trace_byte_order(ctx, iter); - if (ret) { - _PERROR("cannot set trace's byte order (%d)", - ret); - goto error; + ret = set_trace_byte_order(ctx, iter); + if (ret) { + _BT_LOGE_NODE(node, + "Cannot set trace's native byte order: " + "ret=%d", ret); + goto end; + } + + got_trace_decl = TRUE; } - got_trace_decl = TRUE; + if (!got_trace_decl) { + BT_LOGD_STR("Incomplete AST: need trace (`trace` block)."); + ret = -EINCOMPLETE; + goto end; + } } - if (!got_trace_decl) { - _PERROR("no trace declaration found (%d)", ret); - ret = -EPERM; - goto error; + BT_ASSERT(ctx->trace_bo == BT_BYTE_ORDER_LITTLE_ENDIAN || + ctx->trace_bo == BT_BYTE_ORDER_BIG_ENDIAN); + BT_ASSERT(ctx->current_scope && + ctx->current_scope->parent_scope == NULL); + + /* Environment */ + bt_list_for_each_entry(iter, &node->u.root.env, siblings) { + ret = visit_env(ctx, iter); + if (ret) { + _BT_LOGE_NODE(iter, + "Cannot visit trace's environment (`env` block) entry: " + "ret=%d", ret); + goto end; + } } + BT_ASSERT(ctx->current_scope && + ctx->current_scope->parent_scope == NULL); + /* - * Visit clocks first since any early integer can be mapped - * to one. + * Visit clock blocks. */ bt_list_for_each_entry(iter, &node->u.root.clock, siblings) { - ret = visit_clock_decl(ctx, iter, clock_offset_ns); + ret = visit_clock_decl(ctx, iter); if (ret) { - _PERROR("error while visiting clock declaration (%d)", + _BT_LOGE_NODE(iter, + "Cannot visit clock class: ret=%d", ret); - goto error; + goto end; } } + BT_ASSERT(ctx->current_scope && + ctx->current_scope->parent_scope == NULL); + /* * Visit root declarations next, as they can be used by any * following entity. @@ -4650,81 +5470,82 @@ int ctf_visitor_generate_ir(FILE *efd, struct ctf_node *node, siblings) { ret = visit_root_decl(ctx, iter); if (ret) { - _PERROR("error while visiting root declaration (%d)", + _BT_LOGE_NODE(iter, + "Cannot visit root entry: ret=%d", ret); - goto error; + goto end; } } - /* Callsite are not supported */ - bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) { - found_callsite = TRUE; - break; - } + BT_ASSERT(ctx->current_scope && + ctx->current_scope->parent_scope == NULL); - if (found_callsite) { - _PWARNING("%s", "\"callsite\" blocks are not supported as of this version"); + /* Callsite blocks are not supported */ + bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) { + _BT_LOGW_NODE(iter, + "\"callsite\" blocks are not supported as of this version."); } - /* Environment */ - bt_list_for_each_entry(iter, &node->u.root.env, siblings) { - ret = visit_env(ctx, iter); - if (ret) { - _PERROR("error while visiting environment block (%d)", - ret); - goto error; - } - } + BT_ASSERT(ctx->current_scope && + ctx->current_scope->parent_scope == NULL); /* Trace */ bt_list_for_each_entry(iter, &node->u.root.trace, siblings) { ret = visit_trace_decl(ctx, iter); if (ret) { - _PERROR("%s", "error while visiting trace declaration"); - goto error; + _BT_LOGE_NODE(iter, + "Cannot visit trace (`trace` block): " + "ret=%d", ret); + goto end; } } + BT_ASSERT(ctx->current_scope && + ctx->current_scope->parent_scope == NULL); + /* Streams */ bt_list_for_each_entry(iter, &node->u.root.stream, siblings) { ret = visit_stream_decl(ctx, iter); if (ret) { - _PERROR("%s", "error while visiting stream declaration"); - goto error; + _BT_LOGE_NODE(iter, + "Cannot visit stream class: ret=%d", + ret); + goto end; } } + BT_ASSERT(ctx->current_scope && + ctx->current_scope->parent_scope == NULL); + /* Events */ bt_list_for_each_entry(iter, &node->u.root.event, siblings) { ret = visit_event_decl(ctx, iter); if (ret) { - _PERROR("%s", "error while visiting event declaration"); - goto error; + _BT_LOGE_NODE(iter, + "Cannot visit event class: ret=%d", + ret); + goto end; } } + + BT_ASSERT(ctx->current_scope && + ctx->current_scope->parent_scope == NULL); break; } - case NODE_UNKNOWN: default: - _PERROR("unknown node type: %d", (int) node->type); + _BT_LOGE_NODE(node, + "Unexpected node type: node-type=%d", + node->type); ret = -EINVAL; - goto error; + goto end; } - /* Add stream classes to trace now */ - ret = add_stream_classes_to_trace(ctx); + /* Move decoded stream classes to trace, if any */ + ret = move_ctx_stream_classes_to_trace(ctx); if (ret) { - _PERROR("%s", "cannot add stream classes to trace"); + BT_LOGE("Cannot move stream classes to trace: ret=%d", ret); } - ctx_destroy(ctx); - printf_verbose("done!\n"); - - return ret; - -error: - ctx_destroy(ctx); - BT_PUT(*trace); - +end: return ret; }