Fix: remove underscores from CTF IR field names at the source
[babeltrace.git] / plugins / ctf / common / metadata / visitor-generate-ir.c
index 4188d45bdc6fcedc85acac5b6db4030287ecffad..34c3716ad3809c0fea89937d8789a15b70276e6b 100644 (file)
 #include <errno.h>
 #include <babeltrace/compat/uuid-internal.h>
 #include <babeltrace/endian-internal.h>
-#include <babeltrace/ref.h>
-#include <babeltrace/ctf-ir/trace.h>
-#include <babeltrace/ctf-ir/stream-class.h>
-#include <babeltrace/ctf-ir/event.h>
-#include <babeltrace/ctf-ir/event-class.h>
-#include <babeltrace/ctf-ir/field-types.h>
+#include <babeltrace/babeltrace.h>
 #include <babeltrace/ctf-ir/field-types-internal.h>
-#include <babeltrace/ctf-ir/clock-class.h>
 
 #include "scanner.h"
 #include "parser.h"
@@ -226,37 +220,6 @@ struct ctx {
  */
 struct ctf_visitor_generate_ir { };
 
-static
-const char *loglevel_str [] = {
-       [ LOGLEVEL_EMERG ] = "TRACE_EMERG",
-       [ LOGLEVEL_ALERT ] = "TRACE_ALERT",
-       [ LOGLEVEL_CRIT ] = "TRACE_CRIT",
-       [ LOGLEVEL_ERR ] = "TRACE_ERR",
-       [ LOGLEVEL_WARNING ] = "TRACE_WARNING",
-       [ LOGLEVEL_NOTICE ] = "TRACE_NOTICE",
-       [ LOGLEVEL_INFO ] = "TRACE_INFO",
-       [ LOGLEVEL_DEBUG_SYSTEM ] = "TRACE_DEBUG_SYSTEM",
-       [ LOGLEVEL_DEBUG_PROGRAM ] = "TRACE_DEBUG_PROGRAM",
-       [ LOGLEVEL_DEBUG_PROCESS ] = "TRACE_DEBUG_PROCESS",
-       [ LOGLEVEL_DEBUG_MODULE ] = "TRACE_DEBUG_MODULE",
-       [ LOGLEVEL_DEBUG_UNIT ] = "TRACE_DEBUG_UNIT",
-       [ LOGLEVEL_DEBUG_FUNCTION ] = "TRACE_DEBUG_FUNCTION",
-       [ LOGLEVEL_DEBUG_LINE ] = "TRACE_DEBUG_LINE",
-       [ LOGLEVEL_DEBUG ] = "TRACE_DEBUG",
-};
-
-static
-const char *print_loglevel(int64_t value)
-{
-       if (value < 0) {
-               return NULL;
-       }
-       if (value >= _NR_LOGLEVELS) {
-               return "<<UNKNOWN>>";
-       }
-       return loglevel_str[value];
-}
-
 /**
  * Creates a new declaration scope.
  *
@@ -623,8 +586,8 @@ struct ctx *ctx_create(struct bt_ctf_trace *trace,
                goto error;
        }
 
-       ctx->stream_classes = g_hash_table_new_full(g_direct_hash,
-               g_direct_equal, NULL, (GDestroyNotify) bt_put);
+       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;
@@ -701,6 +664,61 @@ static
 int visit_type_specifier_list(struct ctx *ctx, struct ctf_node *ts_list,
        struct bt_ctf_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;
+
+       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)
 {
@@ -913,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;
@@ -922,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;
@@ -1071,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
@@ -1357,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;
@@ -1414,6 +1435,7 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list,
                        /* Lookup unsigned integer definition, create seq. */
                        _BT_CTF_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,
@@ -1422,8 +1444,16 @@ int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list,
                                goto error;
                        }
 
+                       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_ctf_field_type_sequence_create(
-                               nested_decl, length_name);
+                               nested_decl, length_name_no_underscore);
+                       free(length_name_no_underscore);
                        g_free(length_name);
                        BT_PUT(nested_decl);
                        if (!seq_decl) {
@@ -1682,7 +1712,7 @@ int visit_typealias(struct ctx *ctx, struct ctf_node *target,
        /* Do not allow typedef and typealias of untagged variants */
        if (bt_ctf_field_type_is_variant(type_decl)) {
                if (bt_ctf_field_type_variant_get_tag_name(type_decl)) {
-                       _BT_LOGE_NODE(node,
+                       _BT_LOGE_NODE(target,
                                "Type definition of untagged variant field type is not allowed.");
                        ret = -EPERM;
                        goto end;
@@ -1694,7 +1724,7 @@ int visit_typealias(struct ctx *ctx, struct ctf_node *target,
         * abstract or not (if it has an identifier). Check it here.
         */
        if (qdummy_field_name != 0) {
-               _BT_LOGE_NODE(node,
+               _BT_LOGE_NODE(target,
                        "Expecting empty identifier: id=\"%s\"",
                        g_quark_to_string(qdummy_field_name));
                ret = -EINVAL;
@@ -2051,8 +2081,17 @@ 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.
                 */
+               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_ctf_field_type_variant_set_tag_name(
-                       untagged_variant_decl, tag);
+                       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);
@@ -3318,8 +3357,8 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
                        _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_ctf_event_class_log_level log_level =
+                               BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED;
 
                        if (_IS_SET(set, _EVENT_LOGLEVEL_SET)) {
                                _BT_LOGE_DUP_ATTR(node, "loglevel",
@@ -3336,39 +3375,71 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                ret = -EINVAL;
                                goto error;
                        }
-                       value_obj = bt_value_integer_create_init(loglevel_value);
-                       if (!value_obj) {
-                               _BT_LOGE_NODE(node,
-                                       "Cannot create integer value object.");
-                               ret = -ENOMEM;
-                               goto error;
-                       }
-                       if (bt_ctf_event_class_set_attribute(event_class,
-                                       "loglevel", value_obj) != BT_VALUE_STATUS_OK) {
-                               _BT_LOGE_NODE(node,
-                                       "Cannot set event class's `loglevel` attribute.");
-                               ret = -EINVAL;
-                               bt_put(value_obj);
-                               goto error;
+
+                       switch (loglevel_value) {
+                       case 0:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_EMERGENCY;
+                               break;
+                       case 1:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_ALERT;
+                               break;
+                       case 2:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_CRITICAL;
+                               break;
+                       case 3:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_ERROR;
+                               break;
+                       case 4:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_WARNING;
+                               break;
+                       case 5:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_NOTICE;
+                               break;
+                       case 6:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO;
+                               break;
+                       case 7:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM;
+                               break;
+                       case 8:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM;
+                               break;
+                       case 9:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS;
+                               break;
+                       case 10:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE;
+                               break;
+                       case 11:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT;
+                               break;
+                       case 12:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION;
+                               break;
+                       case 13:
+                               log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE;
+                               break;
+                       case 14:
+                               log_level = BT_CTF_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) {
+
+                       if (log_level != BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
+                               ret = bt_ctf_event_class_set_log_level(
+                                       event_class, log_level);
+                               if (ret) {
                                        _BT_LOGE_NODE(node,
-                                               "Cannot set event class's `loglevel_string` attribute.");
-                                       ret = -EINVAL;
-                                       bt_put(str_obj);
+                                               "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;
-                       struct bt_value *str_obj;
 
                        if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) {
                                _BT_LOGE_DUP_ATTR(node, "model.emf.uri",
@@ -3386,16 +3457,19 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                goto error;
                        }
 
-                       str_obj = bt_value_string_create_init(right);
-                       if (bt_ctf_event_class_set_attribute(event_class,
-                                       "model.emf.uri", str_obj) != BT_VALUE_STATUS_OK) {
-                               _BT_LOGE_NODE(node,
-                                       "Cannot set event class's `model.emf.uri` attribute.");
-                               ret = -EINVAL;
-                               bt_put(str_obj);
-                               goto error;
+                       if (strlen(right) == 0) {
+                               _BT_LOGW_NODE(node,
+                                       "Not setting event class's EMF URI because it's empty.");
+                       } else {
+                               ret = bt_ctf_event_class_set_emf_uri(
+                                       event_class, right);
+                               if (ret) {
+                                       _BT_LOGE_NODE(node,
+                                               "Cannot set event class's EMF URI.");
+                                       goto error;
+                               }
                        }
-                       bt_put(str_obj);
+
                        g_free(right);
                        _SET(set, _EVENT_MODEL_EMF_URI_SET);
                } else {
@@ -3618,6 +3692,7 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
 
        if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
                GList *keys = NULL;
+               int64_t *new_stream_id;
                struct bt_ctf_stream_class *new_stream_class;
                size_t stream_class_count =
                        g_hash_table_size(ctx->stream_classes) +
@@ -3630,6 +3705,7 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
                switch (stream_class_count) {
                case 0:
                        /* 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,
@@ -3638,7 +3714,8 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
                                goto error;
                        }
 
-                       ret = bt_ctf_stream_class_set_id(new_stream_class, 0);
+                       ret = bt_ctf_stream_class_set_id(new_stream_class,
+                               stream_id);
                        if (ret) {
                                _BT_LOGE_NODE(node,
                                        "Cannot set stream class's ID: "
@@ -3647,18 +3724,26 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
                                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 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;
+                               stream_id = *((int64_t *) keys->data);
                                g_list_free(keys);
                        } else {
                                assert(bt_ctf_trace_get_stream_class_count(
@@ -3683,8 +3768,7 @@ int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
        assert(stream_id >= 0);
 
        /* We have the stream ID now; get the stream class if found */
-       stream_class = g_hash_table_lookup(ctx->stream_classes,
-               (gpointer) stream_id);
+       stream_class = g_hash_table_lookup(ctx->stream_classes, &stream_id);
        bt_get(stream_class);
        if (!stream_class) {
                stream_class = bt_ctf_trace_get_stream_class_by_id(ctx->trace,
@@ -3762,63 +3846,146 @@ end:
 }
 
 static
-int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
-               struct bt_ctf_field_type *packet_context_field_type,
-               const char **field_names)
+int auto_map_field_to_trace_clock_class(struct ctx *ctx,
+               struct bt_ctf_field_type *ft)
 {
-       _BT_CTF_FIELD_TYPE_INIT(ft);
-       struct bt_ctf_clock_class *clock_class = NULL;
+       struct bt_ctf_clock_class *clock_class_to_map_to = NULL;
        struct bt_ctf_clock_class *mapped_clock_class = NULL;
        int ret = 0;
-       const char **field_name;
+       int64_t clock_class_count;
 
-       if (ctx->decoder_config.strict) {
+       if (!ft || !bt_ctf_field_type_is_integer(ft)) {
                goto end;
        }
 
-       if (!packet_context_field_type) {
+       mapped_clock_class =
+               bt_ctf_field_type_integer_get_mapped_clock_class(ft);
+       if (mapped_clock_class) {
                goto end;
        }
 
-       if (!bt_ctf_field_type_is_structure(packet_context_field_type)) {
+       clock_class_count = bt_ctf_trace_get_clock_class_count(ctx->trace);
+       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_ctf_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_ctf_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_ctf_trace_get_clock_class_by_index(ctx->trace, 0);
+               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;
        }
 
-       if (bt_ctf_trace_get_clock_class_count(ctx->trace) != 1) {
+       assert(clock_class_to_map_to);
+       ret = bt_ctf_field_type_integer_set_mapped_clock_class(ft,
+               clock_class_to_map_to);
+       if (ret) {
+               BT_LOGE("Cannot map field type's field to trace's clock class: "
+                       "clock-class-name=\"%s\", ret=%d",
+                       bt_ctf_clock_class_get_name(clock_class_to_map_to),
+                       ret);
                goto end;
        }
 
-       clock_class = bt_ctf_trace_get_clock_class_by_index(ctx->trace, 0);
-       assert(clock_class);
+end:
+       bt_put(clock_class_to_map_to);
+       bt_put(mapped_clock_class);
+       return ret;
+}
 
-       for (field_name = field_names; *field_name; field_name++) {
-               ft = bt_ctf_field_type_structure_get_field_type_by_name(
-                       packet_context_field_type, *field_name);
+static
+int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
+               struct bt_ctf_field_type *root_ft, const char *field_name)
+{
+       int ret = 0;
+       int64_t i, count;
 
-               if (ft && bt_ctf_field_type_is_integer(ft)) {
-                       mapped_clock_class =
-                               bt_ctf_field_type_integer_get_mapped_clock_class(ft);
+       if (!root_ft) {
+               goto end;
+       }
 
-                       if (!mapped_clock_class) {
-                               ret = bt_ctf_field_type_integer_set_mapped_clock_class(
-                                       ft, clock_class);
-                               if (ret) {
-                                       BT_LOGE("Cannot map field type's field to trace's clock class: "
-                                               "field-name=\"%s\", ret=%d",
-                                               *field_name, ret);
-                                       goto end;
-                               }
+       if (!bt_ctf_field_type_is_structure(root_ft) &&
+                       !bt_ctf_field_type_is_variant(root_ft)) {
+               goto end;
+       }
+
+       if (bt_ctf_field_type_is_structure(root_ft)) {
+               count = bt_ctf_field_type_structure_get_field_count(root_ft);
+       } else {
+               count = bt_ctf_field_type_variant_get_field_count(root_ft);
+       }
+
+       assert(count >= 0);
+
+       for (i = 0; i < count; i++) {
+               _BT_CTF_FIELD_TYPE_INIT(ft);
+               const char *name;
+
+               if (bt_ctf_field_type_is_structure(root_ft)) {
+                       ret = bt_ctf_field_type_structure_get_field_by_index(
+                               root_ft, &name, &ft, i);
+               } else if (bt_ctf_field_type_is_variant(root_ft)) {
+                       ret = bt_ctf_field_type_variant_get_field_by_index(
+                               root_ft, &name, &ft, i);
+               }
+
+               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;
                        }
                }
 
-               BT_PUT(mapped_clock_class);
-               BT_PUT(ft);
+               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:
-       bt_put(mapped_clock_class);
-       bt_put(clock_class);
-       bt_put(ft);
        return ret;
 }
 
@@ -3879,8 +4046,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                goto error;
                        }
 
-                       ptr = g_hash_table_lookup(ctx->stream_classes,
-                               (gpointer) id);
+                       ptr = g_hash_table_lookup(ctx->stream_classes, &id);
                        if (ptr) {
                                _BT_LOGE_NODE(node,
                                        "Duplicate stream class (same ID): id=%" PRId64,
@@ -3899,12 +4065,6 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
 
                        _SET(set, _STREAM_ID_SET);
                } else if (!strcmp(left, "event.header")) {
-                       const char *field_names[] = {
-                               "timestamp",
-                               "ts",
-                               NULL,
-                       };
-
                        if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
                                _BT_LOGE_NODE(node,
                                        "Duplicate `event.header` entry in stream class.");
@@ -3925,10 +4085,10 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
 
                        assert(decl);
                        ret = auto_map_fields_to_trace_clock_class(ctx,
-                               decl, field_names);
+                               decl, "timestamp");
                        if (ret) {
                                _BT_LOGE_NODE(node,
-                                       "Cannot automatically map specific event header field type fields to trace's clock class.");
+                                       "Cannot automatically map specific event header field type fields named `timestamp` to trace's clock class.");
                                goto error;
                        }
 
@@ -3974,12 +4134,6 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
 
                        _SET(set, _STREAM_EVENT_CONTEXT_SET);
                } else if (!strcmp(left, "packet.context")) {
-                       const char *field_names[] = {
-                               "timestamp_begin",
-                               "timestamp_end",
-                               NULL,
-                       };
-
                        if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
                                _BT_LOGE_NODE(node,
                                        "Duplicate `packet.context` entry in stream class.");
@@ -4000,10 +4154,18 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
 
                        assert(decl);
                        ret = auto_map_fields_to_trace_clock_class(ctx,
-                               decl, field_names);
+                               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;
+                       }
+
+                       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 to trace's clock class.");
+                                       "Cannot automatically map specific packet context field type fields named `timestamp_end` to trace's clock class.");
                                goto error;
                        }
 
@@ -4046,6 +4208,7 @@ 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;
@@ -4146,7 +4309,7 @@ int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
         */
        existing_stream_class = bt_ctf_trace_get_stream_class_by_id(ctx->trace,
                id);
-       if (g_hash_table_lookup(ctx->stream_classes, (gpointer) id) ||
+       if (g_hash_table_lookup(ctx->stream_classes, &id) ||
                        existing_stream_class) {
                _BT_LOGE_NODE(node,
                        "Duplicate stream class (same ID): id=%" PRId64,
@@ -4155,8 +4318,16 @@ int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
                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;
        goto end;
@@ -4439,14 +4610,12 @@ int visit_env(struct ctx *ctx, struct ctf_node *node)
                                goto error;
                        }
 
-                       if (!ctx->decoder_config.strict) {
-                               if (strcmp(left, "tracer_name") == 0) {
-                                       if (strncmp(right, "lttng", 5) == 0) {
-                                               BT_LOGI("Non-strict mode: detected LTTng trace from `%s` environment value: "
-                                                       "tracer-name=\"%s\"",
-                                                       left, right);
-                                               ctx->is_lttng = 1;
-                                       }
+                       if (strcmp(left, "tracer_name") == 0) {
+                               if (strncmp(right, "lttng", 5) == 0) {
+                                       BT_LOGI("Detected LTTng trace from `%s` environment value: "
+                                               "tracer-name=\"%s\"",
+                                               left, right);
+                                       ctx->is_lttng = 1;
                                }
                        }
 
@@ -4708,6 +4877,14 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
                        goto error;
                }
 
+               if (freq == -1ULL || freq == 0) {
+                       _BT_LOGE_NODE(entry_node,
+                               "Invalid clock class frequency: freq=%" PRIu64,
+                               freq);
+                       ret = -EINVAL;
+                       goto error;
+               }
+
                ret = bt_ctf_clock_class_set_frequency(clock, freq);
                if (ret) {
                        _BT_LOGE_NODE(entry_node,
@@ -4744,7 +4921,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
 
                _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)) {
                        _BT_LOGE_DUP_ATTR(entry_node, "offset_s",
@@ -4753,7 +4930,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
                        goto error;
                }
 
-               ret = get_unary_unsigned(
+               ret = get_unary_signed(
                        &entry_node->u.ctf_expression.right, &offset_s);
                if (ret) {
                        _BT_LOGE_NODE(entry_node,
@@ -4771,7 +4948,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
 
                _SET(set, _CLOCK_OFFSET_S_SET);
        } else if (!strcmp(left, "offset")) {
-               uint64_t offset;
+               int64_t offset;
 
                if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
                        _BT_LOGE_DUP_ATTR(entry_node, "offset", "clock class");
@@ -4779,7 +4956,7 @@ int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
                        goto error;
                }
 
-               ret = get_unary_unsigned(
+               ret = get_unary_signed(
                        &entry_node->u.ctf_expression.right, &offset);
                if (ret) {
                        _BT_LOGE_NODE(entry_node,
@@ -4904,7 +5081,9 @@ int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node)
        }
 
        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_ctf_clock_class_create(NULL, 1000000000);
        if (!clock) {
                _BT_LOGE_NODE(clock_node,
                        "Cannot create default clock class.");
This page took 0.036757 seconds and 4 git commands to generate.