X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=formats%2Fctf%2Fmetadata%2Fctf-visitor-generate-io-struct.c;h=a8aebf919fc3e2d77b43b02d985bd3f0cab67104;hp=725235d18a8d66a980134600fe44dade95aec6bc;hb=56e603733d2a16aba6fdaf149ad6a4cd42e44eda;hpb=70bd0a12b09ce7f233189cf07e090fda593ebc48 diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 725235d1..a8aebf91 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -87,6 +87,50 @@ char *concatenate_unary_strings(struct cds_list_head *head) return g_string_free(str, FALSE); } +static +GQuark get_map_clock_name_value(struct cds_list_head *head) +{ + struct ctf_node *node; + const char *name = NULL; + int i = 0; + + cds_list_for_each_entry(node, head, siblings) { + char *src_string; + + assert(node->type == NODE_UNARY_EXPRESSION); + assert(node->u.unary_expression.type == UNARY_STRING); + assert((node->u.unary_expression.link == UNARY_LINK_UNKNOWN) + ^ (i != 0)); + /* needs to be chained with . */ + switch (node->u.unary_expression.link) { + case UNARY_DOTLINK: + break; + case UNARY_ARROWLINK: + case UNARY_DOTDOTDOT: + return 0; + default: + break; + } + src_string = node->u.unary_expression.u.string; + switch (i) { + case 0: if (strcmp("clock", src_string) != 0) { + return 0; + } + break; + case 1: name = src_string; + break; + case 2: if (strcmp("value", src_string) != 0) { + return 0; + } + break; + default: + return 0; /* extra identifier, unknown */ + } + i++; + } + return g_quark_from_string(name); +} + static int get_unary_unsigned(struct cds_list_head *head, uint64_t *value) { @@ -104,6 +148,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) { @@ -132,6 +193,12 @@ struct ctf_stream_class *trace_stream_lookup(struct ctf_trace *trace, uint64_t s return g_ptr_array_index(trace->streams, stream_id); } +static +struct ctf_clock *trace_clock_lookup(struct ctf_trace *trace, GQuark clock_name) +{ + return g_hash_table_lookup(trace->clocks, (gpointer) (unsigned long) clock_name); +} + static int visit_type_specifier(FILE *fd, struct ctf_node *type_specifier, GString *str) { @@ -325,7 +392,8 @@ struct declaration *ctf_type_declarator_visit(FILE *fd, int depth, */ integer_declaration = integer_declaration_new(integer_declaration->len, integer_declaration->byte_order, integer_declaration->signedness, - integer_declaration->p.alignment, 16, integer_declaration->encoding); + integer_declaration->p.alignment, 16, integer_declaration->encoding, + integer_declaration->clock); nested_declaration = &integer_declaration->p; } } @@ -1099,6 +1167,7 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth, int has_alignment = 0, has_size = 0; int base = 0; enum ctf_string_encoding encoding = CTF_STRING_NONE; + struct ctf_clock *clock = NULL; struct declaration_integer *integer_declaration; cds_list_for_each_entry(expression, expressions, siblings) { @@ -1217,10 +1286,40 @@ 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")) { + GQuark clock_name; + + if (right->u.unary_expression.type != UNARY_STRING) { + fprintf(fd, "[error] %s: map: expecting identifier\n", + __func__); + return NULL; + } + /* currently only support clock.name.value */ + clock_name = get_map_clock_name_value(&expression->u.ctf_expression.right); + if (!clock_name) { + char *s_right; + + 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; + } + fprintf(fd, "[warning] %s: unknown map %s in integer declaration\n", __func__, + s_right); + g_free(s_right); + continue; + } + clock = trace_clock_lookup(trace, clock_name); + if (!clock) { + fprintf(fd, "[error] %s: map: unable to find clock %s declaration\n", + __func__, g_quark_to_string(clock_name)); + return NULL; + } } 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) { @@ -1238,7 +1337,7 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth, } integer_declaration = integer_declaration_new(size, byte_order, signedness, alignment, - base, encoding); + base, encoding, clock); return &integer_declaration->p; } @@ -1294,9 +1393,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) { @@ -1345,9 +1444,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")) @@ -1550,10 +1649,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); @@ -1616,7 +1744,7 @@ int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node, g_ptr_array_set_size(event->stream->events_by_id, event->id + 1); g_ptr_array_index(event->stream->events_by_id, event->id) = event; g_hash_table_insert(event->stream->event_quark_to_id, - (gpointer)(unsigned long) event->name, + (gpointer) (unsigned long) event->name, &event->id); return 0; @@ -1736,9 +1864,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: @@ -1793,6 +1920,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; @@ -1934,9 +2062,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: @@ -2009,6 +2135,164 @@ error: 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) { @@ -2054,20 +2338,39 @@ 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) { int ret = 0; struct ctf_node *iter; + int clock_done = 0; printf_verbose("CTF visitor: metadata construction... "); 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: + if (!clock_done) { + /* + * declarations need to query clock hash table, + * so clock need to be treated first. + */ + 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; + } + } + clock_done = 1; + } cds_list_for_each_entry(iter, &node->u.root.declaration_list, siblings) { ret = ctf_root_declaration_visit(fd, depth + 1, iter, trace); @@ -2126,5 +2429,6 @@ retry: error: free_declaration_scope(trace->root_declaration_scope); + g_hash_table_destroy(trace->clocks); return ret; }