From 9e29e16ee50d03cf4fdc0cea0220832323939dc3 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 14 Apr 2011 22:14:11 -0400 Subject: [PATCH 01/16] Dynamic definition scope hierarchy Correctly handle hierarchy of definition scope lookups. Signed-off-by: Mathieu Desnoyers --- .../metadata/ctf-visitor-generate-io-struct.c | 82 +++++++++++++++---- include/babeltrace/ctf/metadata.h | 14 +++- include/babeltrace/types.h | 8 +- types/types.c | 57 +++++++++---- 4 files changed, 127 insertions(+), 34 deletions(-) diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index a6773eea..260fc31c 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -384,7 +384,7 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru fprintf(stderr, "[error] %s: stream id %" PRIu64 " cannot be found\n", __func__, event->stream_id); return -EINVAL; } - event->definition_scope = new_definition_scope(stream->definition_scope); + event->definition_scope = new_dynamic_definition_scope(stream->definition_scope); if (!event->definition_scope) { fprintf(stderr, "[error] %s: Error allocating declaration scope\n", __func__); return -EPERM; @@ -402,8 +402,7 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) return -EPERM; - /* TODO: definition */ - event->context = container_of(declaration, struct declaration_struct, p); + event->context_decl = container_of(declaration, struct declaration_struct, p); } else if (!strcmp(left, "fields")) { struct declaration *declaration; @@ -416,8 +415,7 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) return -EPERM; - /* TODO: definition */ - event->fields = container_of(declaration, struct declaration_struct, p); + event->fields_decl = container_of(declaration, struct declaration_struct, p); } free(left); break; @@ -437,6 +435,7 @@ 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); @@ -463,11 +462,30 @@ 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->definition_scope; + if (event->context_decl) { + event->context = + event->context_decl->definition_new(event->context_decl, + parent_def_scope, + g_quark_from_string("event.context"), + MAX_INT); + parent_def_scope = event->context->scope; + declaration_unref(event->context_decl); + } + if (event->fields_decl) { + event->fields = + event->fields_decl->definition_new(event->fields_decl, + parent_def_scope, + g_quark_from_string("event.fields"), + MAX_INT); + parent_def_scope = event->fields->scope; + declaration_unref(event->fields_decl); + } return 0; error: - declaration_unref(event->fields); - declaration_unref(event->context); + declaration_unref(event->fields_decl); + declaration_unref(event->context_decl); free_definition_scope(event->definition_scope); free_declaration_scope(event->declaration_scope); g_free(event); @@ -510,7 +528,7 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str return -EINVAL; } CTF_EVENT_SET_FIELD(event, stream_id); - } else if (!strcmp(left, "event_header")) { + } else if (!strcmp(left, "event.header")) { struct declaration *declaration; declaration = ctf_declaration_specifier_visit(fd, depth, @@ -520,9 +538,8 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) return -EPERM; - /* TODO: definition */ - stream->event_header = container_of(declaration, struct declaration_struct, p); - } else if (!strcmp(left, "event_context")) { + stream->event_header_decl = container_of(declaration, struct declaration_struct, p); + } else if (!strcmp(left, "event.context")) { struct declaration *declaration; declaration = ctf_declaration_specifier_visit(fd, depth, @@ -532,9 +549,8 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) return -EPERM; - /* TODO: definition */ - stream->event_context = container_of(declaration, struct declaration_struct, p); - } else if (!strcmp(left, "packet_context")) { + stream->event_context_decl = container_of(declaration, struct declaration_struct, p); + } else if (!strcmp(left, "packet.context")) { struct declaration *declaration; declaration = ctf_declaration_specifier_visit(fd, depth, @@ -544,8 +560,7 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) return -EPERM; - /* TODO: definition */ - stream->packet_context = container_of(declaration, struct declaration_struct, p); + stream->packet_context_decl = container_of(declaration, struct declaration_struct, p); } free(left); break; @@ -565,10 +580,11 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, int ret = 0; struct ctf_node *iter; struct ctf_stream *stream; + struct definition_scope *parent_def_scope; stream = g_new0(struct ctf_stream, 1); stream->declaration_scope = new_declaration_scope(parent_declaration_scope); - stream->definition_scope = new_definition_scope(trace->definition_scope); + stream->definition_scope = new_dynamic_definition_scope(trace->definition_scope); stream->events_by_id = g_ptr_array_new(); stream->event_quark_to_id = g_hash_table_new(g_int_hash, g_int_equal); cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) { @@ -583,6 +599,36 @@ 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; + + parent_def_scope = stream->definition_scope; + if (stream->packet_context_decl) { + stream->packet_context = + stream->packet_context_decl->definition_new(stream->packet_context_decl, + parent_def_scope, + g_quark_from_string("stream.packet.context"), + MAX_INT); + parent_def_scope = stream->packet_context->scope; + declaration_unref(stream->packet_context_decl); + } + if (stream->event_header_decl) { + stream->event_header = + stream->event_header_decl->definition_new(stream->event_header_decl, + parent_def_scope, + g_quark_from_string("stream.event.header"), + MAX_INT); + parent_def_scope = stream->event_header->scope; + declaration_unref(stream->event_header_decl); + } + if (stream->event_context_decl) { + stream->event_context = + stream->event_context_decl->definition_new(stream->event_context_decl, + parent_def_scope, + g_quark_from_string("stream.event.context"), + MAX_INT); + parent_def_scope = stream->event_context->scope; + declaration_unref(stream->event_context_decl); + } + return 0; error: @@ -681,7 +727,7 @@ int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace if (trace->declaration_scope) return -EEXIST; trace->declaration_scope = new_declaration_scope(trace->root_declaration_scope); - trace->definition_scope = new_definition_scope(trace->root_definition_scope); + trace->definition_scope = new_dynamic_definition_scope(trace->root_definition_scope); trace->streams = g_ptr_array_new(); cds_list_for_each_entry(iter, &node->u.trace.declaration_list, siblings) { ret = ctf_trace_declaration_visit(fd, depth + 1, iter, trace); diff --git a/include/babeltrace/ctf/metadata.h b/include/babeltrace/ctf/metadata.h index 85ff1cb8..a60f1776 100644 --- a/include/babeltrace/ctf/metadata.h +++ b/include/babeltrace/ctf/metadata.h @@ -91,9 +91,15 @@ struct ctf_stream { GPtrArray *events_by_id; /* Array of struct ctf_event pointers indexed by id */ GHashTable *event_quark_to_id; /* GQuark to numeric id */ + /* Declarations only used when parsing */ + struct declaration_struct *packet_context_decl; + struct declaration_struct *event_header_decl; + struct declaration_struct *event_context_decl; + + /* Definitions used afterward */ + struct definition_struct *packet_context; struct definition_struct *event_header; struct definition_struct *event_context; - struct definition_struct *packet_context; uint64_t stream_id; @@ -123,6 +129,12 @@ struct ctf_event { struct declaration_scope *declaration_scope; /* parent is stream scope */ struct definition_scope *definition_scope; + + /* Declarations only used when parsing */ + struct declaration_struct *context_decl; + struct declaration_struct *fields_decl; + + /* Definitions used afterward */ struct definition_struct *context; struct definition_struct *fields; diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 885a6a1b..34e49aef 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -107,8 +107,11 @@ struct definition_scope { struct definition_scope *parent_scope; /* * Complete "path" leading to this definition scope. - * Includes trace/stream/event '.' field name '.' field name '.' .... + * Includes dynamic scope name '.' field name '.' field name '.' .... * Array of GQuark elements (which are each separated by dots). + * The dynamic scope name can contain dots, and is encoded into + * a single GQuark. Thus, scope_path[0] returns the GQuark + * identifying the dynamic scope. */ GArray *scope_path; /* array of GQuark */ }; @@ -377,6 +380,9 @@ int register_field_definition(GQuark field_name, struct definition_scope * new_definition_scope(struct definition_scope *parent_scope, GQuark field_name); +struct definition_scope * + new_dynamic_definition_scope(struct definition_scope *parent_scope, + GQuark field_name); void free_definition_scope(struct definition_scope *scope); void declaration_ref(struct declaration *declaration); diff --git a/types/types.c b/types/types.c index 208b303f..227a1e5e 100644 --- a/types/types.c +++ b/types/types.c @@ -147,12 +147,17 @@ static struct definition_scope * /* * OK, here is the fun. We want to lookup a field that is: - * - either in the current scope, but prior to the current field. - * - or in a parent scope (or parent of parent ...) still in a field - * prior to the current field position within the parents. - * A reaching through a dynamic scoping (e.g. from payload structure to - * event header structure), the parent fields are always entirely prior - * to the child. + * - either in the same dynamic scope: + * - either in the current scope, but prior to the current field. + * - or in a parent scope (or parent of parent ...) still in a field + * prior to the current field position within the parents. + * - or in a different dynamic scope: + * - either in a upper dynamic scope (walk down a targeted scope from + * the dynamic scope root) + * - or in a lower dynamic scope (failure) + * The dynamic scope roots are linked together, so we can access the + * parent dynamic scope from the child dynamic scope by walking up to + * the parent. * If we cannot find such a field that is prior to our current path, we * return NULL. * @@ -406,30 +411,54 @@ int register_enum_declaration(GQuark enum_name, return 0; } -struct definition_scope * - new_definition_scope(struct definition_scope *parent_scope, - GQuark field_name) +static struct definition_scope * + _new_definition_scope(struct definition_scope *parent_scope, + int scope_path_len) { struct definition_scope *scope = g_new(struct definition_scope, 1); - int scope_path_len = 1; scope->definitions = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) definition_unref); scope->parent_scope = parent_scope; - if (scope->parent_scope) - scope_path_len += scope->parent_scope->scope_path->len; scope->scope_path = g_array_sized_new(FALSE, TRUE, sizeof(GQuark), scope_path_len); g_array_set_size(scope->scope_path, scope_path_len); - if (scope->parent_scope) - memcpy(scope->scope_path, scope->parent_scope->scope_path, + return scope; +} + +struct definition_scope * + new_definition_scope(struct definition_scope *parent_scope, + GQuark field_name) +{ + struct definition_scope *scope; + int scope_path_len = 1; + + if (parent_scope) + scope_path_len += parent_scope->scope_path->len; + scope = _new_definition_scope(parent_scope, scope_path_len); + if (parent_scope) + memcpy(scope->scope_path, parent_scope->scope_path, sizeof(GQuark) * (scope_path_len - 1)); g_array_index(scope->scope_path, GQuark, scope_path_len - 1) = field_name; return scope; } +/* + * Same as new_definition_scope, but reset the scope path. + */ +struct definition_scope * + new_dynamic_definition_scope(struct definition_scope *parent_scope, + GQuark field_name) +{ + struct definition_scope *scope; + + scope = _new_definition_scope(parent_scope, 1); + g_array_index(scope->scope_path, GQuark, 0) = field_name; + return scope; +} + void free_definition_scope(struct definition_scope *scope) { g_array_free(scope->scope_path, TRUE); -- 2.34.1 From 41253107837c6698a01af3133d11762302d8f9e5 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 15 Apr 2011 20:24:21 -0400 Subject: [PATCH 02/16] Definition scope: update Signed-off-by: Mathieu Desnoyers --- .../metadata/ctf-visitor-generate-io-struct.c | 114 +++++++++++++----- include/babeltrace/ctf/metadata.h | 7 +- include/babeltrace/types.h | 5 +- types/types.c | 15 +-- 4 files changed, 88 insertions(+), 53 deletions(-) diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 260fc31c..f54a276a 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "ctf-scanner.h" #include "ctf-parser.h" #include "ctf-ast.h" @@ -178,24 +179,76 @@ int ctf_visitor_print_type_declarator(FILE *fd, int depth, struct ctf_node *node } /* - * String returned must be freed by the caller. + * String returned must be freed by the caller using g_free. */ static char *concatenate_unary_strings(struct list_head *head) { - + struct ctf_node *node; + GString *str; + int i = 0; + + str = g_string_new(); + 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)) + switch (node->u.unary_expression.link) { + case UNARY_DOTLINK: + g_string_append(str, ".") + break; + case UNARY_ARROWLINK: + g_string_append(str, "->") + break; + case UNARY_DOTDOTDOT: + g_string_append(str, "...") + break; + } + src_string = u.unary_expression.u.string; + g_string_append(str, src_string); + i++; + } + return g_string_free(str, FALSE); } static int get_unary_unsigned(struct list_head *head, uint64_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.unsigned_constant + i++; + } + return 0; } static int get_unary_uuid(struct list_head *head, uuid_t *uuid) { - + struct ctf_node *node; + int i = 0; + int ret = -1; + + cds_list_for_each_entry(node, head, siblings) { + const 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); + assert(i == 0); + src_string = u.unary_expression.u.string; + ret = uuid_parse(u.unary_expression.u.string, *uuid); + } + return ret; } static @@ -360,7 +413,7 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return -EINVAL; } event->name = g_quark_from_string(right); - free(right); + g_free(right); CTF_EVENT_SET_FIELD(event, name); } else if (!strcmp(left, "id")) { if (CTF_EVENT_FIELD_IS_SET(event, id)) @@ -384,11 +437,6 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru fprintf(stderr, "[error] %s: stream id %" PRIu64 " cannot be found\n", __func__, event->stream_id); return -EINVAL; } - event->definition_scope = new_dynamic_definition_scope(stream->definition_scope); - if (!event->definition_scope) { - fprintf(stderr, "[error] %s: Error allocating declaration scope\n", __func__); - return -EPERM; - } CTF_EVENT_SET_FIELD(event, stream_id); } else if (!strcmp(left, "context")) { struct declaration *declaration; @@ -417,7 +465,7 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return -EPERM; event->fields_decl = container_of(declaration, struct declaration_struct, p); } - free(left); + g_free(left); break; } default: @@ -462,22 +510,22 @@ 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->definition_scope; + parent_def_scope = stream->definition_scope; if (event->context_decl) { event->context = event->context_decl->definition_new(event->context_decl, - parent_def_scope, - g_quark_from_string("event.context"), - MAX_INT); + parent_def_scope, 0, 0); + set_dynamic_definition_scope(event->context->scope, + g_quark_from_string("event.context")); parent_def_scope = event->context->scope; declaration_unref(event->context_decl); } if (event->fields_decl) { event->fields = event->fields_decl->definition_new(event->fields_decl, - parent_def_scope, - g_quark_from_string("event.fields"), - MAX_INT); + parent_def_scope, 0, 0); + set_dynamic_definition_scope(event->fields->scope, + g_quark_from_string("event.fields")); parent_def_scope = event->fields->scope; declaration_unref(event->fields_decl); } @@ -562,7 +610,7 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str return -EPERM; stream->packet_context_decl = container_of(declaration, struct declaration_struct, p); } - free(left); + g_free(left); break; } default: @@ -584,7 +632,6 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, stream = g_new0(struct ctf_stream, 1); stream->declaration_scope = new_declaration_scope(parent_declaration_scope); - stream->definition_scope = new_dynamic_definition_scope(trace->definition_scope); stream->events_by_id = g_ptr_array_new(); stream->event_quark_to_id = g_hash_table_new(g_int_hash, g_int_equal); cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) { @@ -600,34 +647,35 @@ 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 = stream->definition_scope; + parent_def_scope = NULL; if (stream->packet_context_decl) { stream->packet_context = stream->packet_context_decl->definition_new(stream->packet_context_decl, - parent_def_scope, - g_quark_from_string("stream.packet.context"), - MAX_INT); + parent_def_scope, 0, 0); + set_dynamic_definition_scope(stream->packet_context->scope, + g_quark_from_string("stream.packet.context")); parent_def_scope = stream->packet_context->scope; declaration_unref(stream->packet_context_decl); } if (stream->event_header_decl) { stream->event_header = stream->event_header_decl->definition_new(stream->event_header_decl, - parent_def_scope, - g_quark_from_string("stream.event.header"), - MAX_INT); + parent_def_scope, 0, 0); + set_dynamic_definition_scope(stream->event_header->scope, + g_quark_from_string("stream.event.header")); parent_def_scope = stream->event_header->scope; declaration_unref(stream->event_header_decl); } if (stream->event_context_decl) { stream->event_context = stream->event_context_decl->definition_new(stream->event_context_decl, - parent_def_scope, - g_quark_from_string("stream.event.context"), - MAX_INT); + parent_def_scope, 0, 0); + set_dynamic_definition_scope(stream->event_context_scope, + g_quark_from_string("stream.event.context")); parent_def_scope = stream->event_context->scope; declaration_unref(stream->event_context_decl); } + stream->definition_scope = parent_def_scope; return 0; @@ -706,7 +754,7 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru } CTF_EVENT_SET_FIELD(trace, uuid); } - free(left); + g_free(left); break; } default: @@ -796,13 +844,13 @@ int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *t } cds_list_for_each_entry(iter, &node->u.root.stream, siblings) { ret = ctf_stream_visit(fd, depth + 1, iter, - trace->declaration_scope, trace); + trace->root_declaration_scope, trace); if (ret) return ret; } cds_list_for_each_entry(iter, &node->u.root.event, siblings) { ret = ctf_event_visit(fd, depth + 1, iter, - trace->declaration_scope, trace); + trace->root_declaration_scope, trace); if (ret) return ret; } diff --git a/include/babeltrace/ctf/metadata.h b/include/babeltrace/ctf/metadata.h index a60f1776..d98a2630 100644 --- a/include/babeltrace/ctf/metadata.h +++ b/include/babeltrace/ctf/metadata.h @@ -47,11 +47,8 @@ struct ctf_event; struct ctf_trace { /* root scope */ struct declaration_scope *root_declaration_scope; - /* root scope */ - struct definition_scope *root_definition_scope; struct declaration_scope *declaration_scope; - struct definition_scope *definition_scope; GPtrArray *streams; /* Array of struct ctf_stream pointers*/ uint64_t major; @@ -86,7 +83,7 @@ struct ctf_stream { struct ctf_trace *trace; /* parent is lexical scope conaining the stream scope */ struct declaration_scope *declaration_scope; - /* parent is trace scope */ + /* innermost definition scope. to be used as parent of event. */ struct definition_scope *definition_scope; GPtrArray *events_by_id; /* Array of struct ctf_event pointers indexed by id */ GHashTable *event_quark_to_id; /* GQuark to numeric id */ @@ -127,8 +124,6 @@ struct ctf_event { struct ctf_stream *stream; /* parent is lexical scope conaining the event scope */ struct declaration_scope *declaration_scope; - /* parent is stream scope */ - struct definition_scope *definition_scope; /* Declarations only used when parsing */ struct declaration_struct *context_decl; diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 34e49aef..44c9e5b2 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -380,9 +380,8 @@ int register_field_definition(GQuark field_name, struct definition_scope * new_definition_scope(struct definition_scope *parent_scope, GQuark field_name); -struct definition_scope * - new_dynamic_definition_scope(struct definition_scope *parent_scope, - GQuark field_name); +void set_dynamic_definition_scope(struct definition_scope *scope, + GQuark root_name); void free_definition_scope(struct definition_scope *scope); void declaration_ref(struct declaration *declaration); diff --git a/types/types.c b/types/types.c index 227a1e5e..1f93da4e 100644 --- a/types/types.c +++ b/types/types.c @@ -445,18 +445,11 @@ struct definition_scope * return scope; } -/* - * Same as new_definition_scope, but reset the scope path. - */ -struct definition_scope * - new_dynamic_definition_scope(struct definition_scope *parent_scope, - GQuark field_name) +void set_dynamic_definition_scope(struct definition_scope *scope, + GQuark root_name) { - struct definition_scope *scope; - - scope = _new_definition_scope(parent_scope, 1); - g_array_index(scope->scope_path, GQuark, 0) = field_name; - return scope; + g_array_set_size(scope->scope_path, 1); + g_array_index(scope->scope_path, GQuark, 0) = root_name; } void free_definition_scope(struct definition_scope *scope) -- 2.34.1 From 6a36ddcab611cb253bc589c61a2ef87a6d033867 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 15 Apr 2011 20:36:51 -0400 Subject: [PATCH 03/16] Dynamic scope: child position is MAX_INT Ensure that lookup knows the parent fields are prior to the child location. Signed-off-by: Mathieu Desnoyers --- .../ctf/metadata/ctf-visitor-generate-io-struct.c | 15 ++++++++++----- include/babeltrace/types.h | 3 ++- types/types.c | 9 ++++++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index f54a276a..2c01a9a2 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -515,7 +515,8 @@ int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node, event->context = event->context_decl->definition_new(event->context_decl, parent_def_scope, 0, 0); - set_dynamic_definition_scope(event->context->scope, + set_dynamic_definition_scope(&event->context->p, + event->context->scope, g_quark_from_string("event.context")); parent_def_scope = event->context->scope; declaration_unref(event->context_decl); @@ -524,7 +525,8 @@ int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node, event->fields = event->fields_decl->definition_new(event->fields_decl, parent_def_scope, 0, 0); - set_dynamic_definition_scope(event->fields->scope, + set_dynamic_definition_scope(&event->fields->p, + event->fields->scope, g_quark_from_string("event.fields")); parent_def_scope = event->fields->scope; declaration_unref(event->fields_decl); @@ -652,7 +654,8 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, stream->packet_context = stream->packet_context_decl->definition_new(stream->packet_context_decl, parent_def_scope, 0, 0); - set_dynamic_definition_scope(stream->packet_context->scope, + set_dynamic_definition_scope(&stream->packet_context->p, + stream->packet_context->scope, g_quark_from_string("stream.packet.context")); parent_def_scope = stream->packet_context->scope; declaration_unref(stream->packet_context_decl); @@ -661,7 +664,8 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, stream->event_header = stream->event_header_decl->definition_new(stream->event_header_decl, parent_def_scope, 0, 0); - set_dynamic_definition_scope(stream->event_header->scope, + set_dynamic_definition_scope(&stream->event_header->p, + stream->event_header->scope, g_quark_from_string("stream.event.header")); parent_def_scope = stream->event_header->scope; declaration_unref(stream->event_header_decl); @@ -670,7 +674,8 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, stream->event_context = stream->event_context_decl->definition_new(stream->event_context_decl, parent_def_scope, 0, 0); - set_dynamic_definition_scope(stream->event_context_scope, + set_dynamic_definition_scope(&stream->event_context->p, + stream->event_context->scope, g_quark_from_string("stream.event.context")); parent_def_scope = stream->event_context->scope; declaration_unref(stream->event_context_decl); diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 44c9e5b2..21dd66f2 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -380,7 +380,8 @@ int register_field_definition(GQuark field_name, struct definition_scope * new_definition_scope(struct definition_scope *parent_scope, GQuark field_name); -void set_dynamic_definition_scope(struct definition_scope *scope, +void set_dynamic_definition_scope(struct definition *definition, + struct definition_scope *scope, GQuark root_name); void free_definition_scope(struct definition_scope *scope); diff --git a/types/types.c b/types/types.c index 1f93da4e..fe1538f0 100644 --- a/types/types.c +++ b/types/types.c @@ -19,6 +19,7 @@ */ #include +#include #include #include @@ -445,11 +446,17 @@ struct definition_scope * return scope; } -void set_dynamic_definition_scope(struct definition_scope *scope, +void set_dynamic_definition_scope(struct definition *definition, + struct definition_scope *scope, GQuark root_name) { g_array_set_size(scope->scope_path, 1); g_array_index(scope->scope_path, GQuark, 0) = root_name; + /* + * Use INT_MAX order to ensure that all fields of the parent + * scope are seen as being prior to this scope. + */ + definition->index = INT_MAX; } void free_definition_scope(struct definition_scope *scope) -- 2.34.1 From d00d17d1e06065eb31a699ce59e16ceb6b858029 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 18 Apr 2011 15:35:53 -0400 Subject: [PATCH 04/16] Scope path: split dynamic scope path Keep the lookup code regular. Signed-off-by: Mathieu Desnoyers --- .../metadata/ctf-visitor-generate-io-struct.c | 10 ++--- include/babeltrace/types.h | 2 +- types/types.c | 40 +++++++++++++++++-- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 2c01a9a2..499db793 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -517,7 +517,7 @@ int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node, parent_def_scope, 0, 0); set_dynamic_definition_scope(&event->context->p, event->context->scope, - g_quark_from_string("event.context")); + "event.context"); parent_def_scope = event->context->scope; declaration_unref(event->context_decl); } @@ -527,7 +527,7 @@ int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node, parent_def_scope, 0, 0); set_dynamic_definition_scope(&event->fields->p, event->fields->scope, - g_quark_from_string("event.fields")); + "event.fields"); parent_def_scope = event->fields->scope; declaration_unref(event->fields_decl); } @@ -656,7 +656,7 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, parent_def_scope, 0, 0); set_dynamic_definition_scope(&stream->packet_context->p, stream->packet_context->scope, - g_quark_from_string("stream.packet.context")); + "stream.packet.context"); parent_def_scope = stream->packet_context->scope; declaration_unref(stream->packet_context_decl); } @@ -666,7 +666,7 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, parent_def_scope, 0, 0); set_dynamic_definition_scope(&stream->event_header->p, stream->event_header->scope, - g_quark_from_string("stream.event.header")); + "stream.event.header"); parent_def_scope = stream->event_header->scope; declaration_unref(stream->event_header_decl); } @@ -676,7 +676,7 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, parent_def_scope, 0, 0); set_dynamic_definition_scope(&stream->event_context->p, stream->event_context->scope, - g_quark_from_string("stream.event.context")); + "stream.event.context"); parent_def_scope = stream->event_context->scope; declaration_unref(stream->event_context_decl); } diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 21dd66f2..6fde4d18 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -382,7 +382,7 @@ struct definition_scope * GQuark field_name); void set_dynamic_definition_scope(struct definition *definition, struct definition_scope *scope, - GQuark root_name); + const char *root_name); void free_definition_scope(struct definition_scope *scope); void declaration_ref(struct declaration *declaration); diff --git a/types/types.c b/types/types.c index fe1538f0..e57624fb 100644 --- a/types/types.c +++ b/types/types.c @@ -446,12 +446,46 @@ struct definition_scope * return scope; } +/* + * in: path, out: q (GArray of GQuark) + */ +static +void append_scope_path(const char *path, GArray *q) +{ + const char *ptrbegin, *ptrend = path; + GQuark quark; + + for (;;) { + char *str; + size_t len; + + ptrbegin = ptrend; + ptrend = strchr(ptrbegin, '.'); + if (!ptrend) + break; + len = ptrend - ptrbegin; + /* Don't accept two consecutive dots */ + assert(len != 0); + str = g_new(char, len + 1); /* include \0 */ + memcpy(str, ptrbegin, len); + str[len] = '\0'; + quark = g_quark_from_string(str); + g_array_append_val(q, quark); + g_free(str); + } + /* last. Check for trailing dot (and discard). */ + if (ptrbegin[0] != '\0') { + quark = g_quark_from_string(ptrbegin); + g_array_append_val(q, quark); + } +} + void set_dynamic_definition_scope(struct definition *definition, struct definition_scope *scope, - GQuark root_name) + const char *root_name) { - g_array_set_size(scope->scope_path, 1); - g_array_index(scope->scope_path, GQuark, 0) = root_name; + g_array_set_size(scope->scope_path, 0); + append_scope_path(root_name, scope->scope_path); /* * Use INT_MAX order to ensure that all fields of the parent * scope are seen as being prior to this scope. -- 2.34.1 From d60cb676b003e5eb83566f9a2707b4dfea005020 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 18 Apr 2011 16:49:59 -0400 Subject: [PATCH 05/16] Create "untagged" variant structure Signed-off-by: Mathieu Desnoyers --- .../metadata/ctf-visitor-generate-io-struct.c | 4 +- include/babeltrace/types.h | 30 ++- types/types.c | 3 +- types/variant.c | 210 +++++++++++------- 4 files changed, 153 insertions(+), 94 deletions(-) diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 499db793..1a3fe585 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -824,7 +824,7 @@ int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *t ret = ctf_typedef_visit(fd, depth + 1, &iter->u._typedef.declaration_specifier, &iter->u._typedef.type_declarators, - trace->declaration_scope); + trace->root_declaration_scope); if (ret) return ret; } @@ -832,7 +832,7 @@ int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *t siblings) { ret = ctf_typealias_visit(fd, depth + 1, &iter->u.typealias.target, &iter->u.typealias.alias - trace->declaration_scope); + trace->root_declaration_scope); if (ret) return ret; } diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 6fde4d18..c8e31337 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -123,6 +123,7 @@ enum ctf_type_id { CTF_TYPE_ENUM, CTF_TYPE_STRING, CTF_TYPE_STRUCT, + CTF_TYPE_UNTAGGED_VARIANT, CTF_TYPE_VARIANT, CTF_TYPE_ARRAY, CTF_TYPE_SEQUENCE, @@ -285,15 +286,20 @@ struct definition_struct { GArray *fields; /* Array of struct field */ }; -struct declaration_variant { +struct declaration_untagged_variant { struct declaration p; GHashTable *fields_by_tag; /* Tuples (field tag, field index) */ struct declaration_scope *scope; GArray *fields; /* Array of declaration_field */ - GQuark tag_name; /* TODO */ - /* Tag name must be nonzero and must exist when defining the variant */ }; +struct declaration_variant { + struct declaration p; + struct declaration_untagged_variant *untagged_variant; + GArray *tag_name; /* Array of GQuark */ +}; + +/* A variant needs to be tagged to be defined. */ struct definition_variant { struct definition p; struct declaration_variant *declaration; @@ -468,13 +474,16 @@ struct_get_field_from_index(struct definition_struct *struct_definition, * from numeric values to a single tag. Overlapping tag value ranges are * therefore forbidden. */ -struct declaration_variant *variant_declaration_new(const char *name, +struct declaration_untagged_variant *untagged_variant_declaration_new(const char *name, struct declaration_scope *parent_scope); -void variant_declaration_add_field(struct declaration_variant *variant_declaration, - const char *tag_name, - struct declaration *tag_declaration); +struct declaration_variant *variant_declaration_new(struct declaration_untagged_variant *untagged_variant, + const char *tag); + +void untagged_variant_declaration_add_field(struct declaration_untagged_variant *untagged_variant_declaration, + const char *field_name, + struct declaration *field_declaration); struct declaration_field * - variant_declaration_get_field_from_tag(struct declaration_variant *variant_declaration, + untagged_variant_declaration_get_field_from_tag(struct declaration_untagged_variant *untagged_variant_declaration, GQuark tag); /* * Returns 0 on success, -EPERM on error. @@ -508,4 +517,9 @@ struct declaration_sequence * struct declaration *elem_declaration, struct declaration_scope *parent_scope); +/* + * in: path (dot separated), out: q (GArray of GQuark) + */ +void append_scope_path(const char *path, GArray *q); + #endif /* _BABELTRACE_declarationS_H */ diff --git a/types/types.c b/types/types.c index e57624fb..a8ead299 100644 --- a/types/types.c +++ b/types/types.c @@ -447,9 +447,8 @@ struct definition_scope * } /* - * in: path, out: q (GArray of GQuark) + * in: path (dot separated), out: q (GArray of GQuark) */ -static void append_scope_path(const char *path, GArray *q) { const char *ptrbegin, *ptrend = path; diff --git a/types/variant.c b/types/variant.c index 4a8abcb1..2ab14a21 100644 --- a/types/variant.c +++ b/types/variant.c @@ -49,42 +49,73 @@ void variant_copy(struct stream_pos *dest, const struct format *fdest, } static -void _variant_declaration_free(struct declaration *declaration) +void _untagged_variant_declaration_free(struct declaration *declaration) { - struct declaration_variant *variant_declaration = - container_of(declaration, struct declaration_variant, p); + struct declaration_untagged_variant *untagged_variant_declaration = + container_of(declaration, struct declaration_untagged_variant, p); unsigned long i; - free_declaration_scope(variant_declaration->scope); - g_hash_table_destroy(variant_declaration->fields_by_tag); + free_declaration_scope(untagged_variant_declaration->scope); + g_hash_table_destroy(untagged_variant_declaration->fields_by_tag); - for (i = 0; i < variant_declaration->fields->len; i++) { + for (i = 0; i < untagged_variant_declaration->fields->len; i++) { struct declaration_field *declaration_field = - &g_array_index(variant_declaration->fields, + &g_array_index(untagged_variant_declaration->fields, struct declaration_field, i); declaration_unref(declaration_field->declaration); } - g_array_free(variant_declaration->fields, true); - g_free(variant_declaration); + g_array_free(untagged_variant_declaration->fields, true); + g_free(untagged_variant_declaration); } -struct declaration_variant *variant_declaration_new(const char *name, +struct declaration_untagged_variant *untagged_variant_declaration_new(const char *name, struct declaration_scope *parent_scope) { - struct declaration_variant *variant_declaration; + struct declaration_untagged_variant *untagged_variant_declaration; struct declaration *declaration; - variant_declaration = g_new(struct declaration_variant, 1); - declaration = &variant_declaration->p; - variant_declaration->fields_by_tag = g_hash_table_new(g_direct_hash, + untagged_variant_declaration = g_new(struct declaration_untagged_variant, 1); + declaration = &untagged_variant_declaration->p; + untagged_variant_declaration->fields_by_tag = g_hash_table_new(g_direct_hash, g_direct_equal); - variant_declaration->fields = g_array_sized_new(FALSE, TRUE, + untagged_variant_declaration->fields = g_array_sized_new(FALSE, TRUE, sizeof(struct declaration_field), DEFAULT_NR_STRUCT_FIELDS); - variant_declaration->scope = new_declaration_scope(parent_scope); - declaration->id = CTF_TYPE_VARIANT; + untagged_variant_declaration->scope = new_declaration_scope(parent_scope); + declaration->id = CTF_TYPE_UNTAGGED_VARIANT; declaration->name = g_quark_from_string(name); declaration->alignment = 1; + declaration->copy = NULL; + declaration->declaration_free = _untagged_variant_declaration_free; + declaration->definition_new = NULL; + declaration->definition_free = NULL; + declaration->ref = 1; + return untagged_variant_declaration; +} + +static +void _variant_declaration_free(struct declaration *declaration) +{ + struct declaration_variant *variant_declaration = + container_of(declaration, struct declaration_variant, p); + + _untagged_variant_declaration_free(&variant_declaration->untagged_variant->p); + g_array_free(variant_declaration->tag_name, TRUE); +} + +struct declaration_variant * + variant_declaration_new(struct declaration_untagged_variant *untagged_variant, const char *tag) +{ + struct declaration_variant *variant_declaration; + struct declaration *declaration; + + variant_declaration = g_new(struct declaration_variant, 1); + declaration = &variant_declaration->p; + variant_declaration->untagged_variant = untagged_variant; + variant_declaration->tag_name = g_array_new(FALSE, TRUE, sizeof(GQuark)); + append_scope_path(tag, variant_declaration->tag_name); + declaration->id = CTF_TYPE_VARIANT; + declaration->alignment = 1; declaration->copy = variant_copy; declaration->declaration_free = _variant_declaration_free; declaration->definition_new = _variant_definition_new; @@ -93,6 +124,53 @@ struct declaration_variant *variant_declaration_new(const char *name, return variant_declaration; } +/* + * tag_instance is assumed to be an enumeration. + * Returns 0 if OK, < 0 if error. + */ +static +int check_enum_tag(struct definition_variant *variant, + struct definition *enum_tag) +{ + struct definition_enum *_enum = + container_of(enum_tag, struct definition_enum, p); + struct declaration_enum *enum_declaration = _enum->declaration; + int missing_field = 0; + unsigned long i; + + /* + * Strictly speaking, each enumerator must map to a field of the + * variant. However, we are even stricter here by requiring that each + * variant choice map to an enumerator too. We then validate that the + * number of enumerators equals the number of variant choices. + */ + if (variant->declaration->untagged_variant->fields->len != enum_get_nr_enumerators(enum_declaration)) + return -EPERM; + + for (i = 0; i < variant->declaration->untagged_variant->fields->len; i++) { + struct declaration_field *field_declaration = + &g_array_index(variant->declaration->untagged_variant->fields, + struct declaration_field, i); + if (!enum_quark_to_range_set(enum_declaration, field_declaration->name)) { + missing_field = 1; + break; + } + } + if (missing_field) + return -EPERM; + + /* + * Check the enumeration: it must map each value to one and only one + * enumerator tag. + * TODO: we should also check that each range map to one and only one + * tag. For the moment, we will simply check this dynamically in + * variant_declaration_get_current_field(). + */ + return 0; +} + + + static struct definition * _variant_definition_new(struct declaration *declaration, @@ -111,13 +189,21 @@ struct definition * variant->p.ref = 1; variant->p.index = index; variant->scope = new_definition_scope(parent_scope, field_name); + variant->enum_tag = lookup_definition(variant->scope->scope_path, + variant_declaration->tag_name, + parent_scope); + + if (!variant->enum_tag + || check_enum_tag(variant, variant->enum_tag) < 0) + goto error; + definition_ref(variant->enum_tag); variant->fields = g_array_sized_new(FALSE, TRUE, sizeof(struct field), - DEFAULT_NR_STRUCT_FIELDS); - g_array_set_size(variant->fields, variant_declaration->fields->len); - for (i = 0; i < variant_declaration->fields->len; i++) { + variant_declaration->untagged_variant->fields->len); + g_array_set_size(variant->fields, variant_declaration->untagged_variant->fields->len); + for (i = 0; i < variant_declaration->untagged_variant->fields->len; i++) { struct declaration_field *declaration_field = - &g_array_index(variant_declaration->fields, + &g_array_index(variant_declaration->untagged_variant->fields, struct declaration_field, i); struct field *field = &g_array_index(variant->fields, struct field, i); @@ -134,6 +220,11 @@ struct definition * } variant->current_field = NULL; return &variant->p; +error: + free_definition_scope(variant->scope); + declaration_unref(&variant_declaration->p); + g_free(variant); + return NULL; } static @@ -143,32 +234,33 @@ void _variant_definition_free(struct definition *definition) container_of(definition, struct definition_variant, p); unsigned long i; - assert(variant->fields->len == variant->declaration->fields->len); + assert(variant->fields->len == variant->declaration->untagged_variant->fields->len); for (i = 0; i < variant->fields->len; i++) { struct field *field = &g_array_index(variant->fields, struct field, i); definition_unref(field->definition); } + definition_unref(variant->enum_tag); free_definition_scope(variant->scope); declaration_unref(variant->p.declaration); g_free(variant); } -void variant_declaration_add_field(struct declaration_variant *variant_declaration, - const char *tag_name, - struct declaration *tag_declaration) +void untagged_variant_declaration_add_field(struct declaration_untagged_variant *untagged_variant_declaration, + const char *field_name, + struct declaration *field_declaration) { struct declaration_field *field; unsigned long index; - g_array_set_size(variant_declaration->fields, variant_declaration->fields->len + 1); - index = variant_declaration->fields->len - 1; /* last field (new) */ - field = &g_array_index(variant_declaration->fields, struct declaration_field, index); - field->name = g_quark_from_string(tag_name); - declaration_ref(tag_declaration); - field->declaration = tag_declaration; + g_array_set_size(untagged_variant_declaration->fields, untagged_variant_declaration->fields->len + 1); + index = untagged_variant_declaration->fields->len - 1; /* last field (new) */ + field = &g_array_index(untagged_variant_declaration->fields, struct declaration_field, index); + field->name = g_quark_from_string(field_name); + declaration_ref(field_declaration); + field->declaration = field_declaration; /* Keep index in hash rather than pointer, because array can relocate */ - g_hash_table_insert(variant_declaration->fields_by_tag, + g_hash_table_insert(untagged_variant_declaration->fields_by_tag, (gpointer) (unsigned long) field->name, (gpointer) index); /* @@ -179,59 +271,13 @@ void variant_declaration_add_field(struct declaration_variant *variant_declarati } struct declaration_field * -struct_declaration_get_field_from_tag(struct declaration_variant *variant_declaration, GQuark tag) +untagged_variant_declaration_get_field_from_tag(struct declaration_untagged_variant *untagged_variant_declaration, GQuark tag) { unsigned long index; - index = (unsigned long) g_hash_table_lookup(variant_declaration->fields_by_tag, + index = (unsigned long) g_hash_table_lookup(untagged_variant_declaration->fields_by_tag, (gconstpointer) (unsigned long) tag); - return &g_array_index(variant_declaration->fields, struct declaration_field, index); -} - -/* - * tag_instance is assumed to be an enumeration. - */ -int variant_definition_set_tag(struct definition_variant *variant, - struct definition *enum_tag) -{ - struct definition_enum *_enum = - container_of(variant->enum_tag, struct definition_enum, p); - struct declaration_enum *enum_declaration = _enum->declaration; - int missing_field = 0; - unsigned long i; - - /* - * Strictly speaking, each enumerator must map to a field of the - * variant. However, we are even stricter here by requiring that each - * variant choice map to an enumerator too. We then validate that the - * number of enumerators equals the number of variant choices. - */ - if (variant->declaration->fields->len != enum_get_nr_enumerators(enum_declaration)) - return -EPERM; - - for (i = 0; i < variant->declaration->fields->len; i++) { - struct declaration_field *field_declaration = - &g_array_index(variant->declaration->fields, - struct declaration_field, i); - if (!enum_quark_to_range_set(enum_declaration, field_declaration->name)) { - missing_field = 1; - break; - } - } - if (missing_field) - return -EPERM; - - /* - * Check the enumeration: it must map each value to one and only one - * enumerator tag. - * TODO: we should also check that each range map to one and only one - * tag. For the moment, we will simply check this dynamically in - * variant_declaration_get_current_field(). - */ - - /* Set the enum tag field */ - variant->enum_tag = enum_tag; - return 0; + return &g_array_index(untagged_variant_declaration->fields, struct declaration_field, index); } /* @@ -253,7 +299,7 @@ struct field *variant_get_current_field(struct definition_variant *variant) */ assert(tag_array->len == 1); tag = g_array_index(tag_array, GQuark, 0); - index = (unsigned long) g_hash_table_lookup(variant_declaration->fields_by_tag, + index = (unsigned long) g_hash_table_lookup(variant_declaration->untagged_variant->fields_by_tag, (gconstpointer) (unsigned long) tag); variant->current_field = &g_array_index(variant->fields, struct field, index); return variant->current_field; -- 2.34.1 From 1ee8e81dbe8f14831974e32cef7d5f116d17a73d Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 20 Apr 2011 22:01:24 -0400 Subject: [PATCH 06/16] Update typealias behavior Signed-off-by: Mathieu Desnoyers --- formats/ctf/metadata/ctf-ast.h | 2 + formats/ctf/metadata/ctf-parser.y | 85 ++++++++++--------- .../metadata/ctf-visitor-semantic-validator.c | 46 +++++++++- include/babeltrace/types.h | 1 + 4 files changed, 94 insertions(+), 40 deletions(-) diff --git a/formats/ctf/metadata/ctf-ast.h b/formats/ctf/metadata/ctf-ast.h index 8b5ad887..0ce21a5a 100644 --- a/formats/ctf/metadata/ctf-ast.h +++ b/formats/ctf/metadata/ctf-ast.h @@ -216,11 +216,13 @@ struct ctf_node { char *choice; /* list of typedef, typealias and declarations */ struct cds_list_head declaration_list; + int has_body; } variant; struct { char *name; /* list of typedef, typealias and declarations */ struct cds_list_head declaration_list; + int has_body; } _struct; } u; }; diff --git a/formats/ctf/metadata/ctf-parser.y b/formats/ctf/metadata/ctf-parser.y index 2ded0aef..f6c61859 100644 --- a/formats/ctf/metadata/ctf-parser.y +++ b/formats/ctf/metadata/ctf-parser.y @@ -811,6 +811,7 @@ void ctf_scanner_free(struct ctf_scanner *scanner) %type stream_declaration %type trace_declaration %type declaration_specifiers +%type alias_declaration_specifiers %type type_declarator_list %type abstract_type_declarator_list @@ -821,7 +822,6 @@ void ctf_scanner_free(struct ctf_scanner *scanner) %type enum_type_specifier %type struct_or_variant_declaration_list %type struct_or_variant_declaration -%type specifier_qualifier_list %type struct_or_variant_declarator_list %type struct_or_variant_declarator %type enumerator_list @@ -1116,7 +1116,7 @@ declaration: _cds_list_splice_tail(&($1)->tmp_head, &($$)->u._typedef.declaration_specifier); _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._typedef.type_declarators); } - | TYPEALIAS declaration_specifiers abstract_declarator_list COLON declaration_specifiers abstract_type_declarator_list SEMICOLON + | TYPEALIAS declaration_specifiers abstract_declarator_list COLON alias_declaration_specifiers abstract_type_declarator_list SEMICOLON { $$ = make_node(scanner, NODE_TYPEALIAS); $$->u.typealias.target = make_node(scanner, NODE_TYPEALIAS_TARGET); @@ -1126,15 +1126,6 @@ declaration: _cds_list_splice_tail(&($5)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.declaration_specifier); _cds_list_splice_tail(&($6)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.type_declarators); } - | TYPEALIAS declaration_specifiers abstract_declarator_list COLON type_declarator_list SEMICOLON - { - $$ = make_node(scanner, NODE_TYPEALIAS); - $$->u.typealias.target = make_node(scanner, NODE_TYPEALIAS_TARGET); - $$->u.typealias.alias = make_node(scanner, NODE_TYPEALIAS_ALIAS); - _cds_list_splice_tail(&($2)->tmp_head, &($$)->u.typealias.target->u.typealias_target.declaration_specifier); - _cds_list_splice_tail(&($3)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.declaration_specifier); - _cds_list_splice_tail(&($5)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.type_declarators); - } ; event_declaration: @@ -1361,12 +1352,14 @@ struct_type_specifier: struct_declaration_begin struct_or_variant_declaration_list struct_declaration_end { $$ = make_node(scanner, NODE_STRUCT); + $$->u._struct.has_body = 1; if (set_parent_node($2, $$)) reparent_error(scanner, "struct reparent error"); } | IDENTIFIER struct_declaration_begin struct_or_variant_declaration_list struct_declaration_end { $$ = make_node(scanner, NODE_STRUCT); + $$->u._struct.has_body = 1; $$->u._struct.name = $1->s; if (set_parent_node($3, $$)) reparent_error(scanner, "struct reparent error"); @@ -1374,6 +1367,7 @@ struct_type_specifier: | ID_TYPE struct_declaration_begin struct_or_variant_declaration_list struct_declaration_end { $$ = make_node(scanner, NODE_STRUCT); + $$->u._struct.has_body = 1; $$->u._struct.name = $1->s; if (set_parent_node($3, $$)) reparent_error(scanner, "struct reparent error"); @@ -1381,11 +1375,13 @@ struct_type_specifier: | IDENTIFIER { $$ = make_node(scanner, NODE_STRUCT); + $$->u._struct.has_body = 0; $$->u._struct.name = $1->s; } | ID_TYPE { $$ = make_node(scanner, NODE_STRUCT); + $$->u._struct.has_body = 0; $$->u._struct.name = $1->s; } ; @@ -1404,12 +1400,14 @@ variant_type_specifier: variant_declaration_begin struct_or_variant_declaration_list variant_declaration_end { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 1; if (set_parent_node($2, $$)) reparent_error(scanner, "variant reparent error"); } | LT IDENTIFIER GT variant_declaration_begin struct_or_variant_declaration_list variant_declaration_end { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 1; $$->u.variant.choice = $2->s; if (set_parent_node($5, $$)) reparent_error(scanner, "variant reparent error"); @@ -1417,6 +1415,7 @@ variant_type_specifier: | LT ID_TYPE GT variant_declaration_begin struct_or_variant_declaration_list variant_declaration_end { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 1; $$->u.variant.choice = $2->s; if (set_parent_node($5, $$)) reparent_error(scanner, "variant reparent error"); @@ -1424,6 +1423,7 @@ variant_type_specifier: | IDENTIFIER variant_declaration_begin struct_or_variant_declaration_list variant_declaration_end { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 1; $$->u.variant.name = $1->s; if (set_parent_node($3, $$)) reparent_error(scanner, "variant reparent error"); @@ -1431,6 +1431,7 @@ variant_type_specifier: | IDENTIFIER LT IDENTIFIER GT variant_declaration_begin struct_or_variant_declaration_list variant_declaration_end { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 1; $$->u.variant.name = $1->s; $$->u.variant.choice = $3->s; if (set_parent_node($6, $$)) @@ -1439,12 +1440,14 @@ variant_type_specifier: | IDENTIFIER LT IDENTIFIER GT { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 0; $$->u.variant.name = $1->s; $$->u.variant.choice = $3->s; } | IDENTIFIER LT ID_TYPE GT variant_declaration_begin struct_or_variant_declaration_list variant_declaration_end { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 1; $$->u.variant.name = $1->s; $$->u.variant.choice = $3->s; if (set_parent_node($6, $$)) @@ -1453,12 +1456,14 @@ variant_type_specifier: | IDENTIFIER LT ID_TYPE GT { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 0; $$->u.variant.name = $1->s; $$->u.variant.choice = $3->s; } | ID_TYPE variant_declaration_begin struct_or_variant_declaration_list variant_declaration_end { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 1; $$->u.variant.name = $1->s; if (set_parent_node($3, $$)) reparent_error(scanner, "variant reparent error"); @@ -1466,6 +1471,7 @@ variant_type_specifier: | ID_TYPE LT IDENTIFIER GT variant_declaration_begin struct_or_variant_declaration_list variant_declaration_end { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 1; $$->u.variant.name = $1->s; $$->u.variant.choice = $3->s; if (set_parent_node($6, $$)) @@ -1474,12 +1480,14 @@ variant_type_specifier: | ID_TYPE LT IDENTIFIER GT { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 0; $$->u.variant.name = $1->s; $$->u.variant.choice = $3->s; } | ID_TYPE LT ID_TYPE GT variant_declaration_begin struct_or_variant_declaration_list variant_declaration_end { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 1; $$->u.variant.name = $1->s; $$->u.variant.choice = $3->s; if (set_parent_node($6, $$)) @@ -1488,6 +1496,7 @@ variant_type_specifier: | ID_TYPE LT ID_TYPE GT { $$ = make_node(scanner, NODE_VARIANT); + $$->u.variant.has_body = 0; $$->u.variant.name = $1->s; $$->u.variant.choice = $3->s; } @@ -1644,32 +1653,32 @@ struct_or_variant_declaration_list: ; struct_or_variant_declaration: - specifier_qualifier_list struct_or_variant_declarator_list SEMICOLON + declaration_specifiers struct_or_variant_declarator_list SEMICOLON { $$ = make_node(scanner, NODE_STRUCT_OR_VARIANT_DECLARATION); _cds_list_splice_tail(&($1)->tmp_head, &($$)->u.struct_or_variant_declaration.declaration_specifier); _cds_list_splice_tail(&($2)->tmp_head, &($$)->u.struct_or_variant_declaration.type_declarators); } - | specifier_qualifier_list TYPEDEF specifier_qualifier_list type_declarator_list SEMICOLON + | declaration_specifiers TYPEDEF declaration_specifiers type_declarator_list SEMICOLON { $$ = make_node(scanner, NODE_TYPEDEF); _cds_list_splice_tail(&($1)->tmp_head, &($$)->u._typedef.declaration_specifier); _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._typedef.declaration_specifier); _cds_list_splice_tail(&($4)->tmp_head, &($$)->u._typedef.type_declarators); } - | TYPEDEF specifier_qualifier_list type_declarator_list SEMICOLON + | TYPEDEF declaration_specifiers type_declarator_list SEMICOLON { $$ = make_node(scanner, NODE_TYPEDEF); _cds_list_splice_tail(&($2)->tmp_head, &($$)->u._typedef.declaration_specifier); _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._typedef.type_declarators); } - | specifier_qualifier_list TYPEDEF type_declarator_list SEMICOLON + | declaration_specifiers TYPEDEF type_declarator_list SEMICOLON { $$ = make_node(scanner, NODE_TYPEDEF); _cds_list_splice_tail(&($1)->tmp_head, &($$)->u._typedef.declaration_specifier); _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._typedef.type_declarators); } - | TYPEALIAS specifier_qualifier_list abstract_declarator_list COLON specifier_qualifier_list abstract_type_declarator_list SEMICOLON + | TYPEALIAS declaration_specifiers abstract_declarator_list COLON alias_declaration_specifiers abstract_type_declarator_list SEMICOLON { $$ = make_node(scanner, NODE_TYPEALIAS); $$->u.typealias.target = make_node(scanner, NODE_TYPEALIAS_TARGET); @@ -1679,18 +1688,9 @@ struct_or_variant_declaration: _cds_list_splice_tail(&($5)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.declaration_specifier); _cds_list_splice_tail(&($6)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.type_declarators); } - | TYPEALIAS specifier_qualifier_list abstract_declarator_list COLON type_declarator_list SEMICOLON - { - $$ = make_node(scanner, NODE_TYPEALIAS); - $$->u.typealias.target = make_node(scanner, NODE_TYPEALIAS_TARGET); - $$->u.typealias.alias = make_node(scanner, NODE_TYPEALIAS_ALIAS); - _cds_list_splice_tail(&($2)->tmp_head, &($$)->u.typealias.target->u.typealias_target.declaration_specifier); - _cds_list_splice_tail(&($3)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.declaration_specifier); - _cds_list_splice_tail(&($5)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.type_declarators); - } ; -specifier_qualifier_list: +alias_declaration_specifiers: CONST { $$ = make_node(scanner, NODE_TYPE_SPECIFIER); @@ -1698,7 +1698,14 @@ specifier_qualifier_list: } | type_specifier { $$ = $1; } - | specifier_qualifier_list CONST + | IDENTIFIER + { + add_type(scanner, $1); + $$ = make_node(scanner, NODE_TYPE_SPECIFIER); + ($$)->u.type_specifier.type = TYPESPEC_ID_TYPE; + ($$)->u.type_specifier.id_type = yylval.gs->s; + } + | alias_declaration_specifiers CONST { struct ctf_node *node; @@ -1707,11 +1714,22 @@ specifier_qualifier_list: node->u.type_specifier.type = TYPESPEC_CONST; cds_list_add_tail(&node->siblings, &($$)->tmp_head); } - | specifier_qualifier_list type_specifier + | alias_declaration_specifiers type_specifier { $$ = $1; cds_list_add_tail(&($2)->siblings, &($$)->tmp_head); } + | alias_declaration_specifiers IDENTIFIER + { + struct ctf_node *node; + + add_type(scanner, $2); + $$ = $1; + node = make_node(scanner, NODE_TYPE_SPECIFIER); + node->u.type_specifier.type = TYPESPEC_ID_TYPE; + node->u.type_specifier.id_type = yylval.gs->s; + cds_list_add_tail(&node->siblings, &($$)->tmp_head); + } ; struct_or_variant_declarator_list: @@ -2052,7 +2070,7 @@ ctf_assignment_expression: _cds_list_splice_tail(&($1)->tmp_head, &($$)->u._typedef.declaration_specifier); _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._typedef.type_declarators); } - | TYPEALIAS declaration_specifiers abstract_declarator_list COLON declaration_specifiers abstract_type_declarator_list + | TYPEALIAS declaration_specifiers abstract_declarator_list COLON alias_declaration_specifiers abstract_type_declarator_list { $$ = make_node(scanner, NODE_TYPEALIAS); $$->u.typealias.target = make_node(scanner, NODE_TYPEALIAS_TARGET); @@ -2062,13 +2080,4 @@ ctf_assignment_expression: _cds_list_splice_tail(&($5)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.declaration_specifier); _cds_list_splice_tail(&($6)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.type_declarators); } - | TYPEALIAS declaration_specifiers abstract_declarator_list COLON type_declarator_list - { - $$ = make_node(scanner, NODE_TYPEALIAS); - $$->u.typealias.target = make_node(scanner, NODE_TYPEALIAS_TARGET); - $$->u.typealias.alias = make_node(scanner, NODE_TYPEALIAS_ALIAS); - _cds_list_splice_tail(&($2)->tmp_head, &($$)->u.typealias.target->u.typealias_target.declaration_specifier); - _cds_list_splice_tail(&($3)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.declaration_specifier); - _cds_list_splice_tail(&($5)->tmp_head, &($$)->u.typealias.alias->u.typealias_alias.type_declarators); - } ; diff --git a/formats/ctf/metadata/ctf-visitor-semantic-validator.c b/formats/ctf/metadata/ctf-visitor-semantic-validator.c index fae2b711..da77f596 100644 --- a/formats/ctf/metadata/ctf-visitor-semantic-validator.c +++ b/formats/ctf/metadata/ctf-visitor-semantic-validator.c @@ -232,10 +232,30 @@ int ctf_visitor_type_declarator(FILE *fd, int depth, struct ctf_node *node) */ if (!cds_list_empty(&node->u.type_declarator.pointers)) goto errperm; - /* Fall-through */ - case NODE_TYPEDEF: + break; /* OK */ case NODE_TYPEALIAS_TARGET: + break; /* OK */ case NODE_TYPEALIAS_ALIAS: + /* + * Only accept alias name containing: + * - identifier + * - identifier * (any number of pointers) + * NOT accepting alias names containing [] (would otherwise + * cause semantic clash for later declarations of + * arrays/sequences of elements, where elements could be + * arrays/sequences themselves (if allowed in typealias). + * NOT accepting alias with identifier. The declarator should + * be either empty or contain pointer(s). + */ + if (node->u.type_declarator.type == TYPEDEC_NESTED) + goto errperm; + if (cds_list_empty(&node->u.type_declarator.pointers)) + goto errperm; + if (node->u.type_declarator.type == TYPEDEC_ID && + node->u.type_declarator.u.id != NULL) + goto errperm; + break; /* OK */ + case NODE_TYPEDEF: case NODE_STRUCT_OR_VARIANT_DECLARATION: break; /* OK */ @@ -484,6 +504,9 @@ int _ctf_visitor_semantic_check(FILE *fd, int depth, struct ctf_node *node) depth--; break; case NODE_TYPEALIAS_TARGET: + { + int nr_declarators; + switch (node->parent->type) { case NODE_TYPEALIAS: break; /* OK */ @@ -497,14 +520,25 @@ int _ctf_visitor_semantic_check(FILE *fd, int depth, struct ctf_node *node) if (ret) return ret; } + nr_declarators = 0; cds_list_for_each_entry(iter, &node->u.typealias_target.type_declarators, siblings) { ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); if (ret) return ret; + nr_declarators++; + } + if (nr_declarators > 1) { + fprintf(fd, "[error] %s: Too many declarators in typealias alias (%d, max is 1)\n", __func__, nr_declarators); + + return -EINVAL; } depth--; break; + } case NODE_TYPEALIAS_ALIAS: + { + int nr_declarators; + switch (node->parent->type) { case NODE_TYPEALIAS: break; /* OK */ @@ -518,13 +552,21 @@ int _ctf_visitor_semantic_check(FILE *fd, int depth, struct ctf_node *node) if (ret) return ret; } + nr_declarators = 0; cds_list_for_each_entry(iter, &node->u.typealias_alias.type_declarators, siblings) { ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); if (ret) return ret; + nr_declarators++; + } + if (nr_declarators > 1) { + fprintf(fd, "[error] %s: Too many declarators in typealias alias (%d, max is 1)\n", __func__, nr_declarators); + + return -EINVAL; } depth--; break; + } case NODE_TYPEALIAS: switch (node->parent->type) { case NODE_ROOT: diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index c8e31337..ad28ac09 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -90,6 +90,7 @@ struct definition; /* type scope */ struct declaration_scope { /* Hash table mapping type name GQuark to "struct declaration" */ + /* Used for both typedef and typealias. */ GHashTable *typedef_declarations; /* Hash table mapping struct name GQuark to "struct declaration_struct" */ GHashTable *struct_declarations; -- 2.34.1 From a3cca9e94429c6a510f60924daf24ca9bd924753 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 20 Apr 2011 22:30:13 -0400 Subject: [PATCH 07/16] ctf visitor generate I/O struct: visit typedef/typealias Signed-off-by: Mathieu Desnoyers --- .../metadata/ctf-visitor-generate-io-struct.c | 390 +++++++++++++++++- 1 file changed, 382 insertions(+), 8 deletions(-) diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 1a3fe585..7e2dc072 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -35,6 +35,11 @@ #define _cds_list_first_entry(ptr, type, member) \ cds_list_entry((ptr)->next, type, member) +static +struct declaration *ctf_declaration_specifier_visit(FILE *fd, + int depth, struct list_head *head, + struct declaration_scope *declaration_scope); + static int ctf_visitor_print_type_specifier(FILE *fd, int depth, struct ctf_node *node) { @@ -259,27 +264,396 @@ struct ctf_stream *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_ return g_ptr_array_index(trace->streams, stream_id); } +static +struct declaration *ctf_type_declarator_visit(int fd, int depth, + struct cds_list_head *declaration_specifier, + GQuark *field_name, + struct ctf_node *node_type_declarator, + struct declaration_scope *declaration_scope + struct declaration *nested_declaration) +{ + /* + * Visit type declarator by first taking care of sequence/array + * (recursively). Then, when we get to the identifier, take care + * of pointers. + */ + + assert(node_type_declarator->u.type_declarator.type != TYPEDEC_UNKNOWN); + /* TODO: gcc bitfields not supported yet. */ + assert(node_type_declarator->u.type_declarator.bitfield_len == NULL); + + if (!nested_declaration) { + if (!cds_list_empty(&node_type_declarator->u.type_declarator.pointers)) { + /* + * If we have a pointer declarator, it _has_ to be present in + * the typealiases (else fail). + */ + nested_declaration = ... ; + } else { + nested_declaration = /* parse declaration_specifier */; + } + + } + + if (node_type_declarator->u.type_declarator.type == TYPEDEC_ID) { + if (node_type_declarator->u.type_declarator.u.id) + *field_name = g_quark_from_string(node_type_declarator->u.type_declarator.u.id); + else + *field_name = 0; + return nested_declaration; + } else { + struct declaration *declaration; + struct node *length; + + /* TYPEDEC_NESTED */ + + /* create array/sequence, pass nested_declaration as child. */ + length = node_type_declarator->u.type_declarator.u.nested.length; + if (length) { + switch (length->type) { + case NODE_UNARY_EXPRESSION: + /* Array */ + declaration = /* create array */; + break; + case NODE_TYPE_SPECIFIER: + /* Sequence */ + declaration = /* create sequence */; + break; + default: + assert(0); + } + } + + /* Pass it as content of outer container */ + declaration = ctf_type_declarator_visit(fd, depth, + declaration_specifier, field_name, + node_type_declarator->u.type_declarator.u.nested.type_declarator, + declaration_scope, declaration); + return declaration; + } +} + +static +int ctf_struct_type_declarators_visit(int fd, int depth, + struct declaration_struct *struct_declaration, + struct cds_list_head *declaration_specifier, + struct cds_list_head *type_declarators, + struct declaration_scope *declaration_scope) +{ + struct ctf_node *iter; + GQuark field_name; + + cds_list_for_each_entry(iter, type_declarators, siblings) { + struct declaration *field_declaration; + + field_declaration = ctf_type_declarator_visit(fd, depth, + declaration_specifier, + &field_name, iter, + struct_declaration->scope, + NULL); + struct_declaration_add_field(struct_declaration, + g_quark_to_string(field_name), + field_declaration); + } + + return 0; +} + +static +int ctf_typedef_visit(int fd, int depth, struct declaration_scope *scope, + struct cds_list_head *declaration_specifier, + struct cds_list_head *type_declarators) +{ + struct ctf_node *iter; + GQuark identifier; + + cds_list_for_each_entry(iter, type_declarators, siblings) { + struct declaration *type_declaration; + int ret; + + type_declaration = ctf_type_declarator_visit(fd, depth, + declaration_specifier, + &identifier, iter, + scope, NULL); + ret = register_declaration(identifier, type_declaration, scope); + if (ret) { + type_declaration->declaration_free(type_declaration); + return ret; + } + } + return 0; +} + +static +int ctf_typealias_visit(int fd, int depth, struct declaration_scope *scope, + struct ctf_node *target, struct ctf_node *alias) +{ + struct declaration *type_declaration; + struct ctf_node *iter, *node; + GQuark identifier, dummy_id; + GString *str; + const char *str_c; + GQuark alias_q; + int alias_item_nr = 0; + + /* See ctf_visitor_type_declarator() in the semantic validator. */ + + /* + * Create target type declaration. + */ + + type_declaration = ctf_type_declarator_visit(fd, depth, + &target->u.typealias_target.declaration_specifier, + &dummy_id, &target->u.typealias_target.type_declarators, + scope, NULL); + if (!type_declaration) { + fprintf(stderr, "[error] %s: problem creating type declaration\n", __func__); + err = -EINVAL; + goto error; + } + /* + * The semantic validator does not check whether the target is + * abstract or not (if it has an identifier). Check it here. + */ + if (dummy_id != 0) { + fprintf(stderr, "[error] %s: expecting empty identifier\n", __func__); + err = -EINVAL; + goto error; + } + /* + * Create alias identifier. + */ + str = g_string_new(); + cds_list_for_each_entry(iter, &alias->u.typealias_alias.declaration_specifier, siblings) { + if (alias_item_nr != 0) + g_string_append(str, " "); + alias_item_nr++; + + switch (iter->type) { + case NODE_TYPE_SPECIFIER: + switch (iter->u.type_specifier.type) { + case TYPESPEC_VOID: + g_string_append(str, "void"); + break; + case TYPESPEC_CHAR: + g_string_append(str, "char"); + break; + case TYPESPEC_SHORT: + g_string_append(str, "short"); + break; + case TYPESPEC_INT: + g_string_append(str, "int"); + break; + case TYPESPEC_LONG: + g_string_append(str, "long"); + break; + case TYPESPEC_FLOAT: + g_string_append(str, "float"); + break; + case TYPESPEC_DOUBLE: + g_string_append(str, "double"); + break; + case TYPESPEC_SIGNED: + g_string_append(str, "signed"); + break; + case TYPESPEC_UNSIGNED: + g_string_append(str, "unsigned"); + break; + case TYPESPEC_BOOL: + g_string_append(str, "bool"); + break; + case TYPESPEC_COMPLEX: + g_string_append(str, "_Complex"); + break; + case TYPESPEC_IMAGINARY: + g_string_append(str, "_Imaginary"); + break; + case TYPESPEC_CONST: + g_string_append(str, "const"); + break; + case TYPESPEC_ID_TYPE: + if (!iter->u.type_specifier.id_type) { + fprintf(stderr, "[error] %s: unexpected empty ID\n", __func__); + err = -EINVAL; + goto error; + } + g_string_append(str, iter->u.type_specifier.id_type); + break; + default: + fprintf(stderr, "[error] %s: unknown specifier\n", __func__); + err = -EINVAL; + goto error; + } + break; + case NODE_ENUM: + if (!iter->u._enum.enum_id) { + fprintf(stderr, "[error] %s: unexpected empty enum ID\n", __func__); + err = -EINVAL; + goto error; + } + g_string_append(str, "enum "); + g_string_append(str, iter->u._enum.enum_id); + break; + case NODE_VARIANT: + if (!iter->u.variant.name) { + fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__); + err = -EINVAL; + goto error; + } + g_string_append(str, "variant "); + g_string_append(str, iter->u.variant.name); + break; + case NODE_STRUCT: + if (!iter->u._struct.name) { + fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__); + err = -EINVAL; + goto error; + } + g_string_append(str, "struct "); + g_string_append(str, iter->u._struct.name); + break; + default: + fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type); + err = -EINVAL; + goto error; + } + } + + node = _cds_list_first_entry(&alias->u.typealias_alias.type_declarators, + struct node, siblings) { + cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, siblings) { + g_string_append(str, " *"); + if (iter->u.pointer.const_qualifier) + g_string_append(str, " const"); + } + + } + str_c = g_string_free(str, FALSE); + alias_q = g_quark_from_string(str_c); + g_free(str_c); + ret = register_declaration(alias_q, type_declaration, scope); + if (ret) + goto error; + return 0; + +error: + type_declaration->declaration_free(type_declaration); + return ret; +} + +static +int ctf_struct_declaration_list_visit(int fd, int depth, + struct ctf_node *iter, struct declaration_struct *struct_declaration) +{ + struct declaration *declaration; + int ret; + + switch (iter->type) { + case NODE_TYPEDEF: + /* For each declarator, declare type and add type to struct declaration scope */ + ret = ctf_typedef_visit(fd, depth, + struct_declaration->scope, + &iter->u._typedef.declaration_specifier, + &iter->u._typedef.type_declarators); + if (ret) + return ret; + break; + case NODE_TYPEALIAS: + /* Declare type with declarator and add type to struct declaration scope */ + ret = ctf_typealias_visit(fd, depth, + struct_declaration->scope, + iter->u.typealias.target, + iter->u.typealias.alias); + if (ret) + return ret; + break; + case NODE_STRUCT_OR_VARIANT_DECLARATION: + /* Add field to structure declaration */ + ret = ctf_struct_type_declarators_visit(fd, depth, + struct_declaration, + &iter->u.struct_or_variant_declaration.declaration_specifier, + &iter->u.struct_or_variant_declaration.type_declarators); + if (ret) + return ret; + break; + default: + fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type); + assert(0); + } + return 0; +} + +static +struct declaration_struct *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) +{ + struct declaration *declaration; + struct declaration_struct *struct_declaration; + struct ctf_node *iter; + + /* + * For named struct (without body), lookup in + * declaration scope. Don't take reference on struct + * declaration: ref is only taken upon definition. + */ + if (!has_body) { + assert(name); + struct_declaration = + lookup_struct_declaration(g_quark_from_string(name), + declaration_scope); + return struct_declaration; + } else { + /* For unnamed struct, create type */ + /* For named struct (with body), create type and add to declaration scope */ + if (name) { + if (lookup_struct_declaration(g_quark_from_string(name), + declaration_scope)) { + + fprintf(stderr, "[error] %s: struct %s already declared in scope\n", name); + return NULL; + } + } + struct_declaration = struct_declaration_new(name, declaration_scope); + cds_list_for_each_entry(iter, declaration_list, siblings) { + ret = ctf_struct_declaration_list_visit(fd, +depth + 1, iter, struct_declaration); + if (ret) + goto error; + } + if (name) { + ret = register_struct_declaration(g_quark_from_string(name), + struct_declaration, + declaration_scope); + assert(!ret); + } + return struct_declaration; + } +error: + struct_declaration->p.declaration_free(&struct_declaration->p); + return NULL; +} + /* * Also add named variant, struct or enum to the current declaration scope. */ static -struct ctf_declaration *ctf_declaration_specifier_visit(FILE *fd, +struct declaration *ctf_declaration_specifier_visit(FILE *fd, int depth, struct list_head *head, struct declaration_scope *declaration_scope) { - struct ctf_declaration *declaration; + struct declaration *declaration; struct node *first; first = _cds_list_first_entry(head, struct node, siblings); switch (first->type) { case NODE_STRUCT: - /* - * For named struct (without body), lookup in - * declaration scope and create declaration copy. - */ - /* For named struct (with body), create type and add to declaration scope */ - /* For unnamed struct, create type */ + return ctf_declaration_struct_visit(fd, depth, + first->u._struct.name, + &first->u._struct.declaration_list, + first->u._struct.has_body, + declaration_scope); break; case NODE_VARIANT: /* -- 2.34.1 From add40b62157cb13cfa1144c59f6bb6054ad5b8a1 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Apr 2011 00:19:08 -0400 Subject: [PATCH 08/16] Work in progress generate io struct Signed-off-by: Mathieu Desnoyers --- formats/ctf/metadata/ctf-ast.h | 1 + formats/ctf/metadata/ctf-parser.y | 16 + .../metadata/ctf-visitor-generate-io-struct.c | 995 ++++++++---------- formats/ctf/types/float.c | 16 +- include/babeltrace/types.h | 8 +- types/float.c | 9 +- types/integer.c | 3 +- 7 files changed, 453 insertions(+), 595 deletions(-) diff --git a/formats/ctf/metadata/ctf-ast.h b/formats/ctf/metadata/ctf-ast.h index 0ce21a5a..8a2888da 100644 --- a/formats/ctf/metadata/ctf-ast.h +++ b/formats/ctf/metadata/ctf-ast.h @@ -206,6 +206,7 @@ struct ctf_node { /* NULL, value or declaration specifier */ struct ctf_node *container_type; struct cds_list_head enumerator_list; + int has_body; } _enum; struct { struct cds_list_head declaration_specifier; diff --git a/formats/ctf/metadata/ctf-parser.y b/formats/ctf/metadata/ctf-parser.y index f6c61859..07d98738 100644 --- a/formats/ctf/metadata/ctf-parser.y +++ b/formats/ctf/metadata/ctf-parser.y @@ -1542,23 +1542,27 @@ enum_type_specifier: LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; _cds_list_splice_tail(&($2)->tmp_head, &($$)->u._enum.enumerator_list); } | LT type_specifier_or_integer_constant GT LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.container_type = $2; _cds_list_splice_tail(&($5)->tmp_head, &($$)->u._enum.enumerator_list); } | IDENTIFIER LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } | IDENTIFIER LT type_specifier_or_integer_constant GT LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; $$->u._enum.container_type = $3; _cds_list_splice_tail(&($6)->tmp_head, &($$)->u._enum.enumerator_list); @@ -1566,12 +1570,14 @@ enum_type_specifier: | ID_TYPE LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } | ID_TYPE LT type_specifier_or_integer_constant GT LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; $$->u._enum.container_type = $3; _cds_list_splice_tail(&($6)->tmp_head, &($$)->u._enum.enumerator_list); @@ -1579,23 +1585,27 @@ enum_type_specifier: | LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; _cds_list_splice_tail(&($2)->tmp_head, &($$)->u._enum.enumerator_list); } | LT type_specifier_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.container_type = $2; _cds_list_splice_tail(&($5)->tmp_head, &($$)->u._enum.enumerator_list); } | IDENTIFIER LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } | IDENTIFIER LT type_specifier_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; $$->u._enum.container_type = $3; _cds_list_splice_tail(&($6)->tmp_head, &($$)->u._enum.enumerator_list); @@ -1603,23 +1613,27 @@ enum_type_specifier: | IDENTIFIER { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; } | IDENTIFIER LT type_specifier_or_integer_constant GT { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; $$->u._enum.container_type = $3; } | ID_TYPE LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } | ID_TYPE LT type_specifier_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; $$->u._enum.container_type = $3; _cds_list_splice_tail(&($6)->tmp_head, &($$)->u._enum.enumerator_list); @@ -1627,11 +1641,13 @@ enum_type_specifier: | ID_TYPE { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; } | ID_TYPE LT type_specifier_or_integer_constant GT { $$ = make_node(scanner, NODE_ENUM); + $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; $$->u._enum.container_type = $3; } diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 7e2dc072..fd6176fe 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -37,157 +38,14 @@ static struct declaration *ctf_declaration_specifier_visit(FILE *fd, - int depth, struct list_head *head, + int depth, struct cds_list_head *head, struct declaration_scope *declaration_scope); -static -int ctf_visitor_print_type_specifier(FILE *fd, int depth, struct ctf_node *node) -{ - print_tabs(fd, depth); - fprintf(fd, "u.type_specifier.type) { - case TYPESPEC_VOID: - fprintf(fd, "void"); - break; - case TYPESPEC_CHAR: - fprintf(fd, "char"); - break; - case TYPESPEC_SHORT: - fprintf(fd, "short"); - break; - case TYPESPEC_INT: - fprintf(fd, "int"); - break; - case TYPESPEC_LONG: - fprintf(fd, "long"); - break; - case TYPESPEC_FLOAT: - fprintf(fd, "float"); - break; - case TYPESPEC_DOUBLE: - fprintf(fd, "double"); - break; - case TYPESPEC_SIGNED: - fprintf(fd, "signed"); - break; - case TYPESPEC_UNSIGNED: - fprintf(fd, "unsigned"); - break; - case TYPESPEC_BOOL: - fprintf(fd, "bool"); - break; - case TYPESPEC_COMPLEX: - fprintf(fd, "_Complex"); - break; - case TYPESPEC_IMAGINARY: - fprintf(fd, "_Imaginary"); - break; - case TYPESPEC_CONST: - fprintf(fd, "const"); - break; - case TYPESPEC_ID_TYPE: - fprintf(fd, "%s", node->u.type_specifier.id_type); - break; - - case TYPESPEC_UNKNOWN: - default: - fprintf(stderr, "[error] %s: unknown type specifier %d\n", __func__, - (int) node->u.type_specifier.type); - return -EINVAL; - } - fprintf(fd, "\"/>\n"); - return 0; -} - -static -int ctf_visitor_print_type_declarator(FILE *fd, int depth, struct ctf_node *node) -{ - int ret = 0; - struct ctf_node *iter; - - print_tabs(fd, depth); - fprintf(fd, "\n"); - depth++; - - if (!cds_list_empty(&node->u.type_declarator.pointers)) { - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, - siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - } - - switch (node->u.type_declarator.type) { - case TYPEDEC_ID: - if (node->u.type_declarator.u.id) { - print_tabs(fd, depth); - fprintf(fd, "u.type_declarator.u.id); - fprintf(fd, "\" />\n"); - } - break; - case TYPEDEC_NESTED: - if (node->u.type_declarator.u.nested.type_declarator) { - print_tabs(fd, depth); - fprintf(fd, "\n"); - ret = ctf_visitor_print_xml(fd, depth + 1, - node->u.type_declarator.u.nested.type_declarator); - if (ret) - return ret; - print_tabs(fd, depth); - fprintf(fd, "\n"); - } - if (node->u.type_declarator.u.nested.length) { - print_tabs(fd, depth); - fprintf(fd, "\n"); - ret = ctf_visitor_print_xml(fd, depth + 1, - node->u.type_declarator.u.nested.length); - if (ret) - return ret; - print_tabs(fd, depth); - fprintf(fd, "\n"); - } - if (node->u.type_declarator.u.nested.abstract_array) { - print_tabs(fd, depth); - fprintf(fd, "\n"); - print_tabs(fd, depth); - fprintf(fd, "\n"); - } - if (node->u.type_declarator.bitfield_len) { - print_tabs(fd, depth); - fprintf(fd, "\n"); - ret = ctf_visitor_print_xml(fd, depth + 1, - node->u.type_declarator.bitfield_len); - if (ret) - return ret; - print_tabs(fd, depth); - fprintf(fd, "\n"); - } - break; - case TYPEDEC_UNKNOWN: - default: - fprintf(stderr, "[error] %s: unknown type declarator %d\n", __func__, - (int) node->u.type_declarator.type); - return -EINVAL; - } - - depth--; - print_tabs(fd, depth); - fprintf(fd, "\n"); - return 0; -} - /* * String returned must be freed by the caller using g_free. */ static -char *concatenate_unary_strings(struct list_head *head) +char *concatenate_unary_strings(struct cds_list_head *head) { struct ctf_node *node; GString *str; @@ -220,7 +78,7 @@ char *concatenate_unary_strings(struct list_head *head) } static -int get_unary_unsigned(struct list_head *head, uint64_t *value) +int get_unary_unsigned(struct cds_list_head *head, uint64_t *value) { struct ctf_node *node; int i = 0; @@ -237,7 +95,7 @@ int get_unary_unsigned(struct list_head *head, uint64_t *value) } static -int get_unary_uuid(struct list_head *head, uuid_t *uuid) +int get_unary_uuid(struct cds_list_head *head, uuid_t *uuid) { struct ctf_node *node; int i = 0; @@ -264,12 +122,141 @@ struct ctf_stream *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_ return g_ptr_array_index(trace->streams, stream_id); } +static +void visit_declaration_specifier(struct cds_list_head *declaration_specifier, GString *str) +{ + struct ctf_node *iter; + int alias_item_nr = 0; + int err; + + cds_list_for_each_entry(iter, declaration_specifier, siblings) { + if (alias_item_nr != 0) + g_string_append(str, " "); + alias_item_nr++; + + switch (iter->type) { + case NODE_TYPE_SPECIFIER: + switch (iter->u.type_specifier.type) { + case TYPESPEC_VOID: + g_string_append(str, "void"); + break; + case TYPESPEC_CHAR: + g_string_append(str, "char"); + break; + case TYPESPEC_SHORT: + g_string_append(str, "short"); + break; + case TYPESPEC_INT: + g_string_append(str, "int"); + break; + case TYPESPEC_LONG: + g_string_append(str, "long"); + break; + case TYPESPEC_FLOAT: + g_string_append(str, "float"); + break; + case TYPESPEC_DOUBLE: + g_string_append(str, "double"); + break; + case TYPESPEC_SIGNED: + g_string_append(str, "signed"); + break; + case TYPESPEC_UNSIGNED: + g_string_append(str, "unsigned"); + break; + case TYPESPEC_BOOL: + g_string_append(str, "bool"); + break; + case TYPESPEC_COMPLEX: + g_string_append(str, "_Complex"); + break; + case TYPESPEC_IMAGINARY: + g_string_append(str, "_Imaginary"); + break; + case TYPESPEC_CONST: + g_string_append(str, "const"); + break; + case TYPESPEC_ID_TYPE: + if (iter->u.type_specifier.id_type) + g_string_append(str, iter->u.type_specifier.id_type); + break; + default: + fprintf(stderr, "[error] %s: unknown specifier\n", __func__); + err = -EINVAL; + goto error; + } + break; + case NODE_ENUM: + if (!iter->u._enum.enum_id) { + fprintf(stderr, "[error] %s: unexpected empty enum ID\n", __func__); + err = -EINVAL; + goto error; + } + g_string_append(str, "enum "); + g_string_append(str, iter->u._enum.enum_id); + break; + case NODE_VARIANT: + if (!iter->u.variant.name) { + fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__); + err = -EINVAL; + goto error; + } + g_string_append(str, "variant "); + g_string_append(str, iter->u.variant.name); + break; + case NODE_STRUCT: + if (!iter->u._struct.name) { + fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__); + err = -EINVAL; + goto error; + } + g_string_append(str, "struct "); + g_string_append(str, iter->u._struct.name); + break; + default: + fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type); + err = -EINVAL; + goto error; + } + } + return 0; +error: + return err; +} + +static +GQuark create_typealias_identifier(int fd, int depth, + struct cds_list_head *declaration_specifier, + struct ctf_node *node_type_declarator) +{ + GString *str; + const char *str_c; + GQuark alias_q; + int ret; + + str = g_string_new(); + ret = visit_declaration_specifier(declaration_specifier, str); + if (ret) { + g_string_free(str, TRUE); + return 0; + } + cds_list_for_each_entry(iter, &node_type_declarator->u.type_declarator.pointers, siblings) { + g_string_append(str, " *"); + if (iter->u.pointer.const_qualifier) + g_string_append(str, " const"); + } + str_c = g_string_free(str, FALSE); + alias_q = g_quark_from_string(str_c); + g_free(str_c); + return alias_q; +} + static struct declaration *ctf_type_declarator_visit(int fd, int depth, struct cds_list_head *declaration_specifier, GQuark *field_name, struct ctf_node *node_type_declarator, - struct declaration_scope *declaration_scope + struct declaration_scope *declaration_scope, struct declaration *nested_declaration) { /* @@ -279,20 +266,31 @@ struct declaration *ctf_type_declarator_visit(int fd, int depth, */ assert(node_type_declarator->u.type_declarator.type != TYPEDEC_UNKNOWN); + /* TODO: gcc bitfields not supported yet. */ - assert(node_type_declarator->u.type_declarator.bitfield_len == NULL); + if (node_type_declarator->u.type_declarator.bitfield_len != NULL) { + fprintf(stderr, "[error] %s: gcc bitfields are not supported yet.\n", __func__); + return NULL; + } if (!nested_declaration) { if (!cds_list_empty(&node_type_declarator->u.type_declarator.pointers)) { + GQuark alias_q; + /* * If we have a pointer declarator, it _has_ to be present in * the typealiases (else fail). */ - nested_declaration = ... ; + alias_q = create_typealias_identifier(fd, depth, + declaration_specifier, node_type_declarator); + nested_declaration = lookup_declaration(alias_q, declaration_scope); + if (!nested_declaration) { + fprintf(stderr, "[error] %s: cannot find typealias \"%s\".\n", __func__, g_quark_to_string(alias_q)); + return NULL; + } } else { nested_declaration = /* parse declaration_specifier */; } - } if (node_type_declarator->u.type_declarator.type == TYPEDEC_ID) { @@ -313,6 +311,8 @@ struct declaration *ctf_type_declarator_visit(int fd, int depth, switch (length->type) { case NODE_UNARY_EXPRESSION: /* Array */ + /* TODO */ + ............. declaration = /* create array */; break; case NODE_TYPE_SPECIFIER: @@ -355,7 +355,31 @@ int ctf_struct_type_declarators_visit(int fd, int depth, g_quark_to_string(field_name), field_declaration); } + return 0; +} +static +int ctf_variant_type_declarators_visit(int fd, int depth, + struct declaration_variant *variant_declaration, + struct cds_list_head *declaration_specifier, + struct cds_list_head *type_declarators, + struct declaration_scope *declaration_scope) +{ + struct ctf_node *iter; + GQuark field_name; + + cds_list_for_each_entry(iter, type_declarators, siblings) { + struct declaration *field_declaration; + + field_declaration = ctf_type_declarator_visit(fd, depth, + declaration_specifier, + &field_name, iter, + variant_declaration->scope, + NULL); + variant_declaration_add_field(variant_declaration, + g_quark_to_string(field_name), + field_declaration); + } return 0; } @@ -390,11 +414,8 @@ int ctf_typealias_visit(int fd, int depth, struct declaration_scope *scope, { struct declaration *type_declaration; struct ctf_node *iter, *node; - GQuark identifier, dummy_id; - GString *str; - const char *str_c; + GQuark dummy_id; GQuark alias_q; - int alias_item_nr = 0; /* See ctf_visitor_type_declarator() in the semantic validator. */ @@ -423,114 +444,11 @@ int ctf_typealias_visit(int fd, int depth, struct declaration_scope *scope, /* * Create alias identifier. */ - str = g_string_new(); - cds_list_for_each_entry(iter, &alias->u.typealias_alias.declaration_specifier, siblings) { - if (alias_item_nr != 0) - g_string_append(str, " "); - alias_item_nr++; - - switch (iter->type) { - case NODE_TYPE_SPECIFIER: - switch (iter->u.type_specifier.type) { - case TYPESPEC_VOID: - g_string_append(str, "void"); - break; - case TYPESPEC_CHAR: - g_string_append(str, "char"); - break; - case TYPESPEC_SHORT: - g_string_append(str, "short"); - break; - case TYPESPEC_INT: - g_string_append(str, "int"); - break; - case TYPESPEC_LONG: - g_string_append(str, "long"); - break; - case TYPESPEC_FLOAT: - g_string_append(str, "float"); - break; - case TYPESPEC_DOUBLE: - g_string_append(str, "double"); - break; - case TYPESPEC_SIGNED: - g_string_append(str, "signed"); - break; - case TYPESPEC_UNSIGNED: - g_string_append(str, "unsigned"); - break; - case TYPESPEC_BOOL: - g_string_append(str, "bool"); - break; - case TYPESPEC_COMPLEX: - g_string_append(str, "_Complex"); - break; - case TYPESPEC_IMAGINARY: - g_string_append(str, "_Imaginary"); - break; - case TYPESPEC_CONST: - g_string_append(str, "const"); - break; - case TYPESPEC_ID_TYPE: - if (!iter->u.type_specifier.id_type) { - fprintf(stderr, "[error] %s: unexpected empty ID\n", __func__); - err = -EINVAL; - goto error; - } - g_string_append(str, iter->u.type_specifier.id_type); - break; - default: - fprintf(stderr, "[error] %s: unknown specifier\n", __func__); - err = -EINVAL; - goto error; - } - break; - case NODE_ENUM: - if (!iter->u._enum.enum_id) { - fprintf(stderr, "[error] %s: unexpected empty enum ID\n", __func__); - err = -EINVAL; - goto error; - } - g_string_append(str, "enum "); - g_string_append(str, iter->u._enum.enum_id); - break; - case NODE_VARIANT: - if (!iter->u.variant.name) { - fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__); - err = -EINVAL; - goto error; - } - g_string_append(str, "variant "); - g_string_append(str, iter->u.variant.name); - break; - case NODE_STRUCT: - if (!iter->u._struct.name) { - fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__); - err = -EINVAL; - goto error; - } - g_string_append(str, "struct "); - g_string_append(str, iter->u._struct.name); - break; - default: - fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type); - err = -EINVAL; - goto error; - } - } node = _cds_list_first_entry(&alias->u.typealias_alias.type_declarators, - struct node, siblings) { - cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, siblings) { - g_string_append(str, " *"); - if (iter->u.pointer.const_qualifier) - g_string_append(str, " const"); - } - - } - str_c = g_string_free(str, FALSE); - alias_q = g_quark_from_string(str_c); - g_free(str_c); + struct node, siblings); + alias_q = create_typealias_identifier(fd, depth, + &alias->u.typealias_alias.declaration_specifier, node); ret = register_declaration(alias_q, type_declaration, scope); if (ret) goto error; @@ -583,6 +501,48 @@ int ctf_struct_declaration_list_visit(int fd, int depth, return 0; } +static +int ctf_variant_declaration_list_visit(int fd, int depth, + struct ctf_node *iter, struct declaration_variant *variant_declaration) +{ + struct declaration *declaration; + int ret; + + switch (iter->type) { + case NODE_TYPEDEF: + /* For each declarator, declare type and add type to variant declaration scope */ + ret = ctf_typedef_visit(fd, depth, + variant_declaration->scope, + &iter->u._typedef.declaration_specifier, + &iter->u._typedef.type_declarators); + if (ret) + return ret; + break; + case NODE_TYPEALIAS: + /* Declare type with declarator and add type to variant declaration scope */ + ret = ctf_typealias_visit(fd, depth, + variant_declaration->scope, + iter->u.typealias.target, + iter->u.typealias.alias); + if (ret) + return ret; + break; + case NODE_STRUCT_OR_VARIANT_DECLARATION: + /* Add field to structure declaration */ + ret = ctf_variant_type_declarators_visit(fd, depth, + variant_declaration, + &iter->u.struct_or_variant_declaration.declaration_specifier, + &iter->u.struct_or_variant_declaration.type_declarators); + if (ret) + return ret; + break; + default: + fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type); + assert(0); + } + return 0; +} + static struct declaration_struct *ctf_declaration_struct_visit(FILE *fd, int depth, const char *name, struct cds_list_head *declaration_list, @@ -610,14 +570,13 @@ struct declaration_struct *ctf_declaration_struct_visit(FILE *fd, if (lookup_struct_declaration(g_quark_from_string(name), declaration_scope)) { - fprintf(stderr, "[error] %s: struct %s already declared in scope\n", name); + fprintf(stderr, "[error] %s: struct %s already declared in scope\n", __func__, name); return NULL; } } struct_declaration = struct_declaration_new(name, declaration_scope); cds_list_for_each_entry(iter, declaration_list, siblings) { - ret = ctf_struct_declaration_list_visit(fd, -depth + 1, iter, struct_declaration); + ret = ctf_struct_declaration_list_visit(fd, depth + 1, iter, struct_declaration); if (ret) goto error; } @@ -634,120 +593,232 @@ error: return NULL; } -/* - * Also add named variant, struct or enum to the current declaration scope. - */ static -struct declaration *ctf_declaration_specifier_visit(FILE *fd, - int depth, struct list_head *head, - struct declaration_scope *declaration_scope) +struct declaration_variant *ctf_declaration_variant_visit(FILE *fd, + int depth, const char *name, struct cds_list_head *declaration_list, + int has_body, struct declaration_scope *declaration_scope) { struct declaration *declaration; - struct node *first; - - first = _cds_list_first_entry(head, struct node, siblings); + struct declaration_variant *variant_declaration; + struct ctf_node *iter; - switch (first->type) { - case NODE_STRUCT: - return ctf_declaration_struct_visit(fd, depth, - first->u._struct.name, - &first->u._struct.declaration_list, - first->u._struct.has_body, - declaration_scope); - break; - case NODE_VARIANT: - /* - * For named variant (without body), lookup in - * declaration scope and create declaration copy. - */ - /* For named variant (with body), create type and add to declaration scope */ + /* + * For named variant (without body), lookup in + * declaration scope. Don't take reference on variant + * declaration: ref is only taken upon definition. + */ + if (!has_body) { + assert(name); + variant_declaration = + lookup_variant_declaration(g_quark_from_string(name), + declaration_scope); + return variant_declaration; + } else { /* For unnamed variant, create type */ - /* If variant has a tag field specifier, assign tag name. */ - break; - case NODE_ENUM: - /* - * For named enum (without body), lookup in declaration - * scope and create declaration copy. - */ - /* For named enum (with body), create type and add to declaration scope */ - /* For unnamed enum, create type */ - /* Enumerations need to have their size/type specifier (< >). */ - break; - case NODE_INTEGER: - /* - * Create an integer declaration. - */ - break; - case NODE_FLOATING_POINT: - /* - * Create a floating point declaration. - */ - break; - case NODE_STRING: - /* - * Create a string declaration. - */ - break; - case NODE_TYPE_SPECIFIER: - /* - * Lookup named type in typedef declarations (in - * declaration scope). Create a copy of the declaration. - */ - break; - + /* For named variant (with body), create type and add to declaration scope */ + if (name) { + if (lookup_variant_declaration(g_quark_from_string(name), + declaration_scope)) { + + fprintf(stderr, "[error] %s: variant %s already declared in scope\n", __func__, name); + return NULL; + } + } + variant_declaration = variant_declaration_new(name, declaration_scope); + cds_list_for_each_entry(iter, declaration_list, siblings) { + ret = ctf_variant_declaration_list_visit(fd, depth + 1, iter, variant_declaration); + if (ret) + goto error; + } + if (name) { + ret = register_variant_declaration(g_quark_from_string(name), + variant_declaration, + declaration_scope); + assert(!ret); + } + return variant_declaration; } +error: + variant_declaration->p.declaration_free(&variant_declaration->p); + return NULL; } static -int ctf_typedef_declarator_visit(FILE *fd, int depth, - struct list_head *declaration_specifier, - struct node *type_declarator, - struct declaration_scope *declaration_scope) +int ctf_enumerator_list_visit(int fd, int depth, + struct ctf_node *enumerator, + struct declaration_enum *enum_declaration) +{ + /* TODO */ +........ + return 0; +} + +static +struct declaration *ctf_declaration_enum_visit(int fd, int depth, + const char *name, + struct ctf_node *container_type, + struct cds_list_head *enumerator_list, + int has_body) { + struct declaration *declaration; + struct declaration_enum *enum_declaration; + struct declaration_integer *integer_declaration; + struct ctf_node *iter; + /* - * Build the type using declaration specifier (creating - * declaration from type_specifier), then apply type declarator, - * add the resulting type to the current declaration scope. + * For named enum (without body), lookup in + * declaration scope. Don't take reference on enum + * declaration: ref is only taken upon definition. */ - cds_list_for_each_entry(iter, declaration_specifier, siblings) { - + if (!has_body) { + assert(name); + enum_declaration = + lookup_enum_declaration(g_quark_from_string(name), + declaration_scope); + return enum_declaration; + } else { + /* For unnamed enum, create type */ + /* For named enum (with body), create type and add to declaration scope */ + if (name) { + if (lookup_enum_declaration(g_quark_from_string(name), + declaration_scope)) { + + fprintf(stderr, "[error] %s: enum %s already declared in scope\n", __func__, name); + return NULL; + } + } + /* TODO CHECK Enumerations need to have their size/type specifier (< >). */ + integer_declaration = integer_declaration_new(); /* TODO ... */ + ..... + enum_declaration = enum_declaration_new(name, integer_declaration); + declaration_unref(&integer_declaration->p); /* leave ref to enum */ + cds_list_for_each_entry(iter, enumerator_list, siblings) { + ret = ctf_enumerator_list_visit(fd, depth + 1, iter, enum_declaration); + if (ret) + goto error; + } + if (name) { + ret = register_enum_declaration(g_quark_from_string(name), + enum_declaration, + declaration_scope); + assert(!ret); + } + return enum_declaration; } - return 0; +error: + enum_declaration->p.declaration_free(&enum_declaration->p); + return NULL; } static -int ctf_typedef_visit(FILE *fd, int depth, - struct list_head *declaration_specifier, - struct list_head *type_declarators, +struct declaration *ctf_declaration_type_specifier_visit(int fd, int depth, + struct cds_list_head *declaration_specifier, struct declaration_scope *declaration_scope) { - struct ctf_node *iter; + GString *str; + struct declaration *declaration; + const char *str_c; - cds_list_for_each_entry(iter, type_declarators, siblings) { - ret = ctf_typedef_declarator_visit(fd, depth + 1, - &node->u._typedef.declaration_specifier, iter, - declaration_scope); - if (ret) - return ret; + str = g_string_new(); + ret = visit_declaration_specifier(declaration_specifier, str); + if (ret) + return NULL; + str_c = g_string_free(str, FALSE); + id_q = g_quark_from_string(str_c); + g_free(str_c); + declaration = lookup_declaration(id_q, declaration_scope); + return declaration; +} + +static +struct declaration *ctf_declaration_integer_visit(int fd, int depth, + struct cds_list_head *expressions) +{ + struct node *expression; + uint64_t alignment, size, byte_order = trace->native_bo, signedness = 0; + int has_alignment = 0, has_size = 0; + struct declaration_integer *integer_declaration; + + cds_list_for_each_entry(expression, expressions, siblings) { + struct node *left, *right; + + left = expression->u.ctf_expression.left; + right = expression->u.ctf_expression.right; + assert(left->u.unary_expression.type == UNARY_STRING); + if (!strcmp(left->u.unary_expression.u.string, "signed")) { + /* TODO */ + ........... + } else if (!strcmp(left->u.unary_expression.u.string, "byte_order")) { + + } else if (!strcmp(left->u.unary_expression.u.string, "size")) { + has_size = 1; + } else if (!strcmp(left->u.unary_expression.u.string, "align")) { + has_alignment = 1; + } else { + fprintf(stderr, "[error] %s: unknown attribute name %s\n", + __func__, left->u.unary_expression.u.string); + return NULL; + } } - return 0; + if (!has_alignment) { + fprintf(stderr, "[error] %s: missing alignment attribute\n", __func__); + return NULL; + } + if (!has_size) { + fprintf(stderr, "[error] %s: missing size attribute\n", __func__); + return NULL; + } + integer_declaration = integer_declaration_new(size, + byte_order, signedness, alignment); + return &integer_declaration->p; } +/* + * Also add named variant, struct or enum to the current declaration scope. + */ static -int ctf_typealias_visit(FILE *fd, int depth, struct ctf_node *target, - struct ctf_node *alias, +struct declaration *ctf_declaration_specifier_visit(FILE *fd, + int depth, struct cds_list_head *head, struct declaration_scope *declaration_scope) { - /* - * Build target type, check that it is reachable in current - * declaration scope. - */ + struct declaration *declaration; + struct node *first; - /* Only one type declarator is allowed */ + first = _cds_list_first_entry(head, struct node, siblings); - /* Build alias type, add to current declaration scope. */ - /* Only one type declarator is allowed */ + switch (first->type) { + case NODE_STRUCT: + return ctf_declaration_struct_visit(fd, depth, + first->u._struct.name, + &first->u._struct.declaration_list, + first->u._struct.has_body, + declaration_scope); + case NODE_VARIANT: + return ctf_declaration_variant_visit(fd, depth, + first->u.variant.name, + &first->u.variant.declaration_list, + first->u.variant.has_body, + declaration_scope); + case NODE_ENUM: + return ctf_declaration_enum_visit(fd, depth, + first->u._enum.enum_id, + first->u._enum.container_type, + &first->u._enum.enumerator_list, + first->u._enum.has_body); + case NODE_INTEGER: + return ctf_declaration_integer_visit(fd, depth, + &first->u.integer.expressions); + case NODE_FLOATING_POINT: /* TODO */ + return ctf_declaration_floating_point_visit(fd, depth, + &first->u.floating_point.expressions); + case NODE_STRING: /* TODO */ + return ctf_declaration_string_visit(fd, depth, + &first->u.string.expressions); + case NODE_TYPE_SPECIFIER: + return ctf_declaration_type_specifier_visit(fd, depth, + head, declaration_scope); + } } static @@ -1144,7 +1215,6 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return 0; } - static int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace) { @@ -1234,229 +1304,6 @@ int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *t return ret; } break; - - case NODE_TYPEALIAS_TARGET: - print_tabs(fd, depth); - fprintf(fd, "\n"); - depth++; - - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.typealias_target.declaration_specifier, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.typealias_target.type_declarators, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - - depth--; - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_TYPEALIAS_ALIAS: - print_tabs(fd, depth); - fprintf(fd, "\n"); - depth++; - - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.typealias_alias.declaration_specifier, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.typealias_alias.type_declarators, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - - depth--; - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_TYPEALIAS: - print_tabs(fd, depth); - fprintf(fd, "\n"); - ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.target); - if (ret) - return ret; - ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.alias); - if (ret) - return ret; - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - - case NODE_TYPE_SPECIFIER: - ret = ctf_visitor_print_type_specifier(fd, depth, node); - if (ret) - return ret; - break; - case NODE_POINTER: - print_tabs(fd, depth); - if (node->u.pointer.const_qualifier) - fprintf(fd, "\n"); - else - fprintf(fd, "\n"); - break; - case NODE_TYPE_DECLARATOR: - ret = ctf_visitor_print_type_declarator(fd, depth, node); - if (ret) - return ret; - break; - - case NODE_FLOATING_POINT: - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.floating_point.expressions, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_INTEGER: - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.integer.expressions, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_STRING: - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.string.expressions, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_ENUMERATOR: - print_tabs(fd, depth); - fprintf(fd, "u.enumerator.id) - fprintf(fd, " id=\"%s\"", node->u.enumerator.id); - fprintf(fd, ">\n"); - cds_list_for_each_entry(iter, &node->u.enumerator.values, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_ENUM: - print_tabs(fd, depth); - if (node->u._struct.name) - fprintf(fd, "\n", - node->u._enum.enum_id); - else - fprintf(fd, "\n"); - depth++; - - if (node->u._enum.container_type) { - print_tabs(fd, depth); - fprintf(fd, "\n"); - ret = ctf_visitor_print_xml(fd, depth + 1, node->u._enum.container_type); - if (ret) - return ret; - print_tabs(fd, depth); - fprintf(fd, "\n"); - } - - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u._enum.enumerator_list, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - - depth--; - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_STRUCT_OR_VARIANT_DECLARATION: - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.declaration_specifier, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - - print_tabs(fd, depth); - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.type_declarators, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_VARIANT: - print_tabs(fd, depth); - fprintf(fd, "u.variant.name) - fprintf(fd, " name=\"%s\"", node->u.variant.name); - if (node->u.variant.choice) - fprintf(fd, " choice=\"%s\"", node->u.variant.choice); - fprintf(fd, ">\n"); - cds_list_for_each_entry(iter, &node->u.variant.declaration_list, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_STRUCT: - print_tabs(fd, depth); - if (node->u._struct.name) - fprintf(fd, "\n", - node->u._struct.name); - else - fprintf(fd, "\n"); - cds_list_for_each_entry(iter, &node->u._struct.declaration_list, siblings) { - ret = ctf_visitor_print_xml(fd, depth + 1, iter); - if (ret) - return ret; - } - print_tabs(fd, depth); - fprintf(fd, "\n"); - break; - case NODE_UNKNOWN: default: fprintf(stderr, "[error] %s: unknown node type %d\n", __func__, diff --git a/formats/ctf/types/float.c b/formats/ctf/types/float.c index ee9a8318..72c77912 100644 --- a/formats/ctf/types/float.c +++ b/formats/ctf/types/float.c @@ -111,8 +111,8 @@ double ctf_double_read(struct stream_pos *srcp, const struct declaration_float *float_declaration) { union doubleIEEE754 u; - struct declaration_float *dest_declaration = float_declaration_new(NULL, - DBL_MANT_DIG, + struct declaration_float *dest_declaration = + float_declaration_new(DBL_MANT_DIG, sizeof(double) * CHAR_BIT - DBL_MANT_DIG, BYTE_ORDER, __alignof__(double)); @@ -130,8 +130,8 @@ void ctf_double_write(struct stream_pos *destp, double v) { union doubleIEEE754 u; - struct declaration_float *src_declaration = float_declaration_new(NULL, - DBL_MANT_DIG, + struct declaration_float *src_declaration = + float_declaration_new(DBL_MANT_DIG, sizeof(double) * CHAR_BIT - DBL_MANT_DIG, BYTE_ORDER, __alignof__(double)); @@ -148,8 +148,8 @@ long double ctf_ldouble_read(struct stream_pos *srcp, const struct declaration_float *float_declaration) { union ldoubleIEEE754 u; - struct declaration_float *dest_declaration = float_declaration_new(NULL, - LDBL_MANT_DIG, + struct declaration_float *dest_declaration = + float_declaration_new(LDBL_MANT_DIG, sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG, BYTE_ORDER, __alignof__(long double)); @@ -167,8 +167,8 @@ void ctf_ldouble_write(struct stream_pos *destp, long double v) { union ldoubleIEEE754 u; - struct declaration_float *src_declaration = float_declaration_new(NULL, - LDBL_MANT_DIG, + struct declaration_float *src_declaration = + float_declaration_new(LDBL_MANT_DIG, sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG, BYTE_ORDER, __alignof__(long double)); diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index ad28ac09..37ee9291 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -398,18 +398,14 @@ void declaration_unref(struct declaration *declaration); void definition_ref(struct definition *definition); void definition_unref(struct definition *definition); -/* Nameless declarations can be created by passing a NULL name */ - -struct declaration_integer *integer_declaration_new(const char *name, - size_t len, int byte_order, +struct declaration_integer *integer_declaration_new(size_t len, int byte_order, int signedness, size_t alignment); /* * mantissa_len is the length of the number of bytes represented by the mantissa * (e.g. result of DBL_MANT_DIG). It includes the leading 1. */ -struct declaration_float *float_declaration_new(const char *name, - size_t mantissa_len, +struct declaration_float *float_declaration_new(size_t mantissa_len, size_t exp_len, int byte_order, size_t alignment); diff --git a/types/float.c b/types/float.c index eef123c8..576f8622 100644 --- a/types/float.c +++ b/types/float.c @@ -59,7 +59,7 @@ void _float_declaration_free(struct declaration *declaration) } struct declaration_float * - float_declaration_new(const char *name, size_t mantissa_len, + float_declaration_new(size_t mantissa_len, size_t exp_len, int byte_order, size_t alignment) { struct declaration_float *float_declaration; @@ -68,7 +68,6 @@ struct declaration_float * float_declaration = g_new(struct declaration_float, 1); declaration = &float_declaration->p; declaration->id = CTF_TYPE_FLOAT; - declaration->name = g_quark_from_string(name); declaration->alignment = alignment; declaration->copy = float_copy; declaration->declaration_free = _float_declaration_free; @@ -77,11 +76,11 @@ struct declaration_float * declaration->ref = 1; float_declaration->byte_order = byte_order; - float_declaration->sign = integer_declaration_new(NULL, 1, + float_declaration->sign = integer_declaration_new(1, byte_order, false, 1); - float_declaration->mantissa = integer_declaration_new(NULL, mantissa_len - 1, + float_declaration->mantissa = integer_declaration_new(mantissa_len - 1, byte_order, false, 1); - float_declaration->exp = integer_declaration_new(NULL, exp_len, + float_declaration->exp = integer_declaration_new(exp_len, byte_order, true, 1); return float_declaration; } diff --git a/types/integer.c b/types/integer.c index 928e4960..7b7d22c8 100644 --- a/types/integer.c +++ b/types/integer.c @@ -58,14 +58,13 @@ void _integer_declaration_free(struct declaration *declaration) } struct declaration_integer * - integer_declaration_new(const char *name, size_t len, int byte_order, + integer_declaration_new(size_t len, int byte_order, int signedness, size_t alignment) { struct declaration_integer *integer_declaration; integer_declaration = g_new(struct declaration_integer, 1); integer_declaration->p.id = CTF_TYPE_INTEGER; - integer_declaration->p.name = g_quark_from_string(name); integer_declaration->p.alignment = alignment; integer_declaration->p.copy = integer_copy; integer_declaration->p.declaration_free = _integer_declaration_free; -- 2.34.1 From e0c14875ccc7df4e6a13052f1af19a69b5bc7e16 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Apr 2011 02:55:54 -0400 Subject: [PATCH 09/16] typealias: Fix reduce conflict in grammar for abstract declarators Signed-off-by: Mathieu Desnoyers --- formats/ctf/metadata/ctf-parser.y | 97 ++++++++++++++----------------- 1 file changed, 45 insertions(+), 52 deletions(-) diff --git a/formats/ctf/metadata/ctf-parser.y b/formats/ctf/metadata/ctf-parser.y index 07d98738..1a76c655 100644 --- a/formats/ctf/metadata/ctf-parser.y +++ b/formats/ctf/metadata/ctf-parser.y @@ -814,7 +814,6 @@ void ctf_scanner_free(struct ctf_scanner *scanner) %type alias_declaration_specifiers %type type_declarator_list -%type abstract_type_declarator_list %type type_specifier %type struct_type_specifier %type variant_type_specifier @@ -829,12 +828,13 @@ void ctf_scanner_free(struct ctf_scanner *scanner) %type abstract_declarator_list %type abstract_declarator %type direct_abstract_declarator +%type alias_abstract_declarator_list +%type alias_abstract_declarator +%type direct_alias_abstract_declarator %type declarator %type direct_declarator %type type_declarator %type direct_type_declarator -%type abstract_type_declarator -%type direct_abstract_type_declarator %type pointer %type ctf_assignment_expression_list %type ctf_assignment_expression @@ -1116,7 +1116,7 @@ declaration: _cds_list_splice_tail(&($1)->tmp_head, &($$)->u._typedef.declaration_specifier); _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._typedef.type_declarators); } - | TYPEALIAS declaration_specifiers abstract_declarator_list COLON alias_declaration_specifiers abstract_type_declarator_list SEMICOLON + | TYPEALIAS declaration_specifiers abstract_declarator_list COLON alias_declaration_specifiers alias_abstract_declarator_list SEMICOLON { $$ = make_node(scanner, NODE_TYPEALIAS); $$->u.typealias.target = make_node(scanner, NODE_TYPEALIAS_TARGET); @@ -1233,16 +1233,6 @@ type_declarator_list: } ; -abstract_type_declarator_list: - abstract_type_declarator - { $$ = $1; } - | abstract_type_declarator_list COMMA abstract_type_declarator - { - $$ = $1; - cds_list_add_tail(&($3)->siblings, &($$)->tmp_head); - } - ; - type_specifier: VOID { @@ -1694,7 +1684,7 @@ struct_or_variant_declaration: _cds_list_splice_tail(&($1)->tmp_head, &($$)->u._typedef.declaration_specifier); _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._typedef.type_declarators); } - | TYPEALIAS declaration_specifiers abstract_declarator_list COLON alias_declaration_specifiers abstract_type_declarator_list SEMICOLON + | TYPEALIAS declaration_specifiers abstract_declarator_list COLON alias_declaration_specifiers alias_abstract_declarator_list SEMICOLON { $$ = make_node(scanner, NODE_TYPEALIAS); $$->u.typealias.target = make_node(scanner, NODE_TYPEALIAS_TARGET); @@ -1894,63 +1884,79 @@ direct_abstract_declarator: } ; -declarator: - direct_declarator +alias_abstract_declarator_list: + alias_abstract_declarator { $$ = $1; } - | pointer direct_declarator + | alias_abstract_declarator_list COMMA alias_abstract_declarator + { + $$ = $1; + cds_list_add_tail(&($3)->siblings, &($$)->tmp_head); + } + ; + +alias_abstract_declarator: + direct_alias_abstract_declarator + { $$ = $1; } + | pointer direct_alias_abstract_declarator { $$ = $2; cds_list_splice(&($1)->tmp_head, &($$)->u.type_declarator.pointers); } ; -direct_declarator: - IDENTIFIER +direct_alias_abstract_declarator: + /* empty */ { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); - $$->u.type_declarator.type = TYPEDEC_ID; - $$->u.type_declarator.u.id = $1->s; + $$->u.type_declarator.type = TYPEDEC_ID; + /* id is NULL */ } - | LPAREN declarator RPAREN + | LPAREN alias_abstract_declarator RPAREN { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_declarator LSBRAC type_specifier_or_integer_constant RSBRAC + | direct_alias_abstract_declarator LSBRAC type_specifier_or_integer_constant RSBRAC { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $1; $$->u.type_declarator.u.nested.length = $3; } + | direct_alias_abstract_declarator LSBRAC RSBRAC + { + $$ = make_node(scanner, NODE_TYPE_DECLARATOR); + $$->u.type_declarator.type = TYPEDEC_NESTED; + $$->u.type_declarator.u.nested.type_declarator = $1; + $$->u.type_declarator.u.nested.abstract_array = 1; + } ; -type_declarator: - direct_type_declarator +declarator: + direct_declarator { $$ = $1; } - | pointer direct_type_declarator + | pointer direct_declarator { $$ = $2; cds_list_splice(&($1)->tmp_head, &($$)->u.type_declarator.pointers); } ; -direct_type_declarator: +direct_declarator: IDENTIFIER { - add_type(scanner, $1); $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_ID; $$->u.type_declarator.u.id = $1->s; } - | LPAREN type_declarator RPAREN + | LPAREN declarator RPAREN { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_type_declarator LSBRAC type_specifier_or_integer_constant RSBRAC + | direct_declarator LSBRAC type_specifier_or_integer_constant RSBRAC { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; @@ -1959,50 +1965,37 @@ direct_type_declarator: } ; -abstract_type_declarator: - direct_abstract_type_declarator +type_declarator: + direct_type_declarator { $$ = $1; } - | pointer direct_abstract_type_declarator + | pointer direct_type_declarator { $$ = $2; cds_list_splice(&($1)->tmp_head, &($$)->u.type_declarator.pointers); } ; -direct_abstract_type_declarator: - /* empty */ - { - $$ = make_node(scanner, NODE_TYPE_DECLARATOR); - $$->u.type_declarator.type = TYPEDEC_ID; - /* id is NULL */ - } - | IDENTIFIER +direct_type_declarator: + IDENTIFIER { add_type(scanner, $1); $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_ID; $$->u.type_declarator.u.id = $1->s; } - | LPAREN abstract_type_declarator RPAREN + | LPAREN type_declarator RPAREN { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_abstract_type_declarator LSBRAC type_specifier_or_integer_constant RSBRAC + | direct_type_declarator LSBRAC type_specifier_or_integer_constant RSBRAC { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $1; $$->u.type_declarator.u.nested.length = $3; } - | direct_abstract_type_declarator LSBRAC RSBRAC - { - $$ = make_node(scanner, NODE_TYPE_DECLARATOR); - $$->u.type_declarator.type = TYPEDEC_NESTED; - $$->u.type_declarator.u.nested.type_declarator = $1; - $$->u.type_declarator.u.nested.abstract_array = 1; - } ; pointer: @@ -2086,7 +2079,7 @@ ctf_assignment_expression: _cds_list_splice_tail(&($1)->tmp_head, &($$)->u._typedef.declaration_specifier); _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._typedef.type_declarators); } - | TYPEALIAS declaration_specifiers abstract_declarator_list COLON alias_declaration_specifiers abstract_type_declarator_list + | TYPEALIAS declaration_specifiers abstract_declarator_list COLON alias_declaration_specifiers alias_abstract_declarator_list { $$ = make_node(scanner, NODE_TYPEALIAS); $$->u.typealias.target = make_node(scanner, NODE_TYPEALIAS_TARGET); -- 2.34.1 From ab4cf05887a402e53396db43b5958918d0d2d022 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Apr 2011 12:41:16 -0400 Subject: [PATCH 10/16] Remove unneeded declaration "name", work in progress for gen io struct Signed-off-by: Mathieu Desnoyers --- formats/ctf/metadata/ctf-ast.h | 4 + .../metadata/ctf-visitor-generate-io-struct.c | 264 ++++++++++++++++-- include/babeltrace/ctf/metadata.h | 1 + include/babeltrace/types.h | 22 +- types/array.c | 3 +- types/enum.c | 3 +- types/sequence.c | 3 +- types/string.c | 5 +- types/struct.c | 5 +- types/variant.c | 5 +- 10 files changed, 264 insertions(+), 51 deletions(-) diff --git a/formats/ctf/metadata/ctf-ast.h b/formats/ctf/metadata/ctf-ast.h index 8a2888da..6ee937b6 100644 --- a/formats/ctf/metadata/ctf-ast.h +++ b/formats/ctf/metadata/ctf-ast.h @@ -235,8 +235,12 @@ struct ctf_ast { const char *node_type(struct ctf_node *node); +struct ctf_trace; + int ctf_visitor_print_xml(FILE *fd, int depth, struct ctf_node *node); int ctf_visitor_semantic_check(FILE *fd, int depth, struct ctf_node *node); int ctf_visitor_parent_links(FILE *fd, int depth, struct ctf_node *node); +int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node, + struct ctf_trace *trace, int byte_order); #endif /* _CTF_PARSER_H */ diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index fd6176fe..bd0a845f 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -39,7 +39,8 @@ static struct declaration *ctf_declaration_specifier_visit(FILE *fd, int depth, struct cds_list_head *head, - struct declaration_scope *declaration_scope); + struct declaration_scope *declaration_scope, + struct ctf_trace *trace); /* * String returned must be freed by the caller using g_free. @@ -731,12 +732,86 @@ struct declaration *ctf_declaration_type_specifier_visit(int fd, int depth, return declaration; } +/* + * Returns 0/1 boolean, or < 0 on error. + */ +static +int get_boolean(int fd, int depth, struct node *unary_expression) +{ + if (unary_expression->type != NODE_UNARY_EXPRESSION) { + fprintf(stderr, "[error] %s: expecting unary expression\n", + __func__); + return -EINVAL; + } + switch (unary_expression->u.unary_expression.type) { + case UNARY_UNSIGNED_CONSTANT: + if (unary_expression->u.unary_expression.u.unsigned_constant == 0) + return 0; + else + return 1; + case UNARY_SIGNED_CONSTANT: + if (unary_expression->u.unary_expression.u.signed_constant == 0) + return 0; + else + return 1; + case UNARY_STRING: + if (!strcmp(unary_expression->u.unary_expression.u.string, "true")) + return 1; + else if (!strcmp(unary_expression->u.unary_expression.u.string, "TRUE")) + return 1; + else if (!strcmp(unary_expression->u.unary_expression.u.string, "false")) + return 0; + else if (!strcmp(unary_expression->u.unary_expression.u.string, "FALSE")) + return 0; + else { + fprintf(stderr, "[error] %s: unexpected string \"%s\"\n", + __func__, unary_expression->u.unary_expression.u.string); + return -EINVAL; + } + break; + default: + fprintf(stderr, "[error] %s: unexpected unary expression type\n", + __func__); + return -EINVAL; + } + +} + +static +int get_byte_order(int fd, int depth, struct node *unary_expression) +{ + int byte_order; + + if (unary_expression->u.unary_expression.type != UNARY_STRING) { + fprintf(stderr, "[error] %s: byte_order: expecting string\n", + __func__); + return -EINVAL; + } + if (!strcmp(unary_expression->u.unary_expression.u.string, "native")) + byte_order = trace->byte_order; + else if (!strcmp(unary_expression->u.unary_expression.u.string, "network")) + byte_order = BIG_ENDIAN; + else if (!strcmp(unary_expression->u.unary_expression.u.string, "be")) + byte_order = BIG_ENDIAN; + else if (!strcmp(unary_expression->u.unary_expression.u.string, "le")) + byte_order = LITTLE_ENDIAN; + else { + fprintf(stderr, "[error] %s: unexpected string \"%s\". Should be \"native\", \"network\", \"be\" or \"le\".\n", + __func__, right->u.unary_expression.u.string); + return -EINVAL; + } + return byte_order; +} + static struct declaration *ctf_declaration_integer_visit(int fd, int depth, - struct cds_list_head *expressions) + struct cds_list_head *expressions, + struct ctf_trace *trace) { struct node *expression; - uint64_t alignment, size, byte_order = trace->native_bo, signedness = 0; + uint64_t alignment, size; + int byte_order = trace->byte_order; + int signedness = 0; int has_alignment = 0, has_size = 0; struct declaration_integer *integer_declaration; @@ -747,13 +822,28 @@ struct declaration *ctf_declaration_integer_visit(int fd, int depth, right = expression->u.ctf_expression.right; assert(left->u.unary_expression.type == UNARY_STRING); if (!strcmp(left->u.unary_expression.u.string, "signed")) { - /* TODO */ - ........... + signedness = get_boolean(fd, depth, right); + if (signedness < 0) + return NULL; } else if (!strcmp(left->u.unary_expression.u.string, "byte_order")) { - + byte_order = get_byte_order(fd, depth, right); + if (byte_order < 0) + return NULL; } else if (!strcmp(left->u.unary_expression.u.string, "size")) { + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + fprintf(stderr, "[error] %s: size: expecting unsigned constant\n", + __func__); + return NULL; + } + size = right->u.unary_expression.u.unsigned_constant; has_size = 1; } else if (!strcmp(left->u.unary_expression.u.string, "align")) { + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + fprintf(stderr, "[error] %s: align: expecting unsigned constant\n", + __func__); + return NULL; + } + alignment = right->u.unary_expression.u.unsigned_constant; has_alignment = 1; } else { fprintf(stderr, "[error] %s: unknown attribute name %s\n", @@ -761,26 +851,140 @@ struct declaration *ctf_declaration_integer_visit(int fd, int depth, return NULL; } } - if (!has_alignment) { - fprintf(stderr, "[error] %s: missing alignment attribute\n", __func__); - return NULL; - } if (!has_size) { fprintf(stderr, "[error] %s: missing size attribute\n", __func__); return NULL; } + if (!has_alignment) { + if (size % CHAR_BIT) { + /* bit-packed alignment */ + alignment = 1; + } else { + /* byte-packed alignment */ + alignment = CHAR_BIT; + } + } integer_declaration = integer_declaration_new(size, byte_order, signedness, alignment); return &integer_declaration->p; } +static +struct declaration *ctf_declaration_floating_point_visit(int fd, int depth, + struct cds_list_head *expressions, + struct ctf_trace *trace) +{ + struct node *expression; + uint64_t alignment, exp_dig, mant_dig, byte_order = trace->byte_order; + int has_alignment = 0, has_exp_dig = 0, has_mant_dig = 0; + struct declaration_float *float_declaration; + + cds_list_for_each_entry(expression, expressions, siblings) { + struct node *left, *right; + + left = expression->u.ctf_expression.left; + right = expression->u.ctf_expression.right; + assert(left->u.unary_expression.type == UNARY_STRING); + if (!strcmp(left->u.unary_expression.u.string, "byte_order")) { + byte_order = get_byte_order(fd, depth, right); + if (byte_order < 0) + return NULL; + } else if (!strcmp(left->u.unary_expression.u.string, "exp_dig")) { + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + fprintf(stderr, "[error] %s: exp_dig: expecting unsigned constant\n", + __func__); + return NULL; + } + exp_dig = right->u.unary_expression.u.unsigned_constant; + has_exp_dig = 1; + } else if (!strcmp(left->u.unary_expression.u.string, "mant_dig")) { + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + fprintf(stderr, "[error] %s: mant_dig: expecting unsigned constant\n", + __func__); + return NULL; + } + mant_dig = right->u.unary_expression.u.unsigned_constant; + has_mant_dig = 1; + } else if (!strcmp(left->u.unary_expression.u.string, "align")) { + if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + fprintf(stderr, "[error] %s: align: expecting unsigned constant\n", + __func__); + return NULL; + } + alignment = right->u.unary_expression.u.unsigned_constant; + has_alignment = 1; + } else { + fprintf(stderr, "[error] %s: unknown attribute name %s\n", + __func__, left->u.unary_expression.u.string); + return NULL; + } + } + if (!has_mant_dig) { + fprintf(stderr, "[error] %s: missing mant_dig attribute\n", __func__); + return NULL; + } + if (!has_exp_dig) { + fprintf(stderr, "[error] %s: missing exp_dig attribute\n", __func__); + return NULL; + } + if (!has_alignment) { + if ((mant_dig + exp_dig) % CHAR_BIT) { + /* bit-packed alignment */ + alignment = 1; + } else { + /* byte-packed alignment */ + alignment = CHAR_BIT; + } + } + float_declaration = float_declaration_new(mant_dig, exp_dig, + byte_order, alignment); + return &float_declaration->p; +} + +static +struct declaration *ctf_declaration_string_visit(int fd, int depth, + struct cds_list_head *expressions, + struct ctf_trace *trace) +{ + struct node *expression; + const char *encoding_c = NULL; + enum ctf_string_encoding encoding = CTF_STRING_UTF8; + struct declaration_string *string_declaration; + + cds_list_for_each_entry(expression, expressions, siblings) { + struct node *left, *right; + + left = expression->u.ctf_expression.left; + right = expression->u.ctf_expression.right; + assert(left->u.unary_expression.type == UNARY_STRING); + if (!strcmp(left->u.unary_expression.u.string, "encoding")) { + if (right->u.unary_expression.type != UNARY_UNSIGNED_STRING) { + fprintf(stderr, "[error] %s: encoding: expecting string\n", + __func__); + return NULL; + } + encoding_c = right->u.unary_expression.u.string; + } else { + fprintf(stderr, "[error] %s: unknown attribute name %s\n", + __func__, left->u.unary_expression.u.string); + return NULL; + } + } + if (encoding_c && !strcmp(encoding_c, "ASCII")) + encoding = CTF_STRING_ASCII; + string_declaration = string_declaration_new(encoding); + return &string_declaration->p; +} + + /* * Also add named variant, struct or enum to the current declaration scope. */ static struct declaration *ctf_declaration_specifier_visit(FILE *fd, int depth, struct cds_list_head *head, - struct declaration_scope *declaration_scope) + struct declaration_scope *declaration_scope, + struct ctf_trace *trace) { struct declaration *declaration; struct node *first; @@ -793,31 +997,34 @@ struct declaration *ctf_declaration_specifier_visit(FILE *fd, first->u._struct.name, &first->u._struct.declaration_list, first->u._struct.has_body, - declaration_scope); + declaration_scope, + trace); case NODE_VARIANT: return ctf_declaration_variant_visit(fd, depth, first->u.variant.name, &first->u.variant.declaration_list, first->u.variant.has_body, - declaration_scope); + declaration_scope, + trace); case NODE_ENUM: return ctf_declaration_enum_visit(fd, depth, first->u._enum.enum_id, first->u._enum.container_type, &first->u._enum.enumerator_list, - first->u._enum.has_body); + first->u._enum.has_body, + trace); case NODE_INTEGER: return ctf_declaration_integer_visit(fd, depth, - &first->u.integer.expressions); - case NODE_FLOATING_POINT: /* TODO */ + &first->u.integer.expressions, trace); + case NODE_FLOATING_POINT: return ctf_declaration_floating_point_visit(fd, depth, - &first->u.floating_point.expressions); - case NODE_STRING: /* TODO */ + &first->u.floating_point.expressions, trace); + case NODE_STRING: return ctf_declaration_string_visit(fd, depth, - &first->u.string.expressions); + &first->u.string.expressions, trace); case NODE_TYPE_SPECIFIER: return ctf_declaration_type_specifier_visit(fd, depth, - head, declaration_scope); + head, declaration_scope, trace); } } @@ -890,7 +1097,7 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return -EPERM; declaration = ctf_declaration_specifier_visit(fd, depth, &node->u.ctf_expression.right, - event->declaration_scope); + event->declaration_scope, trace); if (!declaration) return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) @@ -903,7 +1110,7 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return -EPERM; declaration = ctf_declaration_specifier_visit(fd, depth, &node->u.ctf_expression.right, - event->declaration_scope); + event->declaration_scope, trace); if (!declaration) return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) @@ -1028,7 +1235,7 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str declaration = ctf_declaration_specifier_visit(fd, depth, &node->u.ctf_expression.right, - stream->declaration_scope, stream->definition_scope); + stream->declaration_scope, stream->definition_scope, trace); if (!declaration) return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) @@ -1039,7 +1246,7 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str declaration = ctf_declaration_specifier_visit(fd, depth, &node->u.ctf_expression.right, - stream->declaration_scope); + stream->declaration_scope, trace); if (!declaration) return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) @@ -1050,7 +1257,7 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str declaration = ctf_declaration_specifier_visit(fd, depth, &node->u.ctf_expression.right, - stream->declaration_scope); + stream->declaration_scope, trace); if (!declaration) return -EPERM; if (declaration->type->id != CTF_TYPE_STRUCT) @@ -1256,11 +1463,14 @@ error: return ret; } -int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace) +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; + trace->byte_order = byte_order; + switch (node->type) { case NODE_ROOT: cds_list_for_each_entry(iter, &node->u.root._typedef, @@ -1282,7 +1492,7 @@ int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *t } cds_list_for_each_entry(iter, &node->u.root.declaration_specifier, siblings) { ret = ctf_declaration_specifier_visit(fd, depth, iter, - trace->root_declaration_scope); + trace->root_declaration_scope, trace); if (ret) return ret; } diff --git a/include/babeltrace/ctf/metadata.h b/include/babeltrace/ctf/metadata.h index d98a2630..6c17b410 100644 --- a/include/babeltrace/ctf/metadata.h +++ b/include/babeltrace/ctf/metadata.h @@ -55,6 +55,7 @@ struct ctf_trace { uint64_t minor; uuid_t uuid; uint64_t word_size; + int byte_order; enum { /* Fields populated mask */ CTF_TRACE_major = (1U << 0), diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 37ee9291..bfc69870 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -133,7 +133,6 @@ enum ctf_type_id { struct declaration { enum ctf_type_id id; - GQuark name; /* type name */ size_t alignment; /* type alignment, in bits */ int ref; /* number of references to the type */ /* @@ -253,8 +252,15 @@ struct definition_enum { GArray *value; }; +enum ctf_string_encoding { + CTF_STRING_UTF8 = 0, + CTF_STRING_ASCII, + CTF_STRING_UNKNOWN, +}; + struct declaration_string { struct declaration p; + enum ctf_string_encoding encoding; }; struct definition_string { @@ -442,12 +448,10 @@ void enum_unsigned_insert(struct declaration_enum *enum_declaration, size_t enum_get_nr_enumerators(struct declaration_enum *enum_declaration); struct declaration_enum * - enum_declaration_new(const char *name, - struct declaration_integer *integer_declaration); + enum_declaration_new(struct declaration_integer *integer_declaration); struct declaration_struct * - struct_declaration_new(const char *name, - struct declaration_scope *parent_scope); + struct_declaration_new(struct declaration_scope *parent_scope); void struct_declaration_add_field(struct declaration_struct *struct_declaration, const char *field_name, struct declaration *field_declaration); @@ -471,7 +475,7 @@ struct_get_field_from_index(struct definition_struct *struct_definition, * from numeric values to a single tag. Overlapping tag value ranges are * therefore forbidden. */ -struct declaration_untagged_variant *untagged_variant_declaration_new(const char *name, +struct declaration_untagged_variant *untagged_variant_declaration_new( struct declaration_scope *parent_scope); struct declaration_variant *variant_declaration_new(struct declaration_untagged_variant *untagged_variant, const char *tag); @@ -500,8 +504,7 @@ struct field *variant_get_current_field(struct definition_variant *variant); * array. */ struct declaration_array * - array_declaration_new(const char *name, - size_t len, struct declaration *elem_declaration, + array_declaration_new(size_t len, struct declaration *elem_declaration, struct declaration_scope *parent_scope); /* @@ -509,8 +512,7 @@ struct declaration_array * * to the sequence. No need to free them explicitly. */ struct declaration_sequence * - sequence_declaration_new(const char *name, - struct declaration_integer *len_declaration, + sequence_declaration_new(struct declaration_integer *len_declaration, struct declaration *elem_declaration, struct declaration_scope *parent_scope); diff --git a/types/array.c b/types/array.c index 3e1f2181..c218a11a 100644 --- a/types/array.c +++ b/types/array.c @@ -58,7 +58,7 @@ void _array_declaration_free(struct declaration *declaration) } struct declaration_array * - array_declaration_new(const char *name, size_t len, + array_declaration_new(size_t len, struct declaration *elem_declaration, struct declaration_scope *parent_scope) { @@ -72,7 +72,6 @@ struct declaration_array * array_declaration->elem = elem_declaration; array_declaration->scope = new_declaration_scope(parent_scope); declaration->id = CTF_TYPE_ARRAY; - declaration->name = g_quark_from_string(name); /* No need to align the array, the first element will align itself */ declaration->alignment = 1; declaration->copy = array_copy; diff --git a/types/enum.c b/types/enum.c index 36e310b0..3f7d46bd 100644 --- a/types/enum.c +++ b/types/enum.c @@ -392,7 +392,7 @@ void _enum_declaration_free(struct declaration *declaration) } struct declaration_enum * - _enum_declaration_new(const char *name, struct declaration_integer *integer_declaration) + _enum_declaration_new(struct declaration_integer *integer_declaration) { struct declaration_enum *enum_declaration; @@ -409,7 +409,6 @@ struct declaration_enum * declaration_ref(&integer_declaration->p); enum_declaration->integer_declaration = integer_declaration; enum_declaration->p.id = CTF_TYPE_ENUM; - enum_declaration->p.name = g_quark_from_string(name); enum_declaration->p.alignment = 1; enum_declaration->p.copy = enum_copy; enum_declaration->p.declaration_free = _enum_declaration_free; diff --git a/types/sequence.c b/types/sequence.c index 2f6a7f18..a719ee99 100644 --- a/types/sequence.c +++ b/types/sequence.c @@ -67,7 +67,7 @@ void _sequence_declaration_free(struct declaration *declaration) } struct declaration_sequence * - sequence_declaration_new(const char *name, struct declaration_integer *len_declaration, + sequence_declaration_new(struct declaration_integer *len_declaration, struct declaration *elem_declaration, struct declaration_scope *parent_scope) { @@ -83,7 +83,6 @@ struct declaration_sequence * sequence_declaration->elem = elem_declaration; sequence_declaration->scope = new_declaration_scope(parent_scope); declaration->id = CTF_TYPE_SEQUENCE; - declaration->name = g_quark_from_string(name); declaration->alignment = max(len_declaration->p.alignment, elem_declaration->alignment); declaration->copy = sequence_copy; declaration->declaration_free = _sequence_declaration_free; diff --git a/types/string.c b/types/string.c index 41ac7576..f8778c84 100644 --- a/types/string.c +++ b/types/string.c @@ -54,19 +54,20 @@ void _string_declaration_free(struct declaration *declaration) g_free(string_declaration); } -struct declaration_string *string_declaration_new(const char *name) +struct declaration_string * + string_declaration_new(enum ctf_string_encoding encoding) { struct declaration_string *string_declaration; string_declaration = g_new(struct declaration_string, 1); string_declaration->p.id = CTF_TYPE_STRING; - string_declaration->p.name = g_quark_from_string(name); string_declaration->p.alignment = CHAR_BIT; string_declaration->p.copy = string_copy; string_declaration->p.declaration_free = _string_declaration_free; string_declaration->p.definition_new = _string_definition_new; string_declaration->p.definition_free = _string_definition_free; string_declaration->p.ref = 1; + string_declaration->encoding = encoding; return string_declaration; } diff --git a/types/struct.c b/types/struct.c index 21465c73..69e3a553 100644 --- a/types/struct.c +++ b/types/struct.c @@ -74,8 +74,8 @@ void _struct_declaration_free(struct declaration *declaration) g_free(struct_declaration); } -struct declaration_struct *struct_declaration_new(const char *name, - struct declaration_scope *parent_scope) +struct declaration_struct * + struct_declaration_new(struct declaration_scope *parent_scope) { struct declaration_struct *struct_declaration; struct declaration *declaration; @@ -89,7 +89,6 @@ struct declaration_struct *struct_declaration_new(const char *name, DEFAULT_NR_STRUCT_FIELDS); struct_declaration->scope = new_declaration_scope(parent_scope); declaration->id = CTF_TYPE_STRUCT; - declaration->name = g_quark_from_string(name); declaration->alignment = 1; declaration->copy = struct_copy; declaration->declaration_free = _struct_declaration_free; diff --git a/types/variant.c b/types/variant.c index 2ab14a21..a61d895c 100644 --- a/types/variant.c +++ b/types/variant.c @@ -1,5 +1,5 @@ /* -* variant.c + * variant.c * * BabelTrace - Variant Type Converter * @@ -68,7 +68,7 @@ void _untagged_variant_declaration_free(struct declaration *declaration) g_free(untagged_variant_declaration); } -struct declaration_untagged_variant *untagged_variant_declaration_new(const char *name, +struct declaration_untagged_variant *untagged_variant_declaration_new( struct declaration_scope *parent_scope) { struct declaration_untagged_variant *untagged_variant_declaration; @@ -83,7 +83,6 @@ struct declaration_untagged_variant *untagged_variant_declaration_new(const char DEFAULT_NR_STRUCT_FIELDS); untagged_variant_declaration->scope = new_declaration_scope(parent_scope); declaration->id = CTF_TYPE_UNTAGGED_VARIANT; - declaration->name = g_quark_from_string(name); declaration->alignment = 1; declaration->copy = NULL; declaration->declaration_free = _untagged_variant_declaration_free; -- 2.34.1 From ce8e64d57ff78a35328d89a4c79c739be22bad7d Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Apr 2011 12:52:39 -0400 Subject: [PATCH 11/16] Update readme for uuid dep. Signed-off-by: Mathieu Desnoyers --- README | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README b/README index 85382786..0310f092 100644 --- a/README +++ b/README @@ -27,6 +27,9 @@ To compile Babeltrace, you will need: libc6 development librairies (Debian : libc6, libc6-dev) (Fedora : glibc, glibc) + uuid development libraries + (Debian : uuid-dev) + (Fedora : uuid-devel) For developers using the git tree: -- 2.34.1 From fd55fc57942d179105ddda100a5341f9aacdf5c0 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Apr 2011 12:57:09 -0400 Subject: [PATCH 12/16] Add uuid test to configure.ac Signed-off-by: Mathieu Desnoyers --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 42bfc79e..64cea932 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,11 @@ AC_FUNC_MALLOC AC_FUNC_MMAP AC_CHECK_FUNCS([bzero gettimeofday munmap strtoul]) +# Check libuuid +AC_CHECK_LIB([uuid], [uuid_generate], [], + [AC_MSG_ERROR([Cannot find libuuid. Use [LDFLAGS]=-Ldir to specify its location.])] +) + pkg_modules="gmodule-2.0 >= 2.0.0" PKG_CHECK_MODULES(GMODULE, [$pkg_modules]) AC_SUBST(PACKAGE_LIBS) -- 2.34.1 From 7d4192cb80178ad534e460d56f67e55679c7d8ee Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Apr 2011 14:23:02 -0400 Subject: [PATCH 13/16] enum, sequence, array: use declaration list for length/container type Signed-off-by: Mathieu Desnoyers --- formats/ctf/metadata/ctf-ast.h | 14 +++-- formats/ctf/metadata/ctf-parser.y | 62 ++++++++++--------- .../ctf/metadata/ctf-visitor-parent-links.c | 15 ++--- .../metadata/ctf-visitor-semantic-validator.c | 18 ++++-- formats/ctf/metadata/ctf-visitor-xml.c | 20 ++++-- 5 files changed, 81 insertions(+), 48 deletions(-) diff --git a/formats/ctf/metadata/ctf-ast.h b/formats/ctf/metadata/ctf-ast.h index 6ee937b6..c12d09a9 100644 --- a/formats/ctf/metadata/ctf-ast.h +++ b/formats/ctf/metadata/ctf-ast.h @@ -173,8 +173,11 @@ struct ctf_node { struct { /* typedec has no pointer list */ struct ctf_node *type_declarator; - /* value or first node of declaration specifier list */ - struct ctf_node *length; + /* + * unary expression (value) or + * declaration specifiers. + */ + struct cds_list_head length; /* for abstract type declarator */ unsigned int abstract_array; } nested; @@ -203,8 +206,11 @@ struct ctf_node { } enumerator; struct { char *enum_id; - /* NULL, value or declaration specifier */ - struct ctf_node *container_type; + /* + * Either empty, contains unary expression or + * declaration specifiers. + */ + struct cds_list_head container_type; struct cds_list_head enumerator_list; int has_body; } _enum; diff --git a/formats/ctf/metadata/ctf-parser.y b/formats/ctf/metadata/ctf-parser.y index 1a76c655..cdcfdcdb 100644 --- a/formats/ctf/metadata/ctf-parser.y +++ b/formats/ctf/metadata/ctf-parser.y @@ -292,6 +292,7 @@ static struct ctf_node *make_node(struct ctf_scanner *scanner, CDS_INIT_LIST_HEAD(&node->u.enumerator.values); break; case NODE_ENUM: + CDS_INIT_LIST_HEAD(&node->u._enum.container_type); CDS_INIT_LIST_HEAD(&node->u._enum.enumerator_list); break; case NODE_STRUCT_OR_VARIANT_DECLARATION: @@ -493,10 +494,11 @@ static int reparent_type_specifier(struct ctf_node *node, break; case NODE_TYPE_DECLARATOR: parent->u.type_declarator.type = TYPEDEC_NESTED; - parent->u.type_declarator.u.nested.length = node; + CDS_INIT_LIST_HEAD(&parent->u.type_declarator.u.nested.length); + _cds_list_splice_tail(&node->tmp_head, &parent->u.type_declarator.u.nested.length); break; case NODE_ENUM: - parent->u._enum.container_type = node; + _cds_list_splice_tail(&node->tmp_head, &parent->u._enum.container_type); break; case NODE_STRUCT_OR_VARIANT_DECLARATION: _cds_list_splice_tail(&node->tmp_head, &parent->u.struct_or_variant_declaration.declaration_specifier); @@ -817,7 +819,7 @@ void ctf_scanner_free(struct ctf_scanner *scanner) %type type_specifier %type struct_type_specifier %type variant_type_specifier -%type type_specifier_or_integer_constant +%type declaration_specifiers_or_integer_constant %type enum_type_specifier %type struct_or_variant_declaration_list %type struct_or_variant_declaration @@ -1502,7 +1504,7 @@ variant_declaration_end: { pop_scope(scanner); } ; -type_specifier_or_integer_constant: +declaration_specifiers_or_integer_constant: declaration_specifiers { $$ = $1; } | DECIMAL_CONSTANT @@ -1535,11 +1537,11 @@ enum_type_specifier: $$->u._enum.has_body = 1; _cds_list_splice_tail(&($2)->tmp_head, &($$)->u._enum.enumerator_list); } - | LT type_specifier_or_integer_constant GT LBRAC enumerator_list RBRAC + | LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; - $$->u._enum.container_type = $2; + _cds_list_splice_tail(&($2)->tmp_head, &($$)->u._enum.container_type); _cds_list_splice_tail(&($5)->tmp_head, &($$)->u._enum.enumerator_list); } | IDENTIFIER LBRAC enumerator_list RBRAC @@ -1549,12 +1551,12 @@ enum_type_specifier: $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } - | IDENTIFIER LT type_specifier_or_integer_constant GT LBRAC enumerator_list RBRAC + | IDENTIFIER LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; - $$->u._enum.container_type = $3; + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.container_type); _cds_list_splice_tail(&($6)->tmp_head, &($$)->u._enum.enumerator_list); } | ID_TYPE LBRAC enumerator_list RBRAC @@ -1564,12 +1566,12 @@ enum_type_specifier: $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } - | ID_TYPE LT type_specifier_or_integer_constant GT LBRAC enumerator_list RBRAC + | ID_TYPE LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; - $$->u._enum.container_type = $3; + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.container_type); _cds_list_splice_tail(&($6)->tmp_head, &($$)->u._enum.enumerator_list); } | LBRAC enumerator_list COMMA RBRAC @@ -1578,11 +1580,11 @@ enum_type_specifier: $$->u._enum.has_body = 1; _cds_list_splice_tail(&($2)->tmp_head, &($$)->u._enum.enumerator_list); } - | LT type_specifier_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC + | LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; - $$->u._enum.container_type = $2; + _cds_list_splice_tail(&($2)->tmp_head, &($$)->u._enum.container_type); _cds_list_splice_tail(&($5)->tmp_head, &($$)->u._enum.enumerator_list); } | IDENTIFIER LBRAC enumerator_list COMMA RBRAC @@ -1592,12 +1594,12 @@ enum_type_specifier: $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } - | IDENTIFIER LT type_specifier_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC + | IDENTIFIER LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; - $$->u._enum.container_type = $3; + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.container_type); _cds_list_splice_tail(&($6)->tmp_head, &($$)->u._enum.enumerator_list); } | IDENTIFIER @@ -1606,12 +1608,12 @@ enum_type_specifier: $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; } - | IDENTIFIER LT type_specifier_or_integer_constant GT + | IDENTIFIER LT declaration_specifiers_or_integer_constant GT { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; - $$->u._enum.container_type = $3; + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.container_type); } | ID_TYPE LBRAC enumerator_list COMMA RBRAC { @@ -1620,12 +1622,12 @@ enum_type_specifier: $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } - | ID_TYPE LT type_specifier_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC + | ID_TYPE LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; $$->u._enum.enum_id = $1->s; - $$->u._enum.container_type = $3; + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.container_type); _cds_list_splice_tail(&($6)->tmp_head, &($$)->u._enum.enumerator_list); } | ID_TYPE @@ -1634,12 +1636,12 @@ enum_type_specifier: $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; } - | ID_TYPE LT type_specifier_or_integer_constant GT + | ID_TYPE LT declaration_specifiers_or_integer_constant GT { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; - $$->u._enum.container_type = $3; + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.container_type); } ; @@ -1868,12 +1870,13 @@ direct_abstract_declarator: $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_abstract_declarator LSBRAC type_specifier_or_integer_constant RSBRAC + | direct_abstract_declarator LSBRAC declaration_specifiers_or_integer_constant RSBRAC { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $1; - $$->u.type_declarator.u.nested.length = $3; + CDS_INIT_LIST_HEAD(&($$)->u.type_declarator.u.nested.length); + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u.type_declarator.u.nested.length); } | direct_abstract_declarator LSBRAC RSBRAC { @@ -1917,12 +1920,13 @@ direct_alias_abstract_declarator: $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_alias_abstract_declarator LSBRAC type_specifier_or_integer_constant RSBRAC + | direct_alias_abstract_declarator LSBRAC declaration_specifiers_or_integer_constant RSBRAC { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $1; - $$->u.type_declarator.u.nested.length = $3; + CDS_INIT_LIST_HEAD(&($$)->u.type_declarator.u.nested.length); + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u.type_declarator.u.nested.length); } | direct_alias_abstract_declarator LSBRAC RSBRAC { @@ -1956,12 +1960,13 @@ direct_declarator: $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_declarator LSBRAC type_specifier_or_integer_constant RSBRAC + | direct_declarator LSBRAC declaration_specifiers_or_integer_constant RSBRAC { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $1; - $$->u.type_declarator.u.nested.length = $3; + CDS_INIT_LIST_HEAD(&($$)->u.type_declarator.u.nested.length); + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u.type_declarator.u.nested.length); } ; @@ -1989,12 +1994,13 @@ direct_type_declarator: $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_type_declarator LSBRAC type_specifier_or_integer_constant RSBRAC + | direct_type_declarator LSBRAC declaration_specifiers_or_integer_constant RSBRAC { $$ = make_node(scanner, NODE_TYPE_DECLARATOR); $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $1; - $$->u.type_declarator.u.nested.length = $3; + CDS_INIT_LIST_HEAD(&($$)->u.type_declarator.u.nested.length); + _cds_list_splice_tail(&($3)->tmp_head, &($$)->u.type_declarator.u.nested.length); } ; diff --git a/formats/ctf/metadata/ctf-visitor-parent-links.c b/formats/ctf/metadata/ctf-visitor-parent-links.c index f23458d5..8c4b2124 100644 --- a/formats/ctf/metadata/ctf-visitor-parent-links.c +++ b/formats/ctf/metadata/ctf-visitor-parent-links.c @@ -135,10 +135,10 @@ int ctf_visitor_type_declarator(FILE *fd, int depth, struct ctf_node *node) if (ret) return ret; } - if (node->u.type_declarator.u.nested.length) { - node->u.type_declarator.u.nested.length->parent = node; - ret = ctf_visitor_parent_links(fd, depth + 1, - node->u.type_declarator.u.nested.length); + cds_list_for_each_entry(iter, &node->u.type_declarator.u.nested.length, + siblings) { + iter->parent = node; + ret = ctf_visitor_parent_links(fd, depth + 1, iter); if (ret) return ret; } @@ -358,9 +358,10 @@ int ctf_visitor_parent_links(FILE *fd, int depth, struct ctf_node *node) case NODE_ENUM: depth++; - if (node->u._enum.container_type) { - node->u._enum.container_type->parent = node; - ret = ctf_visitor_parent_links(fd, depth + 1, node->u._enum.container_type); + cds_list_for_each_entry(iter, &node->u._enum.container_type, + siblings) { + iter->parent = node; + ret = ctf_visitor_parent_links(fd, depth + 1, iter); if (ret) return ret; } diff --git a/formats/ctf/metadata/ctf-visitor-semantic-validator.c b/formats/ctf/metadata/ctf-visitor-semantic-validator.c index da77f596..6f46bfbd 100644 --- a/formats/ctf/metadata/ctf-visitor-semantic-validator.c +++ b/formats/ctf/metadata/ctf-visitor-semantic-validator.c @@ -292,17 +292,25 @@ int ctf_visitor_type_declarator(FILE *fd, int depth, struct ctf_node *node) case TYPEDEC_ID: break; case TYPEDEC_NESTED: + { + int nr_nest_len; + if (node->u.type_declarator.u.nested.type_declarator) { ret = _ctf_visitor_semantic_check(fd, depth + 1, node->u.type_declarator.u.nested.type_declarator); if (ret) return ret; } - if (node->u.type_declarator.u.nested.length) { + cds_list_for_each_entry(iter, &node->u.type_declarator.u.nested.length, + siblings) { ret = _ctf_visitor_semantic_check(fd, depth + 1, - node->u.type_declarator.u.nested.length); + iter); if (ret) return ret; + nr_nest_len++; + if (iter->type == NODE_UNARY_EXPRESSION && nr_nest_len > 1) { + goto errperm; + } } if (node->u.type_declarator.bitfield_len) { ret = _ctf_visitor_semantic_check(fd, depth + 1, @@ -311,6 +319,7 @@ int ctf_visitor_type_declarator(FILE *fd, int depth, struct ctf_node *node) return ret; } break; + } case TYPEDEC_UNKNOWN: default: fprintf(fd, "[error] %s: unknown type declarator %d\n", __func__, @@ -810,8 +819,9 @@ int _ctf_visitor_semantic_check(FILE *fd, int depth, struct ctf_node *node) } depth++; - if (node->u._enum.container_type) { - ret = _ctf_visitor_semantic_check(fd, depth + 1, node->u._enum.container_type); + cds_list_for_each_entry(iter, &node->u._enum.container_type, + siblings) { + ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); if (ret) return ret; } diff --git a/formats/ctf/metadata/ctf-visitor-xml.c b/formats/ctf/metadata/ctf-visitor-xml.c index 68a2e554..7f08031a 100644 --- a/formats/ctf/metadata/ctf-visitor-xml.c +++ b/formats/ctf/metadata/ctf-visitor-xml.c @@ -218,13 +218,17 @@ int ctf_visitor_print_type_declarator(FILE *fd, int depth, struct ctf_node *node print_tabs(fd, depth); fprintf(fd, "\n"); } - if (node->u.type_declarator.u.nested.length) { + if (!cds_list_empty(&node->u.type_declarator.u.nested.length)) { print_tabs(fd, depth); fprintf(fd, "\n"); - ret = ctf_visitor_print_xml(fd, depth + 1, - node->u.type_declarator.u.nested.length); + } + cds_list_for_each_entry(iter, &node->u.type_declarator.u.nested.length, + siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); if (ret) return ret; + } + if (!cds_list_empty(&node->u.type_declarator.u.nested.length)) { print_tabs(fd, depth); fprintf(fd, "\n"); } @@ -540,12 +544,18 @@ int ctf_visitor_print_xml(FILE *fd, int depth, struct ctf_node *node) fprintf(fd, "\n"); depth++; - if (node->u._enum.container_type) { + if (!cds_list_empty(&node->u._enum.container_type)) { print_tabs(fd, depth); fprintf(fd, "\n"); - ret = ctf_visitor_print_xml(fd, depth + 1, node->u._enum.container_type); + } + + cds_list_for_each_entry(iter, &node->u._enum.container_type, + siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); if (ret) return ret; + } + if (!cds_list_empty(&node->u._enum.container_type)) { print_tabs(fd, depth); fprintf(fd, "\n"); } -- 2.34.1 From 2b0a0f95394186acf18c453209e31b028312ecf3 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Apr 2011 14:46:00 -0400 Subject: [PATCH 14/16] Remove enum < integer_constant > from grammar Signed-off-by: Mathieu Desnoyers --- formats/ctf/metadata/ctf-parser.y | 16 ++++++++-------- .../metadata/ctf-visitor-semantic-validator.c | 5 ++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/formats/ctf/metadata/ctf-parser.y b/formats/ctf/metadata/ctf-parser.y index cdcfdcdb..66e37923 100644 --- a/formats/ctf/metadata/ctf-parser.y +++ b/formats/ctf/metadata/ctf-parser.y @@ -1537,7 +1537,7 @@ enum_type_specifier: $$->u._enum.has_body = 1; _cds_list_splice_tail(&($2)->tmp_head, &($$)->u._enum.enumerator_list); } - | LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list RBRAC + | LT declaration_specifiers GT LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; @@ -1551,7 +1551,7 @@ enum_type_specifier: $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } - | IDENTIFIER LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list RBRAC + | IDENTIFIER LT declaration_specifiers GT LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; @@ -1566,7 +1566,7 @@ enum_type_specifier: $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } - | ID_TYPE LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list RBRAC + | ID_TYPE LT declaration_specifiers GT LBRAC enumerator_list RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; @@ -1580,7 +1580,7 @@ enum_type_specifier: $$->u._enum.has_body = 1; _cds_list_splice_tail(&($2)->tmp_head, &($$)->u._enum.enumerator_list); } - | LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC + | LT declaration_specifiers GT LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; @@ -1594,7 +1594,7 @@ enum_type_specifier: $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } - | IDENTIFIER LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC + | IDENTIFIER LT declaration_specifiers GT LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; @@ -1608,7 +1608,7 @@ enum_type_specifier: $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; } - | IDENTIFIER LT declaration_specifiers_or_integer_constant GT + | IDENTIFIER LT declaration_specifiers GT { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 0; @@ -1622,7 +1622,7 @@ enum_type_specifier: $$->u._enum.enum_id = $1->s; _cds_list_splice_tail(&($3)->tmp_head, &($$)->u._enum.enumerator_list); } - | ID_TYPE LT declaration_specifiers_or_integer_constant GT LBRAC enumerator_list COMMA RBRAC + | ID_TYPE LT declaration_specifiers GT LBRAC enumerator_list COMMA RBRAC { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 1; @@ -1636,7 +1636,7 @@ enum_type_specifier: $$->u._enum.has_body = 0; $$->u._enum.enum_id = $1->s; } - | ID_TYPE LT declaration_specifiers_or_integer_constant GT + | ID_TYPE LT declaration_specifiers GT { $$ = make_node(scanner, NODE_ENUM); $$->u._enum.has_body = 0; diff --git a/formats/ctf/metadata/ctf-visitor-semantic-validator.c b/formats/ctf/metadata/ctf-visitor-semantic-validator.c index 6f46bfbd..8decc19e 100644 --- a/formats/ctf/metadata/ctf-visitor-semantic-validator.c +++ b/formats/ctf/metadata/ctf-visitor-semantic-validator.c @@ -65,10 +65,8 @@ int ctf_visitor_unary_expression(FILE *fd, int depth, struct ctf_node *node) /* Right child of a ctf expression can be any type of unary exp. */ break; /* OK */ case NODE_TYPE_DECLARATOR: - case NODE_ENUM: /* - * We are the length of a type declarator or the size of an enum - * container. We can only be a numeric constant. + * We are the length of a type declarator. */ switch (node->u.unary_expression.type) { case UNARY_SIGNED_CONSTANT: @@ -104,6 +102,7 @@ int ctf_visitor_unary_expression(FILE *fd, int depth, struct ctf_node *node) case NODE_FLOATING_POINT: case NODE_INTEGER: case NODE_STRING: + case NODE_ENUM: case NODE_STRUCT_OR_VARIANT_DECLARATION: case NODE_VARIANT: case NODE_STRUCT: -- 2.34.1 From 679d3755182c0ff1672d246ae2cc516244b85824 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Apr 2011 14:47:12 -0400 Subject: [PATCH 15/16] Remove enum <32> from tests Signed-off-by: Mathieu Desnoyers --- formats/ctf/metadata/ctf-test/succeed/ctf-test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/formats/ctf/metadata/ctf-test/succeed/ctf-test.txt b/formats/ctf/metadata/ctf-test/succeed/ctf-test.txt index b051a79f..2b127cc4 100644 --- a/formats/ctf/metadata/ctf-test/succeed/ctf-test.txt +++ b/formats/ctf/metadata/ctf-test/succeed/ctf-test.txt @@ -1,5 +1,5 @@ -enum name <32> { +enum name { ZERO, ONE, TWO, -- 2.34.1 From 1cfda06240d6a474d191988e00e336b2a4c41fcf Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Apr 2011 15:00:33 -0400 Subject: [PATCH 16/16] gen io struct visitor: update enum Signed-off-by: Mathieu Desnoyers --- .../metadata/ctf-visitor-generate-io-struct.c | 114 ++++++++++++++++-- 1 file changed, 104 insertions(+), 10 deletions(-) diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index bd0a845f..dd7c9f41 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -649,22 +649,98 @@ int ctf_enumerator_list_visit(int fd, int depth, struct ctf_node *enumerator, struct declaration_enum *enum_declaration) { - /* TODO */ -........ + GQuark q; + struct ctf_node *iter; + + q = g_quark_from_string(enumerator->u.enumerator.id); + if (enum_declaration->integer->signedness) { + int64_t start, end; + int nr_vals = 0; + + cds_list_for_each_entry(iter, enumerator->u.enumerator.values, siblings) { + int64_t *target; + + assert(iter->type == NODE_UNARY_EXPRESSION); + if (nr_vals == 0) + target = &start; + else + target = &end; + + switch (iter->u.unary_expression.type) { + case UNARY_SIGNED_CONSTANT: + *target = iter->u.unary_expression.u.signed_constant; + break; + case UNARY_UNSIGNED_CONSTANT: + *target = iter->u.unary_expression.u.unsigned_constant; + break; + default: + fprintf(stderr, "[error] %s: invalid enumerator\n", __func__); + return -EINVAL; + } + if (nr_vals > 1) { + fprintf(stderr, "[error] %s: invalid enumerator\n", __func__); + return -EINVAL; + } + nr_vals++; + } + if (nr_vals == 1) + end = start; + enum_signed_insert(enum_declaration, start, end, q); + } else + uint64_t start, end; + int nr_vals = 0; + + cds_list_for_each_entry(iter, enumerator->u.enumerator.values, siblings) { + int64_t *target; + + assert(iter->type == NODE_UNARY_EXPRESSION); + if (nr_vals == 0) + target = &start; + else + target = &end; + + switch (iter->u.unary_expression.type) { + case UNARY_UNSIGNED_CONSTANT: + *target = iter->u.unary_expression.u.unsigned_constant; + break; + case UNARY_SIGNED_CONSTANT: + /* + * We don't accept signed constants for enums with unsigned + * container type. + */ + fprintf(stderr, "[error] %s: invalid enumerator (signed constant encountered, but enum container type is unsigned)\n", __func__); + return -EINVAL; + default: + fprintf(stderr, "[error] %s: invalid enumerator\n", __func__); + return -EINVAL; + } + if (nr_vals > 1) { + fprintf(stderr, "[error] %s: invalid enumerator\n", __func__); + return -EINVAL; + } + nr_vals++; + } + if (nr_vals == 1) + end = start; + enum_unsigned_insert(enum_declaration, start, end, q); + } return 0; } static struct declaration *ctf_declaration_enum_visit(int fd, int depth, const char *name, - struct ctf_node *container_type, + struct cds_list_head *container_type, struct cds_list_head *enumerator_list, - int has_body) + int has_body, + struct declaration_scope *declaration_scope, + struct ctf_trace *trace) { struct declaration *declaration; struct declaration_enum *enum_declaration; struct declaration_integer *integer_declaration; - struct ctf_node *iter; + struct ctf_node *iter, *first; + GQuark dummy_id; /* * For named enum (without body), lookup in @@ -688,10 +764,27 @@ struct declaration *ctf_declaration_enum_visit(int fd, int depth, return NULL; } } - - /* TODO CHECK Enumerations need to have their size/type specifier (< >). */ - integer_declaration = integer_declaration_new(); /* TODO ... */ - ..... + if (cds_list_empty(container_type)) { + fprintf(stderr, "[error] %s: missing container type for enumeration\n", __func__, name); + return NULL; + + } + first = _cds_list_first_entry(container_type, struct node, siblings); + switch (first->type) { + case NODE_INTEGER: + case NODE_TYPE_SPECIFIER: + declaration = ctf_type_declarator_visit(fd, depth, + container_type, + &dummy_id, iter, + declaration_scope, + NULL); + assert(declaration->id == CTF_TYPE_INTEGER); + integer_declaration = container_of(declaration, struct declaration_integer, p); + break; + } + default: + assert(0); + } enum_declaration = enum_declaration_new(name, integer_declaration); declaration_unref(&integer_declaration->p); /* leave ref to enum */ cds_list_for_each_entry(iter, enumerator_list, siblings) { @@ -1009,9 +1102,10 @@ struct declaration *ctf_declaration_specifier_visit(FILE *fd, case NODE_ENUM: return ctf_declaration_enum_visit(fd, depth, first->u._enum.enum_id, - first->u._enum.container_type, + &first->u._enum.container_type, &first->u._enum.enumerator_list, first->u._enum.has_body, + declaration_scope, trace); case NODE_INTEGER: return ctf_declaration_integer_visit(fd, depth, -- 2.34.1