Create copy of integer declaration before applying base-16 for pointers
[babeltrace.git] / formats / ctf / metadata / ctf-visitor-generate-io-struct.c
index 1eb763de79b1f407a9e4b268c9e1012a04386990..507233c97cdf3b4fbdf4ce8e24548be2a8fb6967 100644 (file)
@@ -25,6 +25,7 @@
 #include <inttypes.h>
 #include <endian.h>
 #include <errno.h>
+#include <babeltrace/babeltrace.h>
 #include <babeltrace/list.h>
 #include <babeltrace/types.h>
 #include <babeltrace/ctf/metadata.h>
@@ -44,6 +45,10 @@ struct declaration *ctf_type_specifier_list_visit(FILE *fd,
                struct declaration_scope *declaration_scope,
                struct ctf_trace *trace);
 
+static
+int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
+                    struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace);
+
 /*
  * String returned must be freed by the caller using g_free.
  */
@@ -120,7 +125,7 @@ int get_unary_uuid(struct cds_list_head *head, uuid_t *uuid)
 }
 
 static
-struct ctf_stream *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
+struct ctf_stream_class *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
 {
        if (trace->streams->len <= stream_id)
                return NULL;
@@ -308,6 +313,22 @@ struct declaration *ctf_type_declarator_visit(FILE *fd, int depth,
                                fprintf(fd, "[error] %s: cannot find typealias \"%s\".\n", __func__, g_quark_to_string(alias_q));
                                return NULL;
                        }
+                       if (nested_declaration->id == CTF_TYPE_INTEGER) {
+                               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) {
+                                       /*
+                                        * 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);
+                                       nested_declaration = &integer_declaration->p;
+                               }
+                       }
                } else {
                        nested_declaration = ctf_type_specifier_list_visit(fd, depth,
                                type_specifier_list, declaration_scope, trace);
@@ -648,7 +669,8 @@ int ctf_variant_declaration_list_visit(FILE *fd, int depth,
 static
 struct declaration *ctf_declaration_struct_visit(FILE *fd,
        int depth, const char *name, struct cds_list_head *declaration_list,
-       int has_body, struct declaration_scope *declaration_scope,
+       int has_body, struct cds_list_head *min_align,
+       struct declaration_scope *declaration_scope,
        struct ctf_trace *trace)
 {
        struct declaration_struct *struct_declaration;
@@ -667,6 +689,8 @@ struct declaration *ctf_declaration_struct_visit(FILE *fd,
                                                  declaration_scope);
                return &struct_declaration->p;
        } else {
+               uint64_t min_align_value = 0;
+
                /* For unnamed struct, create type */
                /* For named struct (with body), create type and add to declaration scope */
                if (name) {
@@ -677,7 +701,16 @@ struct declaration *ctf_declaration_struct_visit(FILE *fd,
                                return NULL;
                        }
                }
-               struct_declaration = struct_declaration_new(declaration_scope);
+               if (!cds_list_empty(min_align)) {
+                       ret = get_unary_unsigned(min_align, &min_align_value);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for structure \"align\" attribute\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+               }
+               struct_declaration = struct_declaration_new(declaration_scope,
+                                                           min_align_value);
                cds_list_for_each_entry(iter, declaration_list, siblings) {
                        ret = ctf_struct_declaration_list_visit(fd, depth + 1, iter,
                                struct_declaration, trace);
@@ -1052,6 +1085,7 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
        int byte_order = trace->byte_order;
        int signedness = 0;
        int has_alignment = 0, has_size = 0;
+       int base = 0;
        struct declaration_integer *integer_declaration;
 
        cds_list_for_each_entry(expression, expressions, siblings) {
@@ -1083,7 +1117,63 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
                                return NULL;
                        }
                        alignment = right->u.unary_expression.u.unsigned_constant;
+                       /* Make sure alignment is a power of two */
+                       if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
+                               fprintf(fd, "[error] %s: align: expecting power of two\n",
+                                       __func__);
+                               return NULL;
+                       }
                        has_alignment = 1;
+               } else if (!strcmp(left->u.unary_expression.u.string, "base")) {
+                       switch (right->u.unary_expression.type) {
+                       case UNARY_UNSIGNED_CONSTANT:
+                               switch (right->u.unary_expression.u.unsigned_constant) {
+                               case 2: 
+                               case 8:
+                               case 10:
+                               case 16:
+                                       base = right->u.unary_expression.u.unsigned_constant;
+                                       break;
+                               default:
+                                       fprintf(fd, "[error] %s: base not supported (%" PRIu64 ")\n",
+                                               __func__, right->u.unary_expression.u.unsigned_constant);
+                               return NULL;
+                               }
+                               break;
+                       case UNARY_STRING:
+                       {
+                               char *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, "decimal") || !strcmp(s_right, "dec") || !strcmp(s_right, "d")
+                                   || !strcmp(s_right, "i") || !strcmp(s_right, "u")) {
+                                       base = 10;
+                               } else if (!strcmp(s_right, "hexadecimal") || !strcmp(s_right, "hex")
+                                   || !strcmp(s_right, "x") || !strcmp(s_right, "X")
+                                   || !strcmp(s_right, "p")) {
+                                       base = 16;
+                               } else if (!strcmp(s_right, "octal") || !strcmp(s_right, "oct")
+                                   || !strcmp(s_right, "o")) {
+                                       base = 8;
+                               } else if (!strcmp(s_right, "binary") || !strcmp(s_right, "b")) {
+                                       base = 2;
+                               } else {
+                                       fprintf(fd, "[error] %s: unexpected expression for integer base (%s)\n", __func__, s_right);
+                                       g_free(s_right);
+                                       return NULL;
+                               }
+
+                               g_free(s_right);
+                               break;
+                       }
+                       default:
+                               fprintf(fd, "[error] %s: base: expecting unsigned constant or unary string\n",
+                                       __func__);
+                               return NULL;
+                       }
                } else {
                        fprintf(fd, "[error] %s: unknown attribute name %s\n",
                                __func__, left->u.unary_expression.u.string);
@@ -1104,7 +1194,7 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
                }
        }
        integer_declaration = integer_declaration_new(size,
-                               byte_order, signedness, alignment);
+                               byte_order, signedness, alignment, base);
        return &integer_declaration->p;
 }
 
@@ -1151,6 +1241,12 @@ struct declaration *ctf_declaration_floating_point_visit(FILE *fd, int depth,
                                return NULL;
                        }
                        alignment = right->u.unary_expression.u.unsigned_constant;
+                       /* Make sure alignment is a power of two */
+                       if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
+                               fprintf(fd, "[error] %s: align: expecting power of two\n",
+                                       __func__);
+                               return NULL;
+                       }
                        has_alignment = 1;
                } else {
                        fprintf(fd, "[error] %s: unknown attribute name %s\n",
@@ -1248,6 +1344,7 @@ struct declaration *ctf_type_specifier_list_visit(FILE *fd,
                        node->u._struct.name,
                        &node->u._struct.declaration_list,
                        node->u._struct.has_body,
+                       &node->u._struct.min_align,
                        declaration_scope,
                        trace);
        case TYPESPEC_VARIANT:
@@ -1444,10 +1541,17 @@ int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node,
        }
        if (!CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
                /* Allow missing stream_id if there is only a single stream */
-               if (trace->streams->len == 1) {
+               switch (trace->streams->len) {
+               case 0: /* Create stream if there was none. */
+                       ret = ctf_stream_visit(fd, depth, NULL, trace->root_declaration_scope, trace);
+                       if (ret)
+                               goto error;
+                       /* Fall-through */
+               case 1:
                        event->stream_id = 0;
                        event->stream = trace_stream_lookup(trace, event->stream_id);
-               } else {
+                       break;
+               default:
                        ret = -EPERM;
                        fprintf(fd, "[error] %s: missing stream_id field in event declaration\n", __func__);
                        goto error;
@@ -1503,7 +1607,7 @@ error:
 
  
 static
-int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream *stream, struct ctf_trace *trace)
+int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream_class *stream, struct ctf_trace *trace)
 {
        int ret = 0;
 
@@ -1625,18 +1729,20 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
 {
        int ret = 0;
        struct ctf_node *iter;
-       struct ctf_stream *stream;
+       struct ctf_stream_class *stream;
        struct definition_scope *parent_def_scope;
 
-       stream = g_new0(struct ctf_stream, 1);
+       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();
-       cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) {
-               ret = ctf_stream_declaration_visit(fd, depth + 1, iter, stream, trace);
-               if (ret)
-                       goto error;
+       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);
+                       if (ret)
+                               goto error;
+               }
        }
        if (CTF_STREAM_FIELD_IS_SET(stream, stream_id)) {
                /* check that packet header has stream_id field. */
@@ -1950,8 +2056,9 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
        int ret = 0;
        struct ctf_node *iter;
 
-       fprintf(fd, "CTF visitor: metadata construction... ");
+       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) {
@@ -1998,6 +2105,6 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
                        (int) node->type);
                return -EINVAL;
        }
-       fprintf(fd, "done.\n");
+       printf_verbose("done.\n");
        return ret;
 }
This page took 0.028859 seconds and 4 git commands to generate.