Fix: remove underscores from CTF IR field names at the source
[babeltrace.git] / plugins / ctf / common / metadata / visitor-generate-ir.c
index adb1e9c7c86e8ef59d2d5c1e777cb5776a51f8f2..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"
@@ -592,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;
@@ -670,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)
 {
@@ -882,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;
@@ -891,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;
@@ -1040,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
@@ -1326,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;
@@ -1383,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,
@@ -1391,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) {
@@ -1651,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;
@@ -1663,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;
@@ -2020,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);
@@ -3622,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) +
@@ -3634,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,
@@ -3642,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: "
@@ -3651,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(
@@ -3687,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,
@@ -3966,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,
@@ -4129,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;
@@ -4229,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,
@@ -4238,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;
@@ -4789,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,
@@ -4825,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",
@@ -4834,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,
@@ -4852,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");
@@ -4860,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,
This page took 0.030385 seconds and 4 git commands to generate.