X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=formats%2Fctf%2Fmetadata%2Fctf-visitor-generate-io-struct.c;h=43d7630b9a2242f4f20cd8596b60ae75933168ce;hp=7e2dc07268d4a7917c3b78b226d4846a560c70b9;hb=78af2bcd1a8236a26371d7638ab7acb2d41b6807;hpb=a3cca9e94429c6a510f60924daf24ca9bd924753 diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 7e2dc072..43d7630b 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -23,8 +23,11 @@ #include #include #include +#include #include #include +#include +#include #include #include "ctf-scanner.h" #include "ctf-parser.h" @@ -36,183 +39,43 @@ 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) -{ - 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; -} +struct declaration *ctf_type_specifier_list_visit(FILE *fd, + int depth, struct ctf_node *type_specifier_list, + struct declaration_scope *declaration_scope, + struct ctf_trace *trace); /* * 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; int i = 0; - str = g_string_new(); + 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)) + ^ (i != 0)); switch (node->u.unary_expression.link) { case UNARY_DOTLINK: - g_string_append(str, ".") + g_string_append(str, "."); break; case UNARY_ARROWLINK: - g_string_append(str, "->") + g_string_append(str, "->"); break; case UNARY_DOTDOTDOT: - g_string_append(str, "...") + g_string_append(str, "..."); + break; + default: break; } - src_string = u.unary_expression.u.string; + src_string = node->u.unary_expression.u.string; g_string_append(str, src_string); i++; } @@ -220,7 +83,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; @@ -230,14 +93,14 @@ int get_unary_unsigned(struct list_head *head, uint64_t *value) 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 + *value = node->u.unary_expression.u.unsigned_constant; i++; } return 0; } 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; @@ -250,8 +113,8 @@ int get_unary_uuid(struct list_head *head, uuid_t *uuid) 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); + src_string = node->u.unary_expression.u.string; + ret = uuid_parse(node->u.unary_expression.u.string, *uuid); } return ret; } @@ -265,12 +128,154 @@ struct ctf_stream *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_ } static -struct declaration *ctf_type_declarator_visit(int fd, int depth, - struct cds_list_head *declaration_specifier, +int visit_type_specifier(FILE *fd, struct ctf_node *type_specifier, GString *str) +{ + assert(type_specifier->type == NODE_TYPE_SPECIFIER); + + switch (type_specifier->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 (type_specifier->u.type_specifier.id_type) + g_string_append(str, type_specifier->u.type_specifier.id_type); + break; + case TYPESPEC_STRUCT: + { + struct ctf_node *node = type_specifier->u.type_specifier.node; + + if (!node->u._struct.name) { + fprintf(fd, "[error] %s: unexpected empty variant name\n", __func__); + return -EINVAL; + } + g_string_append(str, "struct "); + g_string_append(str, node->u._struct.name); + break; + } + case TYPESPEC_VARIANT: + { + struct ctf_node *node = type_specifier->u.type_specifier.node; + + if (!node->u.variant.name) { + fprintf(fd, "[error] %s: unexpected empty variant name\n", __func__); + return -EINVAL; + } + g_string_append(str, "variant "); + g_string_append(str, node->u.variant.name); + break; + } + case TYPESPEC_ENUM: + { + struct ctf_node *node = type_specifier->u.type_specifier.node; + + if (!node->u._enum.enum_id) { + fprintf(fd, "[error] %s: unexpected empty enum ID\n", __func__); + return -EINVAL; + } + g_string_append(str, "enum "); + g_string_append(str, node->u._enum.enum_id); + break; + } + case TYPESPEC_FLOATING_POINT: + case TYPESPEC_INTEGER: + case TYPESPEC_STRING: + default: + fprintf(fd, "[error] %s: unknown specifier\n", __func__); + return -EINVAL; + } + return 0; +} + +static +int visit_type_specifier_list(FILE *fd, struct ctf_node *type_specifier_list, GString *str) +{ + struct ctf_node *iter; + int alias_item_nr = 0; + int ret; + + cds_list_for_each_entry(iter, &type_specifier_list->u.type_specifier_list.head, siblings) { + if (alias_item_nr != 0) + g_string_append(str, " "); + alias_item_nr++; + ret = visit_type_specifier(fd, iter, str); + if (ret) + return ret; + } + return 0; +} + +static +GQuark create_typealias_identifier(FILE *fd, int depth, + struct ctf_node *type_specifier_list, + struct ctf_node *node_type_declarator) +{ + struct ctf_node *iter; + GString *str; + char *str_c; + GQuark alias_q; + int ret; + + str = g_string_new(""); + ret = visit_type_specifier_list(fd, type_specifier_list, 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(FILE *fd, int depth, + struct ctf_node *type_specifier_list, GQuark *field_name, struct ctf_node *node_type_declarator, - struct declaration_scope *declaration_scope - struct declaration *nested_declaration) + struct declaration_scope *declaration_scope, + struct declaration *nested_declaration, + struct ctf_trace *trace) { /* * Visit type declarator by first taking care of sequence/array @@ -278,23 +283,40 @@ struct declaration *ctf_type_declarator_visit(int fd, int depth, * 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 (node_type_declarator) { + assert(node_type_declarator->u.type_declarator.type != TYPEDEC_UNKNOWN); + + /* TODO: gcc bitfields not supported yet. */ + if (node_type_declarator->u.type_declarator.bitfield_len != NULL) { + fprintf(fd, "[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)) { + if (node_type_declarator && !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, + type_specifier_list, node_type_declarator); + nested_declaration = lookup_declaration(alias_q, declaration_scope); + if (!nested_declaration) { + fprintf(fd, "[error] %s: cannot find typealias \"%s\".\n", __func__, g_quark_to_string(alias_q)); + return NULL; + } } else { - nested_declaration = /* parse declaration_specifier */; + nested_declaration = ctf_type_specifier_list_visit(fd, depth, + type_specifier_list, declaration_scope, trace); } - } + if (!node_type_declarator) + return nested_declaration; + 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); @@ -303,42 +325,71 @@ struct declaration *ctf_type_declarator_visit(int fd, int depth, return nested_declaration; } else { struct declaration *declaration; - struct node *length; + struct ctf_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); + if (!length) { + fprintf(fd, "[error] %s: expecting length type or value.\n", __func__); + return NULL; + } + switch (length->type) { + case NODE_UNARY_EXPRESSION: + { + struct declaration_array *array_declaration; + size_t len; + + if (length->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) { + fprintf(fd, "[error] %s: array: unexpected unary expression.\n", __func__); + return NULL; } + len = length->u.unary_expression.u.unsigned_constant; + array_declaration = array_declaration_new(len, nested_declaration, + declaration_scope); + declaration = &array_declaration->p; + break; + } + case NODE_INTEGER: + case NODE_TYPE_SPECIFIER: + { + struct declaration_sequence *sequence_declaration; + struct declaration_integer *integer_declaration; + GQuark dummy_id; + + declaration = ctf_type_declarator_visit(fd, depth, + length, + &dummy_id, NULL, + declaration_scope, + NULL, trace); + assert(declaration->id == CTF_TYPE_INTEGER); + integer_declaration = container_of(declaration, struct declaration_integer, p); + sequence_declaration = sequence_declaration_new(integer_declaration, + nested_declaration, declaration_scope); + declaration = &sequence_declaration->p; + break; + } + default: + assert(0); } /* Pass it as content of outer container */ declaration = ctf_type_declarator_visit(fd, depth, - declaration_specifier, field_name, + type_specifier_list, field_name, node_type_declarator->u.type_declarator.u.nested.type_declarator, - declaration_scope, declaration); + declaration_scope, declaration, trace); return declaration; } } static -int ctf_struct_type_declarators_visit(int fd, int depth, +int ctf_struct_type_declarators_visit(FILE *fd, int depth, struct declaration_struct *struct_declaration, - struct cds_list_head *declaration_specifier, + struct ctf_node *type_specifier_list, struct cds_list_head *type_declarators, - struct declaration_scope *declaration_scope) + struct declaration_scope *declaration_scope, + struct ctf_trace *trace) { struct ctf_node *iter; GQuark field_name; @@ -347,22 +398,48 @@ int ctf_struct_type_declarators_visit(int fd, int depth, struct declaration *field_declaration; field_declaration = ctf_type_declarator_visit(fd, depth, - declaration_specifier, + type_specifier_list, &field_name, iter, struct_declaration->scope, - NULL); + NULL, trace); struct_declaration_add_field(struct_declaration, g_quark_to_string(field_name), field_declaration); } + return 0; +} +static +int ctf_variant_type_declarators_visit(FILE *fd, int depth, + struct declaration_untagged_variant *untagged_variant_declaration, + struct ctf_node *type_specifier_list, + struct cds_list_head *type_declarators, + struct declaration_scope *declaration_scope, + struct ctf_trace *trace) +{ + 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, + type_specifier_list, + &field_name, iter, + untagged_variant_declaration->scope, + NULL, trace); + untagged_variant_declaration_add_field(untagged_variant_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) +int ctf_typedef_visit(FILE *fd, int depth, struct declaration_scope *scope, + struct ctf_node *type_specifier_list, + struct cds_list_head *type_declarators, + struct ctf_trace *trace) { struct ctf_node *iter; GQuark identifier; @@ -372,9 +449,9 @@ int ctf_typedef_visit(int fd, int depth, struct declaration_scope *scope, int ret; type_declaration = ctf_type_declarator_visit(fd, depth, - declaration_specifier, + type_specifier_list, &identifier, iter, - scope, NULL); + scope, NULL, trace); ret = register_declaration(identifier, type_declaration, scope); if (ret) { type_declaration->declaration_free(type_declaration); @@ -385,16 +462,15 @@ int ctf_typedef_visit(int fd, int depth, struct declaration_scope *scope, } static -int ctf_typealias_visit(int fd, int depth, struct declaration_scope *scope, - struct ctf_node *target, struct ctf_node *alias) +int ctf_typealias_visit(FILE *fd, int depth, struct declaration_scope *scope, + struct ctf_node *target, struct ctf_node *alias, + struct ctf_trace *trace) { struct declaration *type_declaration; - struct ctf_node *iter, *node; - GQuark identifier, dummy_id; - GString *str; - const char *str_c; + struct ctf_node *node; + GQuark dummy_id; GQuark alias_q; - int alias_item_nr = 0; + int err; /* See ctf_visitor_type_declarator() in the semantic validator. */ @@ -402,12 +478,17 @@ int ctf_typealias_visit(int fd, int depth, struct declaration_scope *scope, * Create target type declaration. */ + if (cds_list_empty(&alias->u.typealias_target.type_declarators)) + node = NULL; + else + node = _cds_list_first_entry(&alias->u.typealias_target.type_declarators, + struct ctf_node, siblings); type_declaration = ctf_type_declarator_visit(fd, depth, - &target->u.typealias_target.declaration_specifier, - &dummy_id, &target->u.typealias_target.type_declarators, - scope, NULL); + target->u.typealias_target.type_specifier_list, + &dummy_id, node, + scope, NULL, trace); if (!type_declaration) { - fprintf(stderr, "[error] %s: problem creating type declaration\n", __func__); + fprintf(fd, "[error] %s: problem creating type declaration\n", __func__); err = -EINVAL; goto error; } @@ -416,136 +497,33 @@ int ctf_typealias_visit(int fd, int depth, struct declaration_scope *scope, * abstract or not (if it has an identifier). Check it here. */ if (dummy_id != 0) { - fprintf(stderr, "[error] %s: expecting empty identifier\n", __func__); + fprintf(fd, "[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) + struct ctf_node, siblings); + alias_q = create_typealias_identifier(fd, depth, + alias->u.typealias_alias.type_specifier_list, node); + err = register_declaration(alias_q, type_declaration, scope); + if (err) goto error; return 0; error: type_declaration->declaration_free(type_declaration); - return ret; + return err; } static -int ctf_struct_declaration_list_visit(int fd, int depth, - struct ctf_node *iter, struct declaration_struct *struct_declaration) +int ctf_struct_declaration_list_visit(FILE *fd, int depth, + struct ctf_node *iter, struct declaration_struct *struct_declaration, + struct ctf_trace *trace) { - struct declaration *declaration; int ret; switch (iter->type) { @@ -553,8 +531,8 @@ int ctf_struct_declaration_list_visit(int fd, int depth, /* 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); + iter->u._typedef.type_specifier_list, + &iter->u._typedef.type_declarators, trace); if (ret) return ret; break; @@ -563,7 +541,7 @@ int ctf_struct_declaration_list_visit(int fd, int depth, ret = ctf_typealias_visit(fd, depth, struct_declaration->scope, iter->u.typealias.target, - iter->u.typealias.alias); + iter->u.typealias.alias, trace); if (ret) return ret; break; @@ -571,26 +549,72 @@ int ctf_struct_declaration_list_visit(int fd, int depth, /* 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); + iter->u.struct_or_variant_declaration.type_specifier_list, + &iter->u.struct_or_variant_declaration.type_declarators, + struct_declaration->scope, trace); + if (ret) + return ret; + break; + default: + fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type); + assert(0); + } + return 0; +} + +static +int ctf_variant_declaration_list_visit(FILE *fd, int depth, + struct ctf_node *iter, + struct declaration_untagged_variant *untagged_variant_declaration, + struct ctf_trace *trace) +{ + 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, + untagged_variant_declaration->scope, + iter->u._typedef.type_specifier_list, + &iter->u._typedef.type_declarators, trace); + 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, + untagged_variant_declaration->scope, + iter->u.typealias.target, + iter->u.typealias.alias, trace); + if (ret) + return ret; + break; + case NODE_STRUCT_OR_VARIANT_DECLARATION: + /* Add field to structure declaration */ + ret = ctf_variant_type_declarators_visit(fd, depth, + untagged_variant_declaration, + iter->u.struct_or_variant_declaration.type_specifier_list, + &iter->u.struct_or_variant_declaration.type_declarators, + untagged_variant_declaration->scope, trace); if (ret) return ret; break; default: - fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type); + fprintf(fd, "[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, +struct declaration *ctf_declaration_struct_visit(FILE *fd, int depth, const char *name, struct cds_list_head *declaration_list, - int has_body, struct declaration_scope *declaration_scope) + int has_body, struct declaration_scope *declaration_scope, + struct ctf_trace *trace) { - struct declaration *declaration; struct declaration_struct *struct_declaration; struct ctf_node *iter; + int ret; /* * For named struct (without body), lookup in @@ -602,7 +626,7 @@ struct declaration_struct *ctf_declaration_struct_visit(FILE *fd, struct_declaration = lookup_struct_declaration(g_quark_from_string(name), declaration_scope); - return struct_declaration; + return &struct_declaration->p; } else { /* For unnamed struct, create type */ /* For named struct (with body), create type and add to declaration scope */ @@ -610,144 +634,592 @@ 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(fd, "[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); + struct_declaration = struct_declaration_new(declaration_scope); + cds_list_for_each_entry(iter, declaration_list, siblings) { + ret = ctf_struct_declaration_list_visit(fd, depth + 1, iter, + struct_declaration, trace); + if (ret) + goto error; + } + if (name) { + ret = register_struct_declaration(g_quark_from_string(name), + struct_declaration, + declaration_scope); + assert(!ret); + } + return &struct_declaration->p; + } +error: + struct_declaration->p.declaration_free(&struct_declaration->p); + return NULL; +} + +static +struct declaration *ctf_declaration_variant_visit(FILE *fd, + int depth, const char *name, const char *choice, + struct cds_list_head *declaration_list, + int has_body, struct declaration_scope *declaration_scope, + struct ctf_trace *trace) +{ + struct declaration_untagged_variant *untagged_variant_declaration; + struct declaration_variant *variant_declaration; + struct ctf_node *iter; + int ret; + + /* + * 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); + untagged_variant_declaration = + lookup_variant_declaration(g_quark_from_string(name), + declaration_scope); + } else { + /* For unnamed variant, create type */ + /* 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(fd, "[error] %s: variant %s already declared in scope\n", __func__, name); + return NULL; + } + } + untagged_variant_declaration = untagged_variant_declaration_new(declaration_scope); + cds_list_for_each_entry(iter, declaration_list, siblings) { + ret = ctf_variant_declaration_list_visit(fd, depth + 1, iter, + untagged_variant_declaration, trace); + if (ret) + goto error; + } + if (name) { + ret = register_variant_declaration(g_quark_from_string(name), + untagged_variant_declaration, + declaration_scope); + assert(!ret); + } + } + /* + * if tagged, create tagged variant and return. else return + * untagged variant. + */ + if (!choice) { + return &untagged_variant_declaration->p; + } else { + variant_declaration = variant_declaration_new(untagged_variant_declaration, choice); + if (!variant_declaration) + goto error; + declaration_unref(&untagged_variant_declaration->p); + return &variant_declaration->p; + } +error: + untagged_variant_declaration->p.declaration_free(&variant_declaration->p); + return NULL; +} + +static +int ctf_enumerator_list_visit(FILE *fd, int depth, + struct ctf_node *enumerator, + struct declaration_enum *enum_declaration) +{ + GQuark q; + struct ctf_node *iter; + + q = g_quark_from_string(enumerator->u.enumerator.id); + if (enum_declaration->integer_declaration->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(fd, "[error] %s: invalid enumerator\n", __func__); + return -EINVAL; + } + if (nr_vals > 1) { + fprintf(fd, "[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) { + uint64_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(fd, "[error] %s: invalid enumerator (signed constant encountered, but enum container type is unsigned)\n", __func__); + return -EINVAL; + default: + fprintf(fd, "[error] %s: invalid enumerator\n", __func__); + return -EINVAL; + } + if (nr_vals > 1) { + fprintf(fd, "[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(FILE *fd, int depth, + const char *name, + struct ctf_node *container_type, + struct cds_list_head *enumerator_list, + 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; + GQuark dummy_id; + int ret; + + /* + * For named enum (without body), lookup in + * declaration scope. Don't take reference on enum + * declaration: ref is only taken upon definition. + */ + if (!has_body) { + assert(name); + enum_declaration = + lookup_enum_declaration(g_quark_from_string(name), + declaration_scope); + return &enum_declaration->p; + } 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(fd, "[error] %s: enum %s already declared in scope\n", __func__, name); + return NULL; + } + } + if (!container_type) { + fprintf(fd, "[error] %s: missing container type for enumeration\n", __func__); + return NULL; + + } + switch (container_type->type) { + case NODE_INTEGER: + case NODE_TYPE_SPECIFIER: + declaration = ctf_type_declarator_visit(fd, depth, + container_type, + &dummy_id, NULL, + declaration_scope, + NULL, trace); + assert(declaration->id == CTF_TYPE_INTEGER); + integer_declaration = container_of(declaration, struct declaration_integer, p); + break; + default: + assert(0); + } + enum_declaration = enum_declaration_new(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_struct_declaration(g_quark_from_string(name), - struct_declaration, + ret = register_enum_declaration(g_quark_from_string(name), + enum_declaration, declaration_scope); assert(!ret); } - return struct_declaration; + return &enum_declaration->p; } error: - struct_declaration->p.declaration_free(&struct_declaration->p); + enum_declaration->p.declaration_free(&enum_declaration->p); 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 *ctf_declaration_type_specifier_visit(FILE *fd, int depth, + struct ctf_node *type_specifier_list, struct declaration_scope *declaration_scope) { + GString *str; struct declaration *declaration; - struct node *first; + char *str_c; + int ret; + GQuark id_q; - first = _cds_list_first_entry(head, struct node, siblings); + str = g_string_new(""); + ret = visit_type_specifier_list(fd, type_specifier_list, 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; +} - 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 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. - */ +/* + * Returns 0/1 boolean, or < 0 on error. + */ +static +int get_boolean(FILE *fd, int depth, struct ctf_node *unary_expression) +{ + if (unary_expression->type != NODE_UNARY_EXPRESSION) { + fprintf(fd, "[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(fd, "[error] %s: unexpected string \"%s\"\n", + __func__, unary_expression->u.unary_expression.u.string); + return -EINVAL; + } break; + default: + fprintf(fd, "[error] %s: unexpected unary expression type\n", + __func__); + return -EINVAL; + } - } } 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 get_byte_order(FILE *fd, int depth, struct ctf_node *unary_expression, + struct ctf_trace *trace) { - /* - * Build the type using declaration specifier (creating - * declaration from type_specifier), then apply type declarator, - * add the resulting type to the current declaration scope. - */ - cds_list_for_each_entry(iter, declaration_specifier, siblings) { + int byte_order; + if (unary_expression->u.unary_expression.type != UNARY_STRING) { + fprintf(fd, "[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(fd, "[error] %s: unexpected string \"%s\". Should be \"native\", \"network\", \"be\" or \"le\".\n", + __func__, unary_expression->u.unary_expression.u.string); + return -EINVAL; + } + return byte_order; +} +static +struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth, + struct cds_list_head *expressions, + struct ctf_trace *trace) +{ + struct ctf_node *expression; + 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; + + cds_list_for_each_entry(expression, expressions, siblings) { + struct ctf_node *left, *right; + + left = _cds_list_first_entry(&expression->u.ctf_expression.left, struct ctf_node, siblings); + right = _cds_list_first_entry(&expression->u.ctf_expression.right, struct ctf_node, siblings); + assert(left->u.unary_expression.type == UNARY_STRING); + if (!strcmp(left->u.unary_expression.u.string, "signed")) { + 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, trace); + 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(fd, "[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(fd, "[error] %s: align: expecting unsigned constant\n", + __func__); + return NULL; + } + alignment = right->u.unary_expression.u.unsigned_constant; + has_alignment = 1; + } else { + fprintf(fd, "[error] %s: unknown attribute name %s\n", + __func__, left->u.unary_expression.u.string); + return NULL; + } } - return 0; + if (!has_size) { + fprintf(fd, "[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 -int ctf_typedef_visit(FILE *fd, int depth, - struct list_head *declaration_specifier, - struct list_head *type_declarators, - struct declaration_scope *declaration_scope) +struct declaration *ctf_declaration_floating_point_visit(FILE *fd, int depth, + struct cds_list_head *expressions, + struct ctf_trace *trace) { - struct ctf_node *iter; + struct ctf_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 ctf_node *left, *right; + + left = _cds_list_first_entry(&expression->u.ctf_expression.left, struct ctf_node, siblings); + right = _cds_list_first_entry(&expression->u.ctf_expression.right, struct ctf_node, siblings); + 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, trace); + 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(fd, "[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(fd, "[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(fd, "[error] %s: align: expecting unsigned constant\n", + __func__); + return NULL; + } + alignment = right->u.unary_expression.u.unsigned_constant; + has_alignment = 1; + } else { + fprintf(fd, "[error] %s: unknown attribute name %s\n", + __func__, left->u.unary_expression.u.string); + return NULL; + } + } + if (!has_mant_dig) { + fprintf(fd, "[error] %s: missing mant_dig attribute\n", __func__); + return NULL; + } + if (!has_exp_dig) { + fprintf(fd, "[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; +} - 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; +static +struct declaration *ctf_declaration_string_visit(FILE *fd, int depth, + struct cds_list_head *expressions, + struct ctf_trace *trace) +{ + struct ctf_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 ctf_node *left, *right; + + left = _cds_list_first_entry(&expression->u.ctf_expression.left, struct ctf_node, siblings); + right = _cds_list_first_entry(&expression->u.ctf_expression.right, struct ctf_node, siblings); + assert(left->u.unary_expression.type == UNARY_STRING); + if (!strcmp(left->u.unary_expression.u.string, "encoding")) { + if (right->u.unary_expression.type != UNARY_STRING) { + fprintf(fd, "[error] %s: encoding: expecting string\n", + __func__); + return NULL; + } + encoding_c = right->u.unary_expression.u.string; + } else { + fprintf(fd, "[error] %s: unknown attribute name %s\n", + __func__, left->u.unary_expression.u.string); + return NULL; + } } - return 0; + if (encoding_c && !strcmp(encoding_c, "ASCII")) + encoding = CTF_STRING_ASCII; + string_declaration = string_declaration_new(encoding); + return &string_declaration->p; } + static -int ctf_typealias_visit(FILE *fd, int depth, struct ctf_node *target, - struct ctf_node *alias, - struct declaration_scope *declaration_scope) +struct declaration *ctf_type_specifier_list_visit(FILE *fd, + int depth, struct ctf_node *type_specifier_list, + struct declaration_scope *declaration_scope, + struct ctf_trace *trace) { - /* - * Build target type, check that it is reachable in current - * declaration scope. - */ + struct ctf_node *first; + struct ctf_node *node; - /* Only one type declarator is allowed */ + first = _cds_list_first_entry(&type_specifier_list->u.type_specifier_list.head, struct ctf_node, siblings); + + assert(first->type == NODE_TYPE_SPECIFIER); + + node = first->u.type_specifier.node; + + switch (first->u.type_specifier.type) { + case TYPESPEC_FLOATING_POINT: + return ctf_declaration_floating_point_visit(fd, depth, + &node->u.floating_point.expressions, trace); + case TYPESPEC_INTEGER: + return ctf_declaration_integer_visit(fd, depth, + &node->u.integer.expressions, trace); + case TYPESPEC_STRING: + return ctf_declaration_string_visit(fd, depth, + &first->u.string.expressions, trace); + case TYPESPEC_STRUCT: + return ctf_declaration_struct_visit(fd, depth, + node->u._struct.name, + &node->u._struct.declaration_list, + node->u._struct.has_body, + declaration_scope, + trace); + case TYPESPEC_VARIANT: + return ctf_declaration_variant_visit(fd, depth, + node->u.variant.name, + node->u.variant.choice, + &node->u.variant.declaration_list, + node->u.variant.has_body, + declaration_scope, + trace); + case TYPESPEC_ENUM: + return ctf_declaration_enum_visit(fd, depth, + node->u._enum.enum_id, + node->u._enum.container_type, + &node->u._enum.enumerator_list, + node->u._enum.has_body, + declaration_scope, + trace); - /* Build alias type, add to current declaration scope. */ - /* Only one type declarator is allowed */ + case TYPESPEC_VOID: + case TYPESPEC_CHAR: + case TYPESPEC_SHORT: + case TYPESPEC_INT: + case TYPESPEC_LONG: + case TYPESPEC_FLOAT: + case TYPESPEC_DOUBLE: + case TYPESPEC_SIGNED: + case TYPESPEC_UNSIGNED: + case TYPESPEC_BOOL: + case TYPESPEC_COMPLEX: + case TYPESPEC_IMAGINARY: + case TYPESPEC_CONST: + case TYPESPEC_ID_TYPE: + return ctf_declaration_type_specifier_visit(fd, depth, + type_specifier_list, declaration_scope); + default: + fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) first->u.type_specifier.type); + return NULL; + } } static @@ -758,16 +1230,18 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru switch (node->type) { case NODE_TYPEDEF: ret = ctf_typedef_visit(fd, depth + 1, - &node->u._typedef.declaration_specifier, + event->declaration_scope, + node->u._typedef.type_specifier_list, &node->u._typedef.type_declarators, - event->declaration_scope); + trace); if (ret) return ret; break; case NODE_TYPEALIAS: ret = ctf_typealias_visit(fd, depth + 1, - &node->u.typealias.target, &node->u.typealias.alias - event->declaration_scope); + event->declaration_scope, + node->u.typealias.target, node->u.typealias.alias, + trace); if (ret) return ret; break; @@ -783,7 +1257,7 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return -EPERM; right = concatenate_unary_strings(&node->u.ctf_expression.right); if (!right) { - fprintf(stderr, "[error] %s: unexpected unary expression for event name\n", __func__); + fprintf(fd, "[error] %s: unexpected unary expression for event name\n", __func__); return -EINVAL; } event->name = g_quark_from_string(right); @@ -794,7 +1268,7 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return -EPERM; ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->id); if (ret) { - fprintf(stderr, "[error] %s: unexpected unary expression for event id\n", __func__); + fprintf(fd, "[error] %s: unexpected unary expression for event id\n", __func__); return -EINVAL; } CTF_EVENT_SET_FIELD(event, id); @@ -803,39 +1277,37 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru return -EPERM; ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->stream_id); if (ret) { - fprintf(stderr, "[error] %s: unexpected unary expression for event stream_id\n", __func__); + fprintf(fd, "[error] %s: unexpected unary expression for event stream_id\n", __func__); return -EINVAL; } event->stream = trace_stream_lookup(trace, event->stream_id); if (!event->stream) { - fprintf(stderr, "[error] %s: stream id %" PRIu64 " cannot be found\n", __func__, event->stream_id); + fprintf(fd, "[error] %s: stream id %" PRIu64 " cannot be found\n", __func__, event->stream_id); return -EINVAL; } CTF_EVENT_SET_FIELD(event, stream_id); } else if (!strcmp(left, "context")) { struct declaration *declaration; - if (!event->definition_scope) - return -EPERM; - declaration = ctf_declaration_specifier_visit(fd, depth, - &node->u.ctf_expression.right, - event->declaration_scope); + declaration = ctf_type_specifier_list_visit(fd, depth, + _cds_list_first_entry(&node->u.ctf_expression.right, + struct ctf_node, siblings), + event->declaration_scope, trace); if (!declaration) return -EPERM; - if (declaration->type->id != CTF_TYPE_STRUCT) + if (declaration->id != CTF_TYPE_STRUCT) return -EPERM; event->context_decl = container_of(declaration, struct declaration_struct, p); } else if (!strcmp(left, "fields")) { struct declaration *declaration; - if (!event->definition_scope) - return -EPERM; - declaration = ctf_declaration_specifier_visit(fd, depth, - &node->u.ctf_expression.right, - event->declaration_scope); + declaration = ctf_type_specifier_list_visit(fd, depth, + _cds_list_first_entry(&node->u.ctf_expression.right, + struct ctf_node, siblings), + event->declaration_scope, trace); if (!declaration) return -EPERM; - if (declaration->type->id != CTF_TYPE_STRUCT) + if (declaration->id != CTF_TYPE_STRUCT) return -EPERM; event->fields_decl = container_of(declaration, struct declaration_struct, p); } @@ -884,33 +1356,36 @@ 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 = stream->definition_scope; + parent_def_scope = event->stream->definition_scope; if (event->context_decl) { event->context = - event->context_decl->definition_new(event->context_decl, - parent_def_scope, 0, 0); + container_of( + event->context_decl->p.definition_new(&event->context_decl->p, + parent_def_scope, 0, 0), + struct definition_struct, p); set_dynamic_definition_scope(&event->context->p, event->context->scope, "event.context"); parent_def_scope = event->context->scope; - declaration_unref(event->context_decl); + declaration_unref(&event->context_decl->p); } if (event->fields_decl) { event->fields = - event->fields_decl->definition_new(event->fields_decl, - parent_def_scope, 0, 0); + container_of( + event->fields_decl->p.definition_new(&event->fields_decl->p, + parent_def_scope, 0, 0), + struct definition_struct, p); set_dynamic_definition_scope(&event->fields->p, event->fields->scope, "event.fields"); parent_def_scope = event->fields->scope; - declaration_unref(event->fields_decl); + declaration_unref(&event->fields_decl->p); } return 0; error: - declaration_unref(event->fields_decl); - declaration_unref(event->context_decl); - free_definition_scope(event->definition_scope); + declaration_unref(&event->fields_decl->p); + declaration_unref(&event->context_decl->p); free_declaration_scope(event->declaration_scope); g_free(event); return ret; @@ -925,16 +1400,18 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str switch (node->type) { case NODE_TYPEDEF: ret = ctf_typedef_visit(fd, depth + 1, - &node->u._typedef.declaration_specifier, + stream->declaration_scope, + node->u._typedef.type_specifier_list, &node->u._typedef.type_declarators, - stream->declaration_scope); + trace); if (ret) return ret; break; case NODE_TYPEALIAS: ret = ctf_typealias_visit(fd, depth + 1, - &node->u.typealias.target, &node->u.typealias.alias - stream->declaration_scope); + stream->declaration_scope, + node->u.typealias.target, node->u.typealias.alias, + trace); if (ret) return ret; break; @@ -944,45 +1421,48 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str left = concatenate_unary_strings(&node->u.ctf_expression.left); if (!strcmp(left, "stream_id")) { - if (CTF_EVENT_FIELD_IS_SET(event, stream_id)) + if (CTF_STREAM_FIELD_IS_SET(stream, stream_id)) return -EPERM; - ret = get_unary_unsigned(&node->u.ctf_expression.right, &event->stream_id); + ret = get_unary_unsigned(&node->u.ctf_expression.right, &stream->stream_id); if (ret) { - fprintf(stderr, "[error] %s: unexpected unary expression for event stream_id\n", __func__); + fprintf(fd, "[error] %s: unexpected unary expression for event stream_id\n", __func__); return -EINVAL; } - CTF_EVENT_SET_FIELD(event, stream_id); + CTF_STREAM_SET_FIELD(stream, stream_id); } else if (!strcmp(left, "event.header")) { struct declaration *declaration; - declaration = ctf_declaration_specifier_visit(fd, depth, - &node->u.ctf_expression.right, - stream->declaration_scope, stream->definition_scope); + declaration = ctf_type_specifier_list_visit(fd, depth, + _cds_list_first_entry(&node->u.ctf_expression.right, + struct ctf_node, siblings), + stream->declaration_scope, trace); if (!declaration) return -EPERM; - if (declaration->type->id != CTF_TYPE_STRUCT) + if (declaration->id != CTF_TYPE_STRUCT) return -EPERM; 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, - &node->u.ctf_expression.right, - stream->declaration_scope); + declaration = ctf_type_specifier_list_visit(fd, depth, + _cds_list_first_entry(&node->u.ctf_expression.right, + struct ctf_node, siblings), + stream->declaration_scope, trace); if (!declaration) return -EPERM; - if (declaration->type->id != CTF_TYPE_STRUCT) + if (declaration->id != CTF_TYPE_STRUCT) return -EPERM; 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, - &node->u.ctf_expression.right, - stream->declaration_scope); + declaration = ctf_type_specifier_list_visit(fd, depth, + _cds_list_first_entry(&node->u.ctf_expression.right, + struct ctf_node, siblings), + stream->declaration_scope, trace); if (!declaration) return -EPERM; - if (declaration->type->id != CTF_TYPE_STRUCT) + if (declaration->id != CTF_TYPE_STRUCT) return -EPERM; stream->packet_context_decl = container_of(declaration, struct declaration_struct, p); } @@ -1015,7 +1495,7 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, if (ret) goto error; } - if (!CTF_EVENT_FIELD_IS_SET(stream, stream_id)) { + if (!CTF_STREAM_FIELD_IS_SET(stream, stream_id)) { ret = -EPERM; goto error; } @@ -1026,45 +1506,50 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, 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, 0, 0); + container_of( + stream->packet_context_decl->p.definition_new(&stream->packet_context_decl->p, + parent_def_scope, 0, 0), + struct definition_struct, p); set_dynamic_definition_scope(&stream->packet_context->p, stream->packet_context->scope, "stream.packet.context"); parent_def_scope = stream->packet_context->scope; - declaration_unref(stream->packet_context_decl); + declaration_unref(&stream->packet_context_decl->p); } if (stream->event_header_decl) { stream->event_header = - stream->event_header_decl->definition_new(stream->event_header_decl, - parent_def_scope, 0, 0); + container_of( + stream->event_header_decl->p.definition_new(&stream->event_header_decl->p, + parent_def_scope, 0, 0), + struct definition_struct, p); set_dynamic_definition_scope(&stream->event_header->p, stream->event_header->scope, "stream.event.header"); parent_def_scope = stream->event_header->scope; - declaration_unref(stream->event_header_decl); + declaration_unref(&stream->event_header_decl->p); } if (stream->event_context_decl) { stream->event_context = - stream->event_context_decl->definition_new(stream->event_context_decl, - parent_def_scope, 0, 0); + container_of( + stream->event_context_decl->p.definition_new(&stream->event_context_decl->p, + parent_def_scope, 0, 0), + struct definition_struct, p); set_dynamic_definition_scope(&stream->event_context->p, stream->event_context->scope, "stream.event.context"); parent_def_scope = stream->event_context->scope; - declaration_unref(stream->event_context_decl); + declaration_unref(&stream->event_context_decl->p); } stream->definition_scope = parent_def_scope; return 0; error: - declaration_unref(stream->event_header); - declaration_unref(stream->event_context); - declaration_unref(stream->packet_context); + declaration_unref(&stream->event_header_decl->p); + declaration_unref(&stream->event_context_decl->p); + declaration_unref(&stream->packet_context_decl->p); g_ptr_array_free(stream->events_by_id, TRUE); - g_hash_table_free(stream->event_quark_to_id); - free_definition_scope(stream->definition_scope); + g_hash_table_destroy(stream->event_quark_to_id); free_declaration_scope(stream->declaration_scope); g_free(stream); return ret; @@ -1078,16 +1563,18 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru switch (node->type) { case NODE_TYPEDEF: ret = ctf_typedef_visit(fd, depth + 1, - &node->u._typedef.declaration_specifier, + trace->declaration_scope, + node->u._typedef.type_specifier_list, &node->u._typedef.type_declarators, - trace->declaration_scope); + trace); if (ret) return ret; break; case NODE_TYPEALIAS: ret = ctf_typealias_visit(fd, depth + 1, - &node->u.typealias.target, &node->u.typealias.alias - trace->declaration_scope); + trace->declaration_scope, + node->u.typealias.target, node->u.typealias.alias, + trace); if (ret) return ret; break; @@ -1097,41 +1584,41 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru left = concatenate_unary_strings(&node->u.ctf_expression.left); if (!strcmp(left, "major")) { - if (CTF_EVENT_FIELD_IS_SET(trace, major)) + if (CTF_TRACE_FIELD_IS_SET(trace, major)) return -EPERM; ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->major); if (ret) { - fprintf(stderr, "[error] %s: unexpected unary expression for trace major number\n", __func__); + fprintf(fd, "[error] %s: unexpected unary expression for trace major number\n", __func__); return -EINVAL; } - CTF_EVENT_SET_FIELD(trace, major); + CTF_TRACE_SET_FIELD(trace, major); } else if (!strcmp(left, "minor")) { - if (CTF_EVENT_FIELD_IS_SET(trace, minor)) + if (CTF_TRACE_FIELD_IS_SET(trace, minor)) return -EPERM; ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->minor); if (ret) { - fprintf(stderr, "[error] %s: unexpected unary expression for trace minor number\n", __func__); + fprintf(fd, "[error] %s: unexpected unary expression for trace minor number\n", __func__); return -EINVAL; } - CTF_EVENT_SET_FIELD(trace, minor); + CTF_TRACE_SET_FIELD(trace, minor); } else if (!strcmp(left, "word_size")) { - if (CTF_EVENT_FIELD_IS_SET(trace, word_size)) + if (CTF_TRACE_FIELD_IS_SET(trace, word_size)) return -EPERM; ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->word_size); if (ret) { - fprintf(stderr, "[error] %s: unexpected unary expression for trace word_size\n", __func__); + fprintf(fd, "[error] %s: unexpected unary expression for trace word_size\n", __func__); return -EINVAL; } - CTF_EVENT_SET_FIELD(trace, word_size); + CTF_TRACE_SET_FIELD(trace, word_size); } else if (!strcmp(left, "uuid")) { - if (CTF_EVENT_FIELD_IS_SET(trace, uuid)) + if (CTF_TRACE_FIELD_IS_SET(trace, uuid)) return -EPERM; ret = get_unary_uuid(&node->u.ctf_expression.right, &trace->uuid); if (ret) { - fprintf(stderr, "[error] %s: unexpected unary expression for trace uuid\n", __func__); + fprintf(fd, "[error] %s: unexpected unary expression for trace uuid\n", __func__); return -EINVAL; } - CTF_EVENT_SET_FIELD(trace, uuid); + CTF_TRACE_SET_FIELD(trace, uuid); } g_free(left); break; @@ -1144,7 +1631,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) { @@ -1154,26 +1640,25 @@ 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_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); if (ret) goto error; } - if (!CTF_EVENT_FIELD_IS_SET(trace, major)) { + if (!CTF_TRACE_FIELD_IS_SET(trace, major)) { ret = -EPERM; goto error; } - if (!CTF_EVENT_FIELD_IS_SET(trace, minor)) { + if (!CTF_TRACE_FIELD_IS_SET(trace, minor)) { ret = -EPERM; goto error; } - if (!CTF_EVENT_FIELD_IS_SET(trace, uuid)) { + if (!CTF_TRACE_FIELD_IS_SET(trace, uuid)) { ret = -EPERM; goto error; } - if (!CTF_EVENT_FIELD_IS_SET(trace, word_size)) { + if (!CTF_TRACE_FIELD_IS_SET(trace, word_size)) { ret = -EPERM; goto error; } @@ -1181,287 +1666,97 @@ int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace error: g_ptr_array_free(trace->streams, TRUE); - free_definition_scope(stream->definition_scope); - free_declaration_scope(stream->declaration_scope); + free_declaration_scope(trace->declaration_scope); return ret; } -int _ctf_visitor(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace) +static +int ctf_root_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace) { int ret = 0; - struct ctf_node *iter; switch (node->type) { - case NODE_ROOT: - cds_list_for_each_entry(iter, &node->u.root._typedef, - siblings) { - ret = ctf_typedef_visit(fd, depth + 1, - &iter->u._typedef.declaration_specifier, - &iter->u._typedef.type_declarators, - trace->root_declaration_scope); - if (ret) - return ret; - } - cds_list_for_each_entry(iter, &node->u.root.typealias, - siblings) { - ret = ctf_typealias_visit(fd, depth + 1, - &iter->u.typealias.target, &iter->u.typealias.alias - trace->root_declaration_scope); - if (ret) - return ret; - } - cds_list_for_each_entry(iter, &node->u.root.declaration_specifier, siblings) { - ret = ctf_declaration_specifier_visit(fd, depth, iter, - trace->root_declaration_scope); - if (ret) - return ret; - } - cds_list_for_each_entry(iter, &node->u.root.trace, siblings) { - ret = ctf_trace_visit(fd, depth + 1, iter, trace); - if (ret) - return ret; - } - cds_list_for_each_entry(iter, &node->u.root.stream, siblings) { - ret = ctf_stream_visit(fd, depth + 1, iter, - trace->root_declaration_scope, trace); - if (ret) - return ret; - } - cds_list_for_each_entry(iter, &node->u.root.event, siblings) { - ret = ctf_event_visit(fd, depth + 1, iter, - trace->root_declaration_scope, trace); - if (ret) - 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); + case NODE_TYPEDEF: + ret = ctf_typedef_visit(fd, depth + 1, + trace->root_declaration_scope, + node->u._typedef.type_specifier_list, + &node->u._typedef.type_declarators, + trace); 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); + case NODE_TYPEALIAS: + ret = ctf_typealias_visit(fd, depth + 1, + trace->root_declaration_scope, + node->u.typealias.target, node->u.typealias.alias, + trace); if (ret) return ret; break; + case NODE_TYPE_SPECIFIER_LIST: + { + struct declaration *declaration; - 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"); + /* + * Just add the type specifier to the root scope + * declaration scope. Release local reference. + */ + declaration = ctf_type_specifier_list_visit(fd, depth + 1, + node, trace->root_declaration_scope, trace); + if (!declaration) + return -ENOMEM; + declaration_unref(declaration); 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++; + } + default: + return -EPERM; + } - 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"); - } + return 0; +} - 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"); +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; - 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); + fprintf(fd, "CTF visitor: metadata construction... "); + trace->root_declaration_scope = new_declaration_scope(NULL); + trace->byte_order = byte_order; + + switch (node->type) { + case NODE_ROOT: + cds_list_for_each_entry(iter, &node->u.root.declaration_list, + siblings) { + ret = ctf_root_declaration_visit(fd, depth + 1, iter, trace); 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); + cds_list_for_each_entry(iter, &node->u.root.trace, siblings) { + ret = ctf_trace_visit(fd, depth + 1, iter, trace); 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); + cds_list_for_each_entry(iter, &node->u.root.stream, siblings) { + ret = ctf_stream_visit(fd, depth + 1, iter, + trace->root_declaration_scope, trace); if (ret) 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); + cds_list_for_each_entry(iter, &node->u.root.event, siblings) { + ret = ctf_event_visit(fd, depth + 1, iter, + trace->root_declaration_scope, trace); 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__, + fprintf(fd, "[error] %s: unknown node type %d\n", __func__, (int) node->type); return -EINVAL; } + fprintf(fd, "done.\n"); return ret; }