Implement clock IR generation
[babeltrace.git] / formats / ctf / metadata / ctf-visitor-generate-io-struct.c
index cda3329be4455be450b31d611ce0c8e0dee23690..cb3dc008c76c126deffe53e85cbd5b6a829ba521 100644 (file)
@@ -25,7 +25,7 @@
 #include <inttypes.h>
 #include <endian.h>
 #include <errno.h>
-#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/list.h>
 #include <babeltrace/types.h>
 #include <babeltrace/ctf/metadata.h>
@@ -104,6 +104,23 @@ int get_unary_unsigned(struct cds_list_head *head, uint64_t *value)
        return 0;
 }
 
+static
+int get_unary_signed(struct cds_list_head *head, int64_t *value)
+{
+       struct ctf_node *node;
+       int i = 0;
+
+       cds_list_for_each_entry(node, head, siblings) {
+               assert(node->type == NODE_UNARY_EXPRESSION);
+               assert(node->u.unary_expression.type == UNARY_UNSIGNED_CONSTANT);
+               assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
+               assert(i == 0);
+               *value = node->u.unary_expression.u.signed_constant;
+               i++;
+       }
+       return 0;
+}
+
 static
 int get_unary_uuid(struct cds_list_head *head, uuid_t *uuid)
 {
@@ -119,7 +136,7 @@ int get_unary_uuid(struct cds_list_head *head, uuid_t *uuid)
                assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
                assert(i == 0);
                src_string = node->u.unary_expression.u.string;
-               ret = uuid_parse(node->u.unary_expression.u.string, *uuid);
+               ret = uuid_parse(src_string, *uuid);
        }
        return ret;
 }
@@ -726,7 +743,7 @@ struct declaration *ctf_declaration_struct_visit(FILE *fd,
                        ret = ctf_struct_declaration_list_visit(fd, depth + 1, iter,
                                struct_declaration, trace);
                        if (ret)
-                               goto error;
+                               goto error_free_declaration;
                }
                if (name) {
                        ret = register_struct_declaration(g_quark_from_string(name),
@@ -736,8 +753,9 @@ struct declaration *ctf_declaration_struct_visit(FILE *fd,
                }
                return &struct_declaration->p;
        }
-error:
+error_free_declaration:
        struct_declaration->p.declaration_free(&struct_declaration->p);
+error:
        return NULL;
 }
 
@@ -1092,7 +1110,7 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
                struct ctf_trace *trace)
 {
        struct ctf_node *expression;
-       uint64_t alignment, size;
+       uint64_t alignment = 1, size = 0;
        int byte_order = trace->byte_order;
        int signedness = 0;
        int has_alignment = 0, has_size = 0;
@@ -1216,10 +1234,26 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth,
                                return NULL;
                        }
                        g_free(s_right);
+               } else if (!strcmp(left->u.unary_expression.u.string, "map")) {
+                       char *s_right;
+
+                       if (right->u.unary_expression.type != UNARY_STRING) {
+                               fprintf(fd, "[error] %s: map: expecting identifier\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 map\n", __func__);
+                               g_free(s_right);
+                               return NULL;
+                       }
+                       /* TODO: lookup */
+
                } else {
-                       fprintf(fd, "[error] %s: unknown attribute name %s\n",
+                       fprintf(fd, "[warning] %s: unknown attribute name %s\n",
                                __func__, left->u.unary_expression.u.string);
-                       return NULL;
+                       /* Fall-through after warning */
                }
        }
        if (!has_size) {
@@ -1247,7 +1281,8 @@ struct declaration *ctf_declaration_floating_point_visit(FILE *fd, int depth,
                struct ctf_trace *trace)
 {
        struct ctf_node *expression;
-       uint64_t alignment, exp_dig, mant_dig, byte_order = trace->byte_order;
+       uint64_t alignment = 1, exp_dig = 0, mant_dig = 0,
+               byte_order = trace->byte_order;
        int has_alignment = 0, has_exp_dig = 0, has_mant_dig = 0;
        struct declaration_float *float_declaration;
 
@@ -1292,9 +1327,9 @@ struct declaration *ctf_declaration_floating_point_visit(FILE *fd, int depth,
                        }
                        has_alignment = 1;
                } else {
-                       fprintf(fd, "[error] %s: unknown attribute name %s\n",
+                       fprintf(fd, "[warning] %s: unknown attribute name %s\n",
                                __func__, left->u.unary_expression.u.string);
-                       return NULL;
+                       /* Fall-through after warning */
                }
        }
        if (!has_mant_dig) {
@@ -1343,9 +1378,9 @@ struct declaration *ctf_declaration_string_visit(FILE *fd, int depth,
                        }
                        encoding_c = right->u.unary_expression.u.string;
                } else {
-                       fprintf(fd, "[error] %s: unknown attribute name %s\n",
+                       fprintf(fd, "[warning] %s: unknown attribute name %s\n",
                                __func__, left->u.unary_expression.u.string);
-                       return NULL;
+                       /* Fall-through after warning */
                }
        }
        if (encoding_c && !strcmp(encoding_c, "ASCII"))
@@ -1548,10 +1583,39 @@ 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 if (!strcmp(left, "loglevel.identifier")) {
+                       char *right;
+
+                       if (CTF_EVENT_FIELD_IS_SET(event, loglevel_identifier)) {
+                               fprintf(fd, "[error] %s: identifier already declared in event declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       right = concatenate_unary_strings(&node->u.ctf_expression.right);
+                       if (!right) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for event identifier\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       event->loglevel_identifier = g_quark_from_string(right);
+                       g_free(right);
+                       CTF_EVENT_SET_FIELD(event, loglevel_identifier);
+               } else if (!strcmp(left, "loglevel.value")) {
+                       if (CTF_EVENT_FIELD_IS_SET(event, loglevel_value)) {
+                               fprintf(fd, "[error] %s: loglevel value already declared in event declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       ret = get_unary_signed(&node->u.ctf_expression.right, &event->loglevel_value);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for event loglevel value\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       CTF_EVENT_SET_FIELD(event, loglevel_value);
                } else {
-                       fprintf(fd, "[error] %s: attribute \"%s\" is unknown in event declaration.\n", __func__, left);
-                       ret = -EINVAL;
-                       goto error;
+                       fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in event declaration.\n", __func__, left);
+                       /* Fall-through after warning */
                }
 error:
                g_free(left);
@@ -1734,9 +1798,8 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str
                        }
                        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;
+                       fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in stream declaration.\n", __func__, left);
+                       /* Fall-through after warning */
                }
 
 error:
@@ -1791,6 +1854,7 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
        if (trace->streams->len <= stream->stream_id)
                g_ptr_array_set_size(trace->streams, stream->stream_id + 1);
        g_ptr_array_index(trace->streams, stream->stream_id) = stream;
+       stream->trace = trace;
 
        return 0;
 
@@ -1896,7 +1960,18 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru
                                ret = -EPERM;
                                goto error;
                        } else {
-                               trace->byte_order = byte_order;
+                               if (byte_order != trace->byte_order) {
+                                       trace->byte_order = byte_order;
+                                       /*
+                                        * We need to restart
+                                        * construction of the
+                                        * intermediate representation.
+                                        */
+                                       trace->field_mask = 0;
+                                       CTF_TRACE_SET_FIELD(trace, byte_order);
+                                       ret = -EINTR;
+                                       goto error;
+                               }
                        }
                        CTF_TRACE_SET_FIELD(trace, byte_order);
                } else if (!strcmp(left, "packet.header")) {
@@ -1921,9 +1996,7 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru
                        }
                        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;
+                       fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in trace declaration.\n", __func__, left);
                }
 
 error:
@@ -1986,13 +2059,174 @@ int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace
        return 0;
 
 error:
-       if (trace->packet_header_decl)
+       if (trace->packet_header_decl) {
                declaration_unref(&trace->packet_header_decl->p);
+               trace->packet_header_decl = NULL;
+       }
        g_ptr_array_free(trace->streams, TRUE);
        free_declaration_scope(trace->declaration_scope);
+       trace->declaration_scope = NULL;
+       return ret;
+}
+
+static
+int ctf_clock_declaration_visit(FILE *fd, int depth, struct ctf_node *node,
+               struct ctf_clock *clock, struct ctf_trace *trace)
+{
+       int ret = 0;
+
+       switch (node->type) {
+       case NODE_CTF_EXPRESSION:
+       {
+               char *left;
+
+               left = concatenate_unary_strings(&node->u.ctf_expression.left);
+               if (!strcmp(left, "name")) {
+                       char *right;
+
+                       if (CTF_CLOCK_FIELD_IS_SET(clock, name)) {
+                               fprintf(fd, "[error] %s: name already declared in clock declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       right = concatenate_unary_strings(&node->u.ctf_expression.right);
+                       if (!right) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for clock name\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       clock->name = g_quark_from_string(right);
+                       g_free(right);
+                       CTF_EVENT_SET_FIELD(clock, name);
+               } else if (!strcmp(left, "uuid")) {
+                       char *right;
+
+                       if (clock->uuid) {
+                               fprintf(fd, "[error] %s: uuid already declared in clock declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       right = concatenate_unary_strings(&node->u.ctf_expression.right);
+                       if (!right) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for clock uuid\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       clock->uuid = g_quark_from_string(right);
+                       g_free(right);
+               } else if (!strcmp(left, "description")) {
+                       char *right;
+
+                       if (clock->description) {
+                               fprintf(fd, "[warning] %s: duplicated clock description\n", __func__);
+                               goto error;     /* ret is 0, so not an actual error, just warn. */
+                       }
+                       right = concatenate_unary_strings(&node->u.ctf_expression.right);
+                       if (!right) {
+                               fprintf(fd, "[warning] %s: unexpected unary expression for clock description\n", __func__);
+                               goto error;     /* ret is 0, so not an actual error, just warn. */
+                       }
+                       clock->description = right;
+               } else if (!strcmp(left, "freq")) {
+                       if (clock->freq) {
+                               fprintf(fd, "[error] %s: freq already declared in clock declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->freq);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for clock freq\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+               } else if (!strcmp(left, "precision")) {
+                       if (clock->precision) {
+                               fprintf(fd, "[error] %s: precision already declared in clock declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->precision);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for clock precision\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+               } else if (!strcmp(left, "offset_s")) {
+                       if (clock->offset_s) {
+                               fprintf(fd, "[error] %s: offset_s already declared in clock declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->offset_s);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for clock offset_s\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+               } else if (!strcmp(left, "offset")) {
+                       if (clock->offset) {
+                               fprintf(fd, "[error] %s: offset already declared in clock declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->offset);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for clock offset\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+               } else {
+                       fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in clock declaration.\n", __func__, left);
+               }
+
+error:
+               g_free(left);
+               break;
+       }
+       default:
+               return -EPERM;
+       /* TODO: declaration specifier should be added. */
+       }
+
+       return ret;
+}
+
+static
+int ctf_clock_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
+{
+       int ret = 0;
+       struct ctf_node *iter;
+       struct ctf_clock *clock;
+
+       clock = g_new0(struct ctf_clock, 1);
+       cds_list_for_each_entry(iter, &node->u.clock.declaration_list, siblings) {
+               ret = ctf_clock_declaration_visit(fd, depth + 1, iter, clock, trace);
+               if (ret)
+                       goto error;
+       }
+       if (!CTF_CLOCK_FIELD_IS_SET(clock, name)) {
+               ret = -EPERM;
+               fprintf(fd, "[error] %s: missing namefield in clock declaration\n", __func__);
+               goto error;
+       }
+       g_hash_table_insert(trace->clocks, (gpointer) (unsigned long) clock->name, clock);
+       return 0;
+
+error:
+       g_free(clock->description);
+       g_free(clock);
        return ret;
 }
 
+static
+void clock_free(gpointer data)
+{
+       struct ctf_clock *clock = data;
+
+       g_free(clock->description);
+       g_free(clock);
+}
+
 static
 int ctf_root_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
 {
@@ -2038,6 +2272,7 @@ int ctf_root_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struc
        return 0;
 }
 
+/* TODO: missing metadata "destroy" (memory leak) */
 int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
                struct ctf_trace *trace, int byte_order)
 {
@@ -2045,8 +2280,12 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
        struct ctf_node *iter;
 
        printf_verbose("CTF visitor: metadata construction... ");
-       trace->root_declaration_scope = new_declaration_scope(NULL);
        trace->byte_order = byte_order;
+       trace->clocks = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+                               NULL, clock_free);
+
+retry:
+       trace->root_declaration_scope = new_declaration_scope(NULL);
 
        switch (node->type) {
        case NODE_ROOT:
@@ -2060,11 +2299,29 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
                }
                cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
                        ret = ctf_trace_visit(fd, depth + 1, iter, trace);
+                       if (ret == -EINTR) {
+                               free_declaration_scope(trace->root_declaration_scope);
+                               /*
+                                * Need to restart creation of type
+                                * definitions, aliases and
+                                * trace header declarations.
+                                */
+                               goto retry;
+                       }
                        if (ret) {
                                fprintf(fd, "[error] %s: trace declaration error\n", __func__);
                                goto error;
                        }
                }
+               cds_list_for_each_entry(iter, &node->u.root.clock, siblings) {
+                       ret = ctf_clock_visit(fd, depth + 1, iter,
+                                             trace);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: clock declaration error\n", __func__);
+                               goto error;
+                       }
+               }
+
                if (!trace->streams) {
                        fprintf(fd, "[error] %s: missing trace declaration\n", __func__);
                        ret = -EINVAL;
@@ -2099,5 +2356,6 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
 
 error:
        free_declaration_scope(trace->root_declaration_scope);
+       g_hash_table_destroy(trace->clocks);
        return ret;
 }
This page took 0.028663 seconds and 4 git commands to generate.