Duplicate variant field name check
[babeltrace.git] / formats / ctf / metadata / ctf-visitor-generate-io-struct.c
index 7688f5f1f3cd27470420770139b58b7c9d0fdc3f..bdb5c68d6cfaa45ec3395fc7ad408eb23ff9792a 100644 (file)
@@ -317,8 +317,17 @@ struct declaration *ctf_type_declarator_visit(FILE *fd, int depth,
                                struct declaration_integer *integer_declaration =
                                        container_of(nested_declaration, struct declaration_integer, p);
                                /* For base to 16 for pointers (expected pretty-print) */
-                               if (!integer_declaration->base)
-                                       integer_declaration->base = 16;
+                               if (!integer_declaration->base) {
+                                       /*
+                                        * We need to do a copy of the
+                                        * integer declaration to modify it. There could be other references to
+                                        * it.
+                                        */
+                                       integer_declaration = integer_declaration_new(integer_declaration->len,
+                                               integer_declaration->byte_order, integer_declaration->signedness,
+                                               integer_declaration->p.alignment, 16, integer_declaration->encoding);
+                                       nested_declaration = &integer_declaration->p;
+                               }
                        }
                } else {
                        nested_declaration = ctf_type_specifier_list_visit(fd, depth,
@@ -337,57 +346,52 @@ struct declaration *ctf_type_declarator_visit(FILE *fd, int depth,
                return nested_declaration;
        } else {
                struct declaration *declaration;
-               struct ctf_node *length;
+               struct ctf_node *first;
 
                /* TYPEDEC_NESTED */
 
+               if (!nested_declaration) {
+                       fprintf(fd, "[error] %s: nested type is unknown.\n", __func__);
+                       return NULL;
+               }
+
                /* create array/sequence, pass nested_declaration as child. */
-               length = node_type_declarator->u.type_declarator.u.nested.length;
-               if (!length) {
-                       fprintf(fd, "[error] %s: expecting length type or value.\n", __func__);
+               if (cds_list_empty(&node_type_declarator->u.type_declarator.u.nested.length)) {
+                       fprintf(fd, "[error] %s: expecting length field reference or value.\n", __func__);
                        return NULL;
                }
-               switch (length->type) {
-               case NODE_UNARY_EXPRESSION:
+               first = _cds_list_first_entry(&node_type_declarator->u.type_declarator.u.nested.length, 
+                               struct ctf_node, siblings);
+               assert(first->type == NODE_UNARY_EXPRESSION);
+
+               switch (first->u.unary_expression.type) {
+               case UNARY_UNSIGNED_CONSTANT:
                {
                        struct declaration_array *array_declaration;
                        size_t len;
 
-                       if (length->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
-                               fprintf(fd, "[error] %s: array: unexpected unary expression.\n", __func__);
-                               return NULL;
-                       }
-                       len = length->u.unary_expression.u.unsigned_constant;
+                       len = first->u.unary_expression.u.unsigned_constant;
                        array_declaration = array_declaration_new(len, nested_declaration,
                                                declaration_scope);
+
+                       if (!array_declaration) {
+                               fprintf(fd, "[error] %s: cannot create array declaration.\n", __func__);
+                               return NULL;
+                       }
                        declaration = &array_declaration->p;
                        break;
                }
-               case NODE_TYPE_SPECIFIER_LIST:
+               case UNARY_STRING:
                {
+                       /* Lookup unsigned integer definition, create sequence */
+                       char *length_name = concatenate_unary_strings(&node_type_declarator->u.type_declarator.u.nested.length);
                        struct declaration_sequence *sequence_declaration;
-                       struct declaration_integer *integer_declaration;
 
-                       declaration = ctf_type_specifier_list_visit(fd, depth,
-                               length, declaration_scope, trace);
-                       if (!declaration) {
-                               fprintf(fd, "[error] %s: unable to find declaration type for sequence length\n", __func__);
-                               return NULL;
-                       }
-                       if (declaration->id != CTF_TYPE_INTEGER) {
-                               fprintf(fd, "[error] %s: length type for sequence is expected to be an integer (unsigned).\n", __func__);
-                               declaration_unref(declaration);
+                       sequence_declaration = sequence_declaration_new(length_name, nested_declaration, declaration_scope);
+                       if (!sequence_declaration) {
+                               fprintf(fd, "[error] %s: cannot create sequence declaration.\n", __func__);
                                return NULL;
                        }
-                       integer_declaration = container_of(declaration, struct declaration_integer, p);
-                       if (integer_declaration->signedness != false) {
-                               fprintf(fd, "[error] %s: length type for sequence should always be an unsigned integer.\n", __func__);
-                               declaration_unref(declaration);
-                               return NULL;
-                       }
-
-                       sequence_declaration = sequence_declaration_new(integer_declaration,
-                                       nested_declaration, declaration_scope);
                        declaration = &sequence_declaration->p;
                        break;
                }
@@ -427,6 +431,13 @@ int ctf_struct_type_declarators_visit(FILE *fd, int depth,
                        fprintf(fd, "[error] %s: unable to find struct field declaration type\n", __func__);
                        return -EINVAL;
                }
+
+               /* Check if field with same name already exists */
+               if (struct_declaration_lookup_field_index(struct_declaration, field_name) >= 0) {
+                       fprintf(fd, "[error] %s: duplicate field %s in struct\n", __func__, g_quark_to_string(field_name));
+                       return -EINVAL;
+               }
+
                struct_declaration_add_field(struct_declaration,
                                             g_quark_to_string(field_name),
                                             field_declaration);
@@ -457,6 +468,13 @@ int ctf_variant_type_declarators_visit(FILE *fd, int depth,
                        fprintf(fd, "[error] %s: unable to find variant field declaration type\n", __func__);
                        return -EINVAL;
                }
+
+               if (untagged_variant_declaration_get_field_from_tag(untagged_variant_declaration, field_name) != NULL) {
+                       fprintf(fd, "[error] %s: duplicate field %s in variant\n", __func__, g_quark_to_string(field_name));
+                       return -EINVAL;
+               }
+
+
                untagged_variant_declaration_add_field(untagged_variant_declaration,
                                              g_quark_to_string(field_name),
                                              field_declaration);
@@ -1077,6 +1095,7 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
        int signedness = 0;
        int has_alignment = 0, has_size = 0;
        int base = 0;
+       enum ctf_string_encoding encoding = CTF_STRING_NONE;
        struct declaration_integer *integer_declaration;
 
        cds_list_for_each_entry(expression, expressions, siblings) {
@@ -1165,6 +1184,36 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
                                        __func__);
                                return NULL;
                        }
+               } else if (!strcmp(left->u.unary_expression.u.string, "encoding")) {
+                       char *s_right;
+
+                       if (right->u.unary_expression.type != UNARY_STRING) {
+                               fprintf(fd, "[error] %s: encoding: expecting unary string\n",
+                                       __func__);
+                               return NULL;
+                       }
+                       s_right = concatenate_unary_strings(&expression->u.ctf_expression.right);
+                       if (!s_right) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for integer base\n", __func__);
+                               g_free(s_right);
+                               return NULL;
+                       }
+                       if (!strcmp(s_right, "UTF8")
+                           || !strcmp(s_right, "utf8")
+                           || !strcmp(s_right, "utf-8")
+                           || !strcmp(s_right, "UTF-8"))
+                               encoding = CTF_STRING_UTF8;
+                       else if (!strcmp(s_right, "ASCII")
+                           || !strcmp(s_right, "ascii"))
+                               encoding = CTF_STRING_ASCII;
+                       else if (!strcmp(s_right, "none"))
+                               encoding = CTF_STRING_NONE;
+                       else {
+                               fprintf(fd, "[error] %s: unknown string encoding \"%s\"\n", __func__, s_right);
+                               g_free(s_right);
+                               return NULL;
+                       }
+                       g_free(s_right);
                } else {
                        fprintf(fd, "[error] %s: unknown attribute name %s\n",
                                __func__, left->u.unary_expression.u.string);
@@ -1185,7 +1234,8 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
                }
        }
        integer_declaration = integer_declaration_new(size,
-                               byte_order, signedness, alignment, base);
+                               byte_order, signedness, alignment,
+                               base, encoding);
        return &integer_declaration->p;
 }
 
@@ -1496,6 +1546,10 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru
                                goto error;
                        }
                        event->fields_decl = container_of(declaration, struct declaration_struct, p);
+               } else {
+                       fprintf(fd, "[error] %s: attribute \"%s\" is unknown in event declaration.\n", __func__, left);
+                       ret = -EINVAL;
+                       goto error;
                }
 error:
                g_free(left);
@@ -1516,7 +1570,6 @@ int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node,
        int ret = 0;
        struct ctf_node *iter;
        struct ctf_event *event;
-       struct definition_scope *parent_def_scope;
 
        event = g_new0(struct ctf_event, 1);
        event->declaration_scope = new_declaration_scope(parent_declaration_scope);
@@ -1561,36 +1614,13 @@ int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node,
        g_hash_table_insert(event->stream->event_quark_to_id,
                            (gpointer)(unsigned long) event->name,
                            &event->id);
-       parent_def_scope = event->stream->definition_scope;
-       if (event->context_decl) {
-               event->context =
-                       container_of(
-                       event->context_decl->p.definition_new(&event->context_decl->p,
-                               parent_def_scope, 0, 0),
-                       struct definition_struct, p);
-               set_dynamic_definition_scope(&event->context->p,
-                                            event->context->scope,
-                                            "event.context");
-               parent_def_scope = event->context->scope;
-               declaration_unref(&event->context_decl->p);
-       }
-       if (event->fields_decl) {
-               event->fields =
-                       container_of(
-                       event->fields_decl->p.definition_new(&event->fields_decl->p,
-                               parent_def_scope, 0, 0),
-                       struct definition_struct, p);
-               set_dynamic_definition_scope(&event->fields->p,
-                                            event->fields->scope,
-                                            "event.fields");
-               parent_def_scope = event->fields->scope;
-               declaration_unref(&event->fields_decl->p);
-       }
        return 0;
 
 error:
-       declaration_unref(&event->fields_decl->p);
-       declaration_unref(&event->context_decl->p);
+       if (event->fields_decl)
+               declaration_unref(&event->fields_decl->p);
+       if (event->context_decl)
+               declaration_unref(&event->context_decl->p);
        free_declaration_scope(event->declaration_scope);
        g_free(event);
        return ret;
@@ -1701,7 +1731,12 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str
                                goto error;
                        }
                        stream->packet_context_decl = container_of(declaration, struct declaration_struct, p);
+               } else {
+                       fprintf(fd, "[error] %s: attribute \"%s\" is unknown in stream declaration.\n", __func__, left);
+                       ret = -EINVAL;
+                       goto error;
                }
+
 error:
                g_free(left);
                break;
@@ -1721,13 +1756,12 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
        int ret = 0;
        struct ctf_node *iter;
        struct ctf_stream_class *stream;
-       struct definition_scope *parent_def_scope;
 
        stream = g_new0(struct ctf_stream_class, 1);
        stream->declaration_scope = new_declaration_scope(parent_declaration_scope);
        stream->events_by_id = g_ptr_array_new();
        stream->event_quark_to_id = g_hash_table_new(g_direct_hash, g_direct_equal);
-       stream->files = g_ptr_array_new();
+       stream->streams = g_ptr_array_new();
        if (node) {
                cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) {
                        ret = ctf_stream_declaration_visit(fd, depth + 1, iter, stream, trace);
@@ -1756,52 +1790,16 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
                g_ptr_array_set_size(trace->streams, stream->stream_id + 1);
        g_ptr_array_index(trace->streams, stream->stream_id) = stream;
 
-       parent_def_scope = trace->definition_scope;
-       if (stream->packet_context_decl) {
-               stream->packet_context =
-                       container_of(
-                       stream->packet_context_decl->p.definition_new(&stream->packet_context_decl->p,
-                               parent_def_scope, 0, 0),
-                       struct definition_struct, p);
-               set_dynamic_definition_scope(&stream->packet_context->p,
-                                            stream->packet_context->scope,
-                                            "stream.packet.context");
-               parent_def_scope = stream->packet_context->scope;
-               declaration_unref(&stream->packet_context_decl->p);
-       }
-       if (stream->event_header_decl) {
-               stream->event_header =
-                       container_of(
-                       stream->event_header_decl->p.definition_new(&stream->event_header_decl->p,
-                               parent_def_scope, 0, 0),
-                       struct definition_struct, p);
-               set_dynamic_definition_scope(&stream->event_header->p,
-                                            stream->event_header->scope,
-                                            "stream.event.header");
-               parent_def_scope = stream->event_header->scope;
-               declaration_unref(&stream->event_header_decl->p);
-       }
-       if (stream->event_context_decl) {
-               stream->event_context =
-                       container_of(
-                       stream->event_context_decl->p.definition_new(&stream->event_context_decl->p,
-                               parent_def_scope, 0, 0),
-                       struct definition_struct, p);
-               set_dynamic_definition_scope(&stream->event_context->p,
-                                            stream->event_context->scope,
-                                            "stream.event.context");
-               parent_def_scope = stream->event_context->scope;
-               declaration_unref(&stream->event_context_decl->p);
-       }
-       stream->definition_scope = parent_def_scope;
-
        return 0;
 
 error:
-       declaration_unref(&stream->event_header_decl->p);
-       declaration_unref(&stream->event_context_decl->p);
-       declaration_unref(&stream->packet_context_decl->p);
-       g_ptr_array_free(stream->files, TRUE);
+       if (stream->event_header_decl)
+               declaration_unref(&stream->event_header_decl->p);
+       if (stream->event_context_decl)
+               declaration_unref(&stream->event_context_decl->p);
+       if (stream->packet_context_decl)
+               declaration_unref(&stream->packet_context_decl->p);
+       g_ptr_array_free(stream->streams, TRUE);
        g_ptr_array_free(stream->events_by_id, TRUE);
        g_hash_table_destroy(stream->event_quark_to_id);
        free_declaration_scope(stream->declaration_scope);
@@ -1864,32 +1862,40 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru
                        }
                        CTF_TRACE_SET_FIELD(trace, minor);
                } else if (!strcmp(left, "uuid")) {
-                       if (CTF_TRACE_FIELD_IS_SET(trace, uuid)) {
-                               fprintf(fd, "[error] %s: uuid already declared in trace declaration\n", __func__);
-                               ret = -EPERM;
-                               goto error;
-                       }
-                       ret = get_unary_uuid(&node->u.ctf_expression.right, &trace->uuid);
+                       uuid_t uuid;
+
+                       ret = get_unary_uuid(&node->u.ctf_expression.right, &uuid);
                        if (ret) {
                                fprintf(fd, "[error] %s: unexpected unary expression for trace uuid\n", __func__);
                                ret = -EINVAL;
                                goto error;
                        }
+                       if (CTF_TRACE_FIELD_IS_SET(trace, uuid)
+                               && uuid_compare(uuid, trace->uuid)) {
+                               fprintf(fd, "[error] %s: uuid mismatch\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       } else {
+                               memcpy(trace->uuid, uuid, sizeof(uuid));
+                       }
                        CTF_TRACE_SET_FIELD(trace, uuid);
                } else if (!strcmp(left, "byte_order")) {
                        struct ctf_node *right;
                        int byte_order;
 
-                       if (CTF_TRACE_FIELD_IS_SET(trace, byte_order)) {
-                               fprintf(fd, "[error] %s: endianness already declared in trace declaration\n", __func__);
-                               ret = -EPERM;
-                               goto error;
-                       }
                        right = _cds_list_first_entry(&node->u.ctf_expression.right, struct ctf_node, siblings);
                        byte_order = get_trace_byte_order(fd, depth, right);
                        if (byte_order < 0)
                                return -EINVAL;
-                       trace->byte_order = byte_order;
+
+                       if (CTF_TRACE_FIELD_IS_SET(trace, byte_order)
+                               && byte_order != trace->byte_order) {
+                               fprintf(fd, "[error] %s: endianness mismatch\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       } else {
+                               trace->byte_order = byte_order;
+                       }
                        CTF_TRACE_SET_FIELD(trace, byte_order);
                } else if (!strcmp(left, "packet.header")) {
                        struct declaration *declaration;
@@ -1912,7 +1918,12 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru
                                goto error;
                        }
                        trace->packet_header_decl = container_of(declaration, struct declaration_struct, p);
+               } else {
+                       fprintf(fd, "[error] %s: attribute \"%s\" is unknown in trace declaration.\n", __func__, left);
+                       ret = -EINVAL;
+                       goto error;
                }
+
 error:
                g_free(left);
                break;
@@ -1928,7 +1939,6 @@ error:
 static
 int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
 {
-       struct definition_scope *parent_def_scope;
        int ret = 0;
        struct ctf_node *iter;
 
@@ -1962,35 +1972,20 @@ int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace
                goto error;
        }
 
-       parent_def_scope = NULL;
-       if (trace->packet_header_decl) {
-               trace->packet_header =
-                       container_of(
-                       trace->packet_header_decl->p.definition_new(&trace->packet_header_decl->p,
-                               parent_def_scope, 0, 0),
-                       struct definition_struct, p);
-               set_dynamic_definition_scope(&trace->packet_header->p,
-                                            trace->packet_header->scope,
-                                            "trace.packet.header");
-               parent_def_scope = trace->packet_header->scope;
-               declaration_unref(&trace->packet_header_decl->p);
-       }
-       trace->definition_scope = parent_def_scope;
-
        if (!CTF_TRACE_FIELD_IS_SET(trace, byte_order)) {
                /* check that the packet header contains a "magic" field */
-               if (!trace->packet_header
+               if (!trace->packet_header_decl
                    || struct_declaration_lookup_field_index(trace->packet_header_decl, g_quark_from_static_string("magic")) < 0) {
                        ret = -EPERM;
                        fprintf(fd, "[error] %s: missing both byte_order and packet header magic number in trace declaration\n", __func__);
-                       goto error_free_def;
+                       goto error;
                }
        }
        return 0;
 
-error_free_def:
-       definition_unref(&trace->packet_header->p);
 error:
+       if (trace->packet_header_decl)
+               declaration_unref(&trace->packet_header_decl->p);
        g_ptr_array_free(trace->streams, TRUE);
        free_declaration_scope(trace->declaration_scope);
        return ret;
@@ -2049,7 +2044,6 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
 
        printf_verbose("CTF visitor: metadata construction... ");
        trace->root_declaration_scope = new_declaration_scope(NULL);
-       trace->streams = g_ptr_array_new();
        trace->byte_order = byte_order;
 
        switch (node->type) {
@@ -2059,26 +2053,27 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
                        ret = ctf_root_declaration_visit(fd, depth + 1, iter, trace);
                        if (ret) {
                                fprintf(fd, "[error] %s: root declaration error\n", __func__);
-                               return ret;
+                               goto error;
                        }
                }
                cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
                        ret = ctf_trace_visit(fd, depth + 1, iter, trace);
                        if (ret) {
                                fprintf(fd, "[error] %s: trace declaration error\n", __func__);
-                               return ret;
+                               goto error;
                        }
                }
                if (!trace->streams) {
                        fprintf(fd, "[error] %s: missing trace declaration\n", __func__);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto error;
                }
                cds_list_for_each_entry(iter, &node->u.root.stream, siblings) {
                        ret = ctf_stream_visit(fd, depth + 1, iter,
                                               trace->root_declaration_scope, trace);
                        if (ret) {
                                fprintf(fd, "[error] %s: stream declaration error\n", __func__);
-                               return ret;
+                               goto error;
                        }
                }
                cds_list_for_each_entry(iter, &node->u.root.event, siblings) {
@@ -2086,7 +2081,7 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
                                              trace->root_declaration_scope, trace);
                        if (ret) {
                                fprintf(fd, "[error] %s: event declaration error\n", __func__);
-                               return ret;
+                               goto error;
                        }
                }
                break;
@@ -2094,8 +2089,13 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
        default:
                fprintf(fd, "[error] %s: unknown node type %d\n", __func__,
                        (int) node->type);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto error;
        }
        printf_verbose("done.\n");
        return ret;
+
+error:
+       free_declaration_scope(trace->root_declaration_scope);
+       return ret;
 }
This page took 0.029685 seconds and 4 git commands to generate.