From: Mathieu Desnoyers Date: Mon, 16 May 2011 21:10:48 +0000 (-0400) Subject: Update sequence (type specifier -> field ref), fix definition lookup X-Git-Tag: v0.1~51 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=98df1c9fb24d5e7e10bf628692011e130e0d8339 Update sequence (type specifier -> field ref), fix definition lookup Signed-off-by: Mathieu Desnoyers --- diff --git a/formats/ctf/metadata/ctf-ast.h b/formats/ctf/metadata/ctf-ast.h index 3d8d8b00..f21dda01 100644 --- a/formats/ctf/metadata/ctf-ast.h +++ b/formats/ctf/metadata/ctf-ast.h @@ -192,7 +192,7 @@ struct ctf_node { * unary expression (value) or * type_specifier_list. */ - struct ctf_node *length; + struct cds_list_head length; /* for abstract type declarator */ unsigned int abstract_array; } nested; diff --git a/formats/ctf/metadata/ctf-parser.y b/formats/ctf/metadata/ctf-parser.y index ed766952..697f942c 100644 --- a/formats/ctf/metadata/ctf-parser.y +++ b/formats/ctf/metadata/ctf-parser.y @@ -535,16 +535,13 @@ static int reparent_type_specifier_list(struct ctf_node *node, case NODE_TYPEALIAS_ALIAS: parent->u.typealias_alias.type_specifier_list = node; break; - case NODE_TYPE_DECLARATOR: - parent->u.type_declarator.type = TYPEDEC_NESTED; - parent->u.type_declarator.u.nested.length = node; - break; case NODE_ENUM: parent->u._enum.container_type = node; break; case NODE_STRUCT_OR_VARIANT_DECLARATION: parent->u.struct_or_variant_declaration.type_specifier_list = node; break; + case NODE_TYPE_DECLARATOR: case NODE_TYPE_SPECIFIER: case NODE_TYPEALIAS: case NODE_FLOATING_POINT: @@ -888,7 +885,6 @@ void ctf_scanner_free(struct ctf_scanner *scanner) %type type_specifier %type struct_type_specifier %type variant_type_specifier -%type declaration_specifiers_or_integer_constant %type enum_type_specifier %type struct_or_variant_declaration_list %type struct_or_variant_declaration @@ -1752,32 +1748,6 @@ variant_declaration_end: { pop_scope(scanner); } ; -declaration_specifiers_or_integer_constant: - declaration_specifiers - { $$ = $1; } - | DECIMAL_CONSTANT - { - $$ = make_node(scanner, NODE_UNARY_EXPRESSION); - $$->u.unary_expression.type = UNARY_UNSIGNED_CONSTANT; - sscanf(yylval.gs->s, "%" PRIu64, - &$$->u.unary_expression.u.unsigned_constant); - } - | OCTAL_CONSTANT - { - $$ = make_node(scanner, NODE_UNARY_EXPRESSION); - $$->u.unary_expression.type = UNARY_UNSIGNED_CONSTANT; - sscanf(yylval.gs->s, "0%" PRIo64, - &$$->u.unary_expression.u.unsigned_constant); - } - | HEXADECIMAL_CONSTANT - { - $$ = make_node(scanner, NODE_UNARY_EXPRESSION); - $$->u.unary_expression.type = UNARY_UNSIGNED_CONSTANT; - sscanf(yylval.gs->s, "0x%" PRIx64, - &$$->u.unary_expression.u.unsigned_constant); - } - ; - enum_type_specifier: LBRAC enumerator_list RBRAC { @@ -2142,12 +2112,13 @@ direct_abstract_declarator: $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_abstract_declarator LSBRAC declaration_specifiers_or_integer_constant RSBRAC + | direct_abstract_declarator LSBRAC unary_expression 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 { @@ -2191,12 +2162,13 @@ direct_alias_abstract_declarator: $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_alias_abstract_declarator LSBRAC declaration_specifiers_or_integer_constant RSBRAC + | direct_alias_abstract_declarator LSBRAC unary_expression 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 { @@ -2230,12 +2202,13 @@ direct_declarator: $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_declarator LSBRAC declaration_specifiers_or_integer_constant RSBRAC + | direct_declarator LSBRAC unary_expression 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); } ; @@ -2263,12 +2236,13 @@ direct_type_declarator: $$->u.type_declarator.type = TYPEDEC_NESTED; $$->u.type_declarator.u.nested.type_declarator = $2; } - | direct_type_declarator LSBRAC declaration_specifiers_or_integer_constant RSBRAC + | direct_type_declarator LSBRAC unary_expression 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-test/succeed/ctf-test-seq.txt b/formats/ctf/metadata/ctf-test/succeed/ctf-test-seq.txt new file mode 100644 index 00000000..763a7767 --- /dev/null +++ b/formats/ctf/metadata/ctf-test/succeed/ctf-test-seq.txt @@ -0,0 +1,42 @@ +/* Architecture with 32-bit pointers, 32-bit integers, 32-bit longs */ + +typealias integer { size = 1; align = 1; signed = false; } := uint1_t; +typealias integer { size = 8; align = 8; signed = false; } := uint8_t; +typealias integer { size = 63; align = 1; signed = false; } := timestamp_t; + +typealias integer { size = 32; align = 32; signed = false; base = dec; } := uint32_t; +typealias integer { size = 32; align = 32; signed = false; base = hex;} := void *; + +trace { + major = 0; + minor = 1; + uuid = "2a6422d0-6cee-11e0-8c08-cb07d7b3a564"; + byte_order = be; + packet.header := struct { + uint32_t magic; + uint8_t trace_uuid[16]; + uint32_t stream_id; + }; +}; + +stream { + id = 0; + event.header := struct { + uint1_t id; + timestamp_t timestamp; + } align(8); + event.context := struct { + uint32_t thread_id; + uint32_t event_count; + }; +}; + +event { + name = func_enter; + id = 0; + stream_id = 0; + fields := struct { + uint8_t len; + uint32_t myseq[len]; + }; +}; diff --git a/formats/ctf/metadata/ctf-test/succeed/ctf-test.txt b/formats/ctf/metadata/ctf-test/succeed/ctf-test.txt index 260ac024..c261a9a5 100644 --- a/formats/ctf/metadata/ctf-test/succeed/ctf-test.txt +++ b/formats/ctf/metadata/ctf-test/succeed/ctf-test.txt @@ -51,6 +51,7 @@ struct event_packet_header { trace { major = 66; minor = 2; + byte_order = le; uuid = "1123fcea-706e-11e0-a38b-f3c28a683a3d"; packet.header := struct event_packet_header; }; @@ -175,7 +176,7 @@ event { id = 0; stream_id = 5; context := struct {}; - payload := struct {}; + fields := struct {}; }; typealias integer { size = 32; align = 32; signed = false; } := unsigned long long *; @@ -186,14 +187,18 @@ variant vardecl { }; event { + typealias integer { size = 8; align = 8; signed = true; } := char; + typealias integer { size = 32; align = 32; signed = false; } := unsigned int; + name = test_event2; id = 1; stream_id = 5; - payload := struct { + fields := struct { enum : char { a = 0, b = 1, } tag; variant vardecl myvariant; + unsigned int seqlen; + int myseq[seqlen]; }; }; typedef int myarray[10]; -typedef int myseq[uint]; diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 507233c9..ecd9ffd9 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -346,57 +346,47 @@ struct declaration *ctf_type_declarator_visit(FILE *fd, int depth, return nested_declaration; } else { struct declaration *declaration; - struct ctf_node *length; + struct ctf_node *first; /* TYPEDEC_NESTED */ /* create array/sequence, pass nested_declaration as child. */ - length = node_type_declarator->u.type_declarator.u.nested.length; - if (!length) { - fprintf(fd, "[error] %s: expecting length type or value.\n", __func__); + if (cds_list_empty(&node_type_declarator->u.type_declarator.u.nested.length)) { + fprintf(fd, "[error] %s: expecting length field reference or value.\n", __func__); return NULL; } - switch (length->type) { - case NODE_UNARY_EXPRESSION: + first = _cds_list_first_entry(&node_type_declarator->u.type_declarator.u.nested.length, + struct ctf_node, siblings); + assert(first->type == NODE_UNARY_EXPRESSION); + + switch (first->u.unary_expression.type) { + case UNARY_UNSIGNED_CONSTANT: { 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; + len = first->u.unary_expression.u.unsigned_constant; array_declaration = array_declaration_new(len, nested_declaration, declaration_scope); + + if (!array_declaration) { + fprintf(fd, "[error] %s: cannot create array declaration.\n", __func__); + return NULL; + } declaration = &array_declaration->p; break; } - case NODE_TYPE_SPECIFIER_LIST: + case UNARY_STRING: { + /* Lookup unsigned integer definition, create sequence */ + char *length_name = concatenate_unary_strings(&node_type_declarator->u.type_declarator.u.nested.length); struct declaration_sequence *sequence_declaration; - struct declaration_integer *integer_declaration; - declaration = ctf_type_specifier_list_visit(fd, depth, - length, declaration_scope, trace); - if (!declaration) { - fprintf(fd, "[error] %s: unable to find declaration type for sequence length\n", __func__); - return NULL; - } - if (declaration->id != CTF_TYPE_INTEGER) { - fprintf(fd, "[error] %s: length type for sequence is expected to be an integer (unsigned).\n", __func__); - declaration_unref(declaration); + sequence_declaration = sequence_declaration_new(length_name, nested_declaration, declaration_scope); + if (!sequence_declaration) { + fprintf(fd, "[error] %s: cannot create sequence declaration.\n", __func__); return NULL; } - integer_declaration = container_of(declaration, struct declaration_integer, p); - if (integer_declaration->signedness != false) { - fprintf(fd, "[error] %s: length type for sequence should always be an unsigned integer.\n", __func__); - declaration_unref(declaration); - return NULL; - } - - sequence_declaration = sequence_declaration_new(integer_declaration, - nested_declaration, declaration_scope); declaration = &sequence_declaration->p; break; } @@ -1505,6 +1495,10 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru goto error; } event->fields_decl = container_of(declaration, struct declaration_struct, p); + } else { + fprintf(fd, "[error] %s: attribute \"%s\" is unknown in event declaration.\n", __func__, left); + ret = -EINVAL; + goto error; } error: g_free(left); @@ -1572,34 +1566,40 @@ int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node, &event->id); parent_def_scope = event->stream->definition_scope; if (event->context_decl) { - event->context = - container_of( + struct definition *definition = 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, 0, 0, "event.context"); + if (!definition) { + ret = -EINVAL; + goto error; + } + event->context = container_of(definition, + struct definition_struct, p); parent_def_scope = event->context->scope; - declaration_unref(&event->context_decl->p); } if (event->fields_decl) { - event->fields = - container_of( + struct definition *definition = 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, 0, 0, "event.fields"); + if (!definition) { + ret = -EINVAL; + goto error; + } + event->fields = container_of(definition, + struct definition_struct, p); parent_def_scope = event->fields->scope; - declaration_unref(&event->fields_decl->p); } return 0; error: - declaration_unref(&event->fields_decl->p); - declaration_unref(&event->context_decl->p); + if (event->context) + definition_unref(&event->context->p); + if (event->fields) + definition_unref(&event->fields->p); + if (event->fields_decl) + declaration_unref(&event->fields_decl->p); + if (event->context_decl) + declaration_unref(&event->context_decl->p); free_declaration_scope(event->declaration_scope); g_free(event); return ret; @@ -1710,7 +1710,12 @@ int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, str goto error; } stream->packet_context_decl = container_of(declaration, struct declaration_struct, p); + } else { + fprintf(fd, "[error] %s: attribute \"%s\" is unknown in stream declaration.\n", __func__, left); + ret = -EINVAL; + goto error; } + error: g_free(left); break; @@ -1767,49 +1772,58 @@ int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, parent_def_scope = trace->definition_scope; if (stream->packet_context_decl) { - stream->packet_context = - container_of( + struct definition *definition = 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, 0, 0, "stream.packet.context"); + if (!definition) { + ret = -EINVAL; + goto error; + } + stream->packet_context = container_of(definition, + struct definition_struct, p); parent_def_scope = stream->packet_context->scope; - declaration_unref(&stream->packet_context_decl->p); } if (stream->event_header_decl) { - stream->event_header = - container_of( + struct definition *definition = 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, 0, 0, "stream.event.header"); + if (!definition) { + ret = -EINVAL; + goto error; + } + stream->event_header = + container_of(definition, struct definition_struct, p); parent_def_scope = stream->event_header->scope; - declaration_unref(&stream->event_header_decl->p); } if (stream->event_context_decl) { - stream->event_context = - container_of( + struct definition *definition = 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, 0, 0, "stream.event.context"); + if (!definition) { + ret = -EINVAL; + goto error; + } + stream->event_context = + container_of(definition, struct definition_struct, p); parent_def_scope = stream->event_context->scope; - declaration_unref(&stream->event_context_decl->p); } stream->definition_scope = parent_def_scope; return 0; error: - declaration_unref(&stream->event_header_decl->p); - declaration_unref(&stream->event_context_decl->p); - declaration_unref(&stream->packet_context_decl->p); + if (stream->event_context) + definition_unref(&stream->event_context->p); + if (stream->event_header) + definition_unref(&stream->event_header->p); + if (stream->packet_context) + definition_unref(&stream->packet_context->p); + if (stream->event_header_decl) + declaration_unref(&stream->event_header_decl->p); + if (stream->event_context_decl) + declaration_unref(&stream->event_context_decl->p); + if (stream->packet_context_decl) + declaration_unref(&stream->packet_context_decl->p); g_ptr_array_free(stream->files, TRUE); g_ptr_array_free(stream->events_by_id, TRUE); g_hash_table_destroy(stream->event_quark_to_id); @@ -1921,7 +1935,12 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru goto error; } trace->packet_header_decl = container_of(declaration, struct declaration_struct, p); + } else { + fprintf(fd, "[error] %s: attribute \"%s\" is unknown in trace declaration.\n", __func__, left); + ret = -EINVAL; + goto error; } + error: g_free(left); break; @@ -1973,16 +1992,16 @@ int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace parent_def_scope = NULL; if (trace->packet_header_decl) { - trace->packet_header = - container_of( + struct definition *definition = trace->packet_header_decl->p.definition_new(&trace->packet_header_decl->p, - parent_def_scope, 0, 0), - struct definition_struct, p); - set_dynamic_definition_scope(&trace->packet_header->p, - trace->packet_header->scope, - "trace.packet.header"); + parent_def_scope, 0, 0, "trace.packet.header"); + if (!definition) { + ret = -EINVAL; + goto error; + } + trace->packet_header = + container_of(definition, struct definition_struct, p); parent_def_scope = trace->packet_header->scope; - declaration_unref(&trace->packet_header_decl->p); } trace->definition_scope = parent_def_scope; @@ -1992,14 +2011,16 @@ int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace || struct_declaration_lookup_field_index(trace->packet_header_decl, g_quark_from_static_string("magic")) < 0) { ret = -EPERM; fprintf(fd, "[error] %s: missing both byte_order and packet header magic number in trace declaration\n", __func__); - goto error_free_def; + goto error; } } return 0; -error_free_def: - definition_unref(&trace->packet_header->p); error: + if (trace->packet_header) + definition_unref(&trace->packet_header->p); + if (trace->packet_header_decl) + declaration_unref(&trace->packet_header_decl->p); g_ptr_array_free(trace->streams, TRUE); free_declaration_scope(trace->declaration_scope); return ret; diff --git a/formats/ctf/metadata/ctf-visitor-parent-links.c b/formats/ctf/metadata/ctf-visitor-parent-links.c index ce2fb0d9..a4476b22 100644 --- a/formats/ctf/metadata/ctf-visitor-parent-links.c +++ b/formats/ctf/metadata/ctf-visitor-parent-links.c @@ -128,14 +128,12 @@ int ctf_visitor_type_declarator(FILE *fd, int depth, struct ctf_node *node) depth++; - if (!cds_list_empty(&node->u.type_declarator.pointers)) { - cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, - siblings) { - iter->parent = node; - ret = ctf_visitor_parent_links(fd, depth + 1, iter); - if (ret) - return ret; - } + cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, + siblings) { + iter->parent = node; + ret = ctf_visitor_parent_links(fd, depth + 1, iter); + if (ret) + return ret; } switch (node->u.type_declarator.type) { @@ -149,9 +147,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; } diff --git a/formats/ctf/metadata/ctf-visitor-semantic-validator.c b/formats/ctf/metadata/ctf-visitor-semantic-validator.c index be5ed8f4..0883bc79 100644 --- a/formats/ctf/metadata/ctf-visitor-semantic-validator.c +++ b/formats/ctf/metadata/ctf-visitor-semantic-validator.c @@ -71,9 +71,10 @@ int ctf_visitor_unary_expression(FILE *fd, int depth, struct ctf_node *node) */ switch (node->u.unary_expression.type) { case UNARY_UNSIGNED_CONSTANT: + case UNARY_STRING: break; default: - fprintf(fd, "[error]: semantic error (children of type declarator and enum can only be unsigned numeric constants)\n"); + fprintf(fd, "[error]: semantic error (children of type declarator and enum can only be unsigned numeric constants or references to fields (a.b.c))\n"); goto errperm; } break; /* OK */ @@ -341,13 +342,11 @@ int ctf_visitor_type_declarator(FILE *fd, int depth, struct ctf_node *node) goto errinval; } - if (!cds_list_empty(&node->u.type_declarator.pointers)) { - cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, - siblings) { - ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); - if (ret) - return ret; - } + cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, + siblings) { + ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); + if (ret) + return ret; } switch (node->u.type_declarator.type) { @@ -361,10 +360,16 @@ int ctf_visitor_type_declarator(FILE *fd, int depth, struct ctf_node *node) if (ret) return ret; } - ret = _ctf_visitor_semantic_check(fd, depth + 1, - node->u.type_declarator.u.nested.length); - if (ret) - return ret; + cds_list_for_each_entry(iter, &node->u.type_declarator.u.nested.length, + siblings) { + if (iter->type != NODE_UNARY_EXPRESSION) { + fprintf(fd, "[error] %s: expecting unary expression as length\n", __func__); + return -EINVAL; + } + ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); + if (ret) + return ret; + } if (node->u.type_declarator.bitfield_len) { ret = _ctf_visitor_semantic_check(fd, depth + 1, node->u.type_declarator.bitfield_len); diff --git a/formats/ctf/metadata/ctf-visitor-xml.c b/formats/ctf/metadata/ctf-visitor-xml.c index 0236fbae..7115126f 100644 --- a/formats/ctf/metadata/ctf-visitor-xml.c +++ b/formats/ctf/metadata/ctf-visitor-xml.c @@ -309,12 +309,15 @@ 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); - if (ret) - return ret; + 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; + } print_tabs(fd, depth); fprintf(fd, "\n"); } diff --git a/formats/ctf/types/float.c b/formats/ctf/types/float.c index ebd7b7ae..8ba8a69d 100644 --- a/formats/ctf/types/float.c +++ b/formats/ctf/types/float.c @@ -142,7 +142,7 @@ int ctf_float_read(struct stream_pos *ppos, struct definition *definition) union ldoubleIEEE754 u; struct definition *tmpdef = static_ldouble_declaration->p.definition_new(&static_ldouble_declaration->p, - NULL, 0, 0); + NULL, 0, 0, NULL); struct definition_float *tmpfloat = container_of(tmpdef, struct definition_float, p); struct ctf_stream_pos destp; @@ -168,7 +168,7 @@ int ctf_float_write(struct stream_pos *ppos, struct definition *definition) union ldoubleIEEE754 u; struct definition *tmpdef = static_ldouble_declaration->p.definition_new(&static_ldouble_declaration->p, - NULL, 0, 0); + NULL, 0, 0, NULL); struct definition_float *tmpfloat = container_of(tmpdef, struct definition_float, p); struct ctf_stream_pos srcp; diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 33311a68..2aa45b8a 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -91,7 +91,8 @@ struct declaration { struct definition * (*definition_new)(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index); + GQuark field_name, int index, + const char *root_name); /* * definition_free called with definition ref is decremented to 0. */ @@ -166,6 +167,7 @@ struct definition_float { struct definition_integer *sign; struct definition_integer *mantissa; struct definition_integer *exp; + struct definition_scope *scope; /* Last values read */ long double value; }; @@ -218,6 +220,7 @@ struct definition_enum { struct definition p; struct definition_integer *integer; struct declaration_enum *declaration; + struct definition_scope *scope; /* Last GQuark values read. Keeping a reference on the GQuark array. */ GArray *value; }; @@ -298,7 +301,7 @@ struct definition_array { struct declaration_sequence { struct declaration p; - struct declaration_integer *len_declaration; + GArray *length_name; /* Array of GQuark */ struct declaration *elem; struct declaration_scope *scope; }; @@ -307,7 +310,7 @@ struct definition_sequence { struct definition p; struct declaration_sequence *declaration; struct definition_scope *scope; - struct definition_integer *len; + struct definition_integer *length; GPtrArray *elems; /* Array of pointers to struct definition */ }; @@ -358,13 +361,11 @@ int register_field_definition(GQuark field_name, struct definition_scope *scope); struct definition_scope * new_definition_scope(struct definition_scope *parent_scope, - GQuark field_name); -void set_dynamic_definition_scope(struct definition *definition, - struct definition_scope *scope, - const char *root_name); + GQuark field_name, const char *root_name); void free_definition_scope(struct definition_scope *scope); -GQuark new_definition_path(struct definition_scope *parent_scope, GQuark field_name); +GQuark new_definition_path(struct definition_scope *parent_scope, + GQuark field_name, const char *root_name); static inline int compare_definition_path(struct definition *definition, GQuark path) @@ -497,7 +498,7 @@ int array_rw(struct stream_pos *pos, struct definition *definition); * to the sequence. No need to free them explicitly. */ struct declaration_sequence * - sequence_declaration_new(struct declaration_integer *len_declaration, + sequence_declaration_new(const char *length_name, struct declaration *elem_declaration, struct declaration_scope *parent_scope); uint64_t sequence_len(struct definition_sequence *sequence); diff --git a/types/array.c b/types/array.c index 0bb141ce..0be26476 100644 --- a/types/array.c +++ b/types/array.c @@ -23,7 +23,7 @@ static struct definition *_array_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index); + GQuark field_name, int index, const char *root_name); static void _array_definition_free(struct definition *definition); @@ -86,22 +86,30 @@ static struct definition * _array_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index) + GQuark field_name, int index, const char *root_name) { struct declaration_array *array_declaration = container_of(declaration, struct declaration_array, p); struct definition_array *array; - uint64_t i; + int ret; + int i; array = g_new(struct definition_array, 1); declaration_ref(&array_declaration->p); array->p.declaration = declaration; array->declaration = array_declaration; array->p.ref = 1; - array->p.index = index; + /* + * Use INT_MAX order to ensure that all fields of the parent + * scope are seen as being prior to this scope. + */ + array->p.index = root_name ? INT_MAX : index; array->p.name = field_name; - array->p.path = new_definition_path(parent_scope, field_name); - array->scope = new_definition_scope(parent_scope, field_name); + array->p.path = new_definition_path(parent_scope, field_name, root_name); + array->scope = new_definition_scope(parent_scope, field_name, root_name); + ret = register_field_definition(field_name, &array->p, + parent_scope); + assert(!ret); array->elems = g_ptr_array_sized_new(array_declaration->len); g_ptr_array_set_size(array->elems, array_declaration->len); for (i = 0; i < array_declaration->len; i++) { @@ -110,16 +118,31 @@ struct definition * GQuark name; str = g_string_new(""); - g_string_printf(str, "[%" PRIu64 "]", i); + g_string_printf(str, "[%u]", (unsigned int) i); name = g_quark_from_string(str->str); (void) g_string_free(str, TRUE); field = (struct definition **) &g_ptr_array_index(array->elems, i); *field = array_declaration->elem->definition_new(array_declaration->elem, array->scope, - name, i); + name, i, NULL); + if (!*field) + goto error; } return &array->p; + +error: + for (i--; i >= 0; i--) { + struct definition *field; + + field = g_ptr_array_index(array->elems, i); + field->declaration->definition_free(field); + } + (void) g_ptr_array_free(array->elems, TRUE); + free_definition_scope(array->scope); + declaration_unref(array->p.declaration); + g_free(array); + return NULL; } static diff --git a/types/enum.c b/types/enum.c index 068651c7..b60c9c56 100644 --- a/types/enum.c +++ b/types/enum.c @@ -24,7 +24,8 @@ static struct definition *_enum_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index); + GQuark field_name, int index, + const char *root_name); static void _enum_definition_free(struct definition *definition); @@ -396,26 +397,36 @@ static struct definition * _enum_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index) + GQuark field_name, int index, + const char *root_name) { struct declaration_enum *enum_declaration = container_of(declaration, struct declaration_enum, p); struct definition_enum *_enum; struct definition *definition_integer_parent; + int ret; _enum = g_new(struct definition_enum, 1); declaration_ref(&enum_declaration->p); _enum->p.declaration = declaration; _enum->declaration = enum_declaration; _enum->p.ref = 1; - _enum->p.index = index; + /* + * Use INT_MAX order to ensure that all fields of the parent + * scope are seen as being prior to this scope. + */ + _enum->p.index = root_name ? INT_MAX : index; _enum->p.name = field_name; - _enum->p.path = new_definition_path(parent_scope, field_name); + _enum->p.path = new_definition_path(parent_scope, field_name, root_name); + _enum->scope = new_definition_scope(parent_scope, field_name, root_name); _enum->value = NULL; + ret = register_field_definition(field_name, &_enum->p, + parent_scope); + assert(!ret); definition_integer_parent = enum_declaration->integer_declaration->p.definition_new(&enum_declaration->integer_declaration->p, - parent_scope, - g_quark_from_static_string("container"), 0); + _enum->scope, + g_quark_from_static_string("container"), 0, NULL); _enum->integer = container_of(definition_integer_parent, struct definition_integer, p); return &_enum->p; diff --git a/types/float.c b/types/float.c index 2306d94f..5ae831ce 100644 --- a/types/float.c +++ b/types/float.c @@ -23,7 +23,8 @@ static struct definition *_float_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index); + GQuark field_name, int index, + const char *root_name); static void _float_definition_free(struct definition *definition); @@ -69,43 +70,53 @@ static struct definition * _float_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index) + GQuark field_name, int index, + const char *root_name) { struct declaration_float *float_declaration = container_of(declaration, struct declaration_float, p); struct definition_float *_float; struct definition *tmp; + int ret; _float = g_new(struct definition_float, 1); declaration_ref(&float_declaration->p); _float->p.declaration = declaration; _float->declaration = float_declaration; + _float->scope = new_definition_scope(parent_scope, field_name, root_name); + _float->p.path = new_definition_path(parent_scope, field_name, root_name); if (float_declaration->byte_order == LITTLE_ENDIAN) { tmp = float_declaration->mantissa->p.definition_new(&float_declaration->mantissa->p, - parent_scope, g_quark_from_static_string("mantissa"), 0); + _float->scope, g_quark_from_static_string("mantissa"), 0, NULL); _float->mantissa = container_of(tmp, struct definition_integer, p); tmp = float_declaration->exp->p.definition_new(&float_declaration->exp->p, - parent_scope, g_quark_from_static_string("exp"), 1); + _float->scope, g_quark_from_static_string("exp"), 1, NULL); _float->exp = container_of(tmp, struct definition_integer, p); tmp = float_declaration->sign->p.definition_new(&float_declaration->sign->p, - parent_scope, g_quark_from_static_string("sign"), 2); + _float->scope, g_quark_from_static_string("sign"), 2, NULL); _float->sign = container_of(tmp, struct definition_integer, p); } else { tmp = float_declaration->sign->p.definition_new(&float_declaration->sign->p, - parent_scope, g_quark_from_static_string("sign"), 0); + _float->scope, g_quark_from_static_string("sign"), 0, NULL); _float->sign = container_of(tmp, struct definition_integer, p); tmp = float_declaration->exp->p.definition_new(&float_declaration->exp->p, - parent_scope, g_quark_from_static_string("exp"), 1); + _float->scope, g_quark_from_static_string("exp"), 1, NULL); _float->exp = container_of(tmp, struct definition_integer, p); tmp = float_declaration->mantissa->p.definition_new(&float_declaration->mantissa->p, - parent_scope, g_quark_from_static_string("mantissa"), 2); + _float->scope, g_quark_from_static_string("mantissa"), 2, NULL); _float->mantissa = container_of(tmp, struct definition_integer, p); } _float->p.ref = 1; - _float->p.index = index; + /* + * Use INT_MAX order to ensure that all fields of the parent + * scope are seen as being prior to this scope. + */ + _float->p.index = root_name ? INT_MAX : index; _float->p.name = field_name; - _float->p.path = new_definition_path(parent_scope, field_name); _float->value = 0.0; + ret = register_field_definition(field_name, &_float->p, + parent_scope); + assert(!ret); return &_float->p; } diff --git a/types/integer.c b/types/integer.c index 059c6d89..940963a5 100644 --- a/types/integer.c +++ b/types/integer.c @@ -24,7 +24,8 @@ static struct definition *_integer_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index); + GQuark field_name, int index, + const char *root_name); static void _integer_definition_free(struct definition *definition); @@ -60,21 +61,31 @@ static struct definition * _integer_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index) + GQuark field_name, int index, + const char *root_name) { struct declaration_integer *integer_declaration = container_of(declaration, struct declaration_integer, p); struct definition_integer *integer; + int ret; integer = g_new(struct definition_integer, 1); declaration_ref(&integer_declaration->p); integer->p.declaration = declaration; integer->declaration = integer_declaration; integer->p.ref = 1; - integer->p.index = index; + /* + * Use INT_MAX order to ensure that all fields of the parent + * scope are seen as being prior to this scope. + */ + integer->p.index = root_name ? INT_MAX : index; integer->p.name = field_name; - integer->p.path = new_definition_path(parent_scope, field_name); + integer->p.path = new_definition_path(parent_scope, field_name, + root_name); integer->value._unsigned = 0; + ret = register_field_definition(field_name, &integer->p, + parent_scope); + assert(!ret); return &integer->p; } diff --git a/types/sequence.c b/types/sequence.c index f4262cdb..119522d7 100644 --- a/types/sequence.c +++ b/types/sequence.c @@ -20,14 +20,11 @@ #include #include -#ifndef max -#define max(a, b) ((a) < (b) ? (b) : (a)) -#endif - static struct definition *_sequence_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index); + GQuark field_name, int index, + const char *root_name); static void _sequence_definition_free(struct definition *definition); @@ -40,10 +37,7 @@ int sequence_rw(struct stream_pos *pos, struct definition *definition) uint64_t len, oldlen, i; int ret; - ret = generic_rw(pos, &sequence_definition->len->p); - if (ret) - return ret; - len = sequence_definition->len->value._unsigned; + len = sequence_definition->length->value._unsigned; /* * Yes, large sequences could be _painfully slow_ to parse due * to memory allocation for each event read. At least, never @@ -69,7 +63,7 @@ int sequence_rw(struct stream_pos *pos, struct definition *definition) field = (struct definition **) &g_ptr_array_index(sequence_definition->elems, i); *field = sequence_declaration->elem->definition_new(sequence_declaration->elem, sequence_definition->scope, - name, i); + name, i, NULL); ret = generic_rw(pos, *field); if (ret) return ret; @@ -84,13 +78,13 @@ void _sequence_declaration_free(struct declaration *declaration) container_of(declaration, struct declaration_sequence, p); free_declaration_scope(sequence_declaration->scope); - declaration_unref(&sequence_declaration->len_declaration->p); + g_array_free(sequence_declaration->length_name, TRUE); declaration_unref(sequence_declaration->elem); g_free(sequence_declaration); } struct declaration_sequence * - sequence_declaration_new(struct declaration_integer *len_declaration, + sequence_declaration_new(const char *length, struct declaration *elem_declaration, struct declaration_scope *parent_scope) { @@ -99,14 +93,15 @@ struct declaration_sequence * sequence_declaration = g_new(struct declaration_sequence, 1); declaration = &sequence_declaration->p; - assert(!len_declaration->signedness); - declaration_ref(&len_declaration->p); - sequence_declaration->len_declaration = len_declaration; + + sequence_declaration->length_name = g_array_new(FALSE, TRUE, sizeof(GQuark)); + append_scope_path(length, sequence_declaration->length_name); + declaration_ref(elem_declaration); sequence_declaration->elem = elem_declaration; sequence_declaration->scope = new_declaration_scope(parent_scope); declaration->id = CTF_TYPE_SEQUENCE; - declaration->alignment = max(len_declaration->p.alignment, elem_declaration->alignment); + declaration->alignment = elem_declaration->alignment; declaration->declaration_free = _sequence_declaration_free; declaration->definition_new = _sequence_definition_new; declaration->definition_free = _sequence_definition_free; @@ -117,29 +112,53 @@ struct declaration_sequence * static struct definition *_sequence_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index) + GQuark field_name, int index, + const char *root_name) { struct declaration_sequence *sequence_declaration = container_of(declaration, struct declaration_sequence, p); struct definition_sequence *sequence; struct definition *len_parent; + int ret; sequence = g_new(struct definition_sequence, 1); declaration_ref(&sequence_declaration->p); sequence->p.declaration = declaration; sequence->declaration = sequence_declaration; sequence->p.ref = 1; - sequence->p.index = index; + /* + * Use INT_MAX order to ensure that all fields of the parent + * scope are seen as being prior to this scope. + */ + sequence->p.index = root_name ? INT_MAX : index; sequence->p.name = field_name; - sequence->p.path = new_definition_path(parent_scope, field_name); - sequence->scope = new_definition_scope(parent_scope, field_name); - len_parent = sequence_declaration->len_declaration->p.definition_new(&sequence_declaration->len_declaration->p, - sequence->scope, - g_quark_from_static_string("length"), 0); - sequence->len = + sequence->p.path = new_definition_path(parent_scope, field_name, root_name); + sequence->scope = new_definition_scope(parent_scope, field_name, root_name); + ret = register_field_definition(field_name, &sequence->p, + parent_scope); + assert(!ret); + len_parent = lookup_definition(sequence->scope->scope_path, + sequence_declaration->length_name, + parent_scope); + if (!len_parent) { + printf("[error] Lookup for sequence length field failed.\n"); + goto error; + } + sequence->length = container_of(len_parent, struct definition_integer, p); + if (sequence->length->declaration->signedness) { + printf("[error] Sequence length field should be unsigned.\n"); + goto error; + } + definition_ref(len_parent); sequence->elems = g_ptr_array_new(); return &sequence->p; + +error: + free_definition_scope(sequence->scope); + declaration_unref(&sequence_declaration->p); + g_free(sequence); + return NULL; } static @@ -147,7 +166,7 @@ void _sequence_definition_free(struct definition *definition) { struct definition_sequence *sequence = container_of(definition, struct definition_sequence, p); - struct definition *len_definition = &sequence->len->p; + struct definition *len_definition = &sequence->length->p; uint64_t i; for (i = 0; i < sequence->elems->len; i++) { @@ -157,7 +176,7 @@ void _sequence_definition_free(struct definition *definition) field->declaration->definition_free(field); } (void) g_ptr_array_free(sequence->elems, TRUE); - len_definition->declaration->definition_free(len_definition); + definition_unref(len_definition); free_definition_scope(sequence->scope); declaration_unref(sequence->p.declaration); g_free(sequence); @@ -165,12 +184,12 @@ void _sequence_definition_free(struct definition *definition) uint64_t sequence_len(struct definition_sequence *sequence) { - return sequence->len->value._unsigned; + return sequence->length->value._unsigned; } struct definition *sequence_index(struct definition_sequence *sequence, uint64_t i) { - if (i >= sequence->len->value._unsigned) + if (i >= sequence->length->value._unsigned) return NULL; assert(i < sequence->elems->len); return g_ptr_array_index(sequence->elems, i); diff --git a/types/string.c b/types/string.c index 0f261f41..47e0970e 100644 --- a/types/string.c +++ b/types/string.c @@ -23,7 +23,8 @@ static struct definition *_string_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index); + GQuark field_name, int index, + const char *root_name); static void _string_definition_free(struct definition *definition); @@ -55,23 +56,33 @@ static struct definition * _string_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index) + GQuark field_name, int index, + const char *root_name) { struct declaration_string *string_declaration = container_of(declaration, struct declaration_string, p); struct definition_string *string; + int ret; string = g_new(struct definition_string, 1); declaration_ref(&string_declaration->p); string->p.declaration = declaration; string->declaration = string_declaration; string->p.ref = 1; - string->p.index = index; + /* + * Use INT_MAX order to ensure that all fields of the parent + * scope are seen as being prior to this scope. + */ + string->p.index = root_name ? INT_MAX : index; string->p.name = field_name; - string->p.path = new_definition_path(parent_scope, field_name); + string->p.path = new_definition_path(parent_scope, field_name, + root_name); string->value = NULL; string->len = 0; string->alloc_len = 0; + ret = register_field_definition(field_name, &string->p, + parent_scope); + assert(!ret); return &string->p; } diff --git a/types/struct.c b/types/struct.c index a6b7e3b9..a9703b28 100644 --- a/types/struct.c +++ b/types/struct.c @@ -18,6 +18,7 @@ #include #include +#include #ifndef max #define max(a, b) ((a) < (b) ? (b) : (a)) @@ -26,7 +27,8 @@ static struct definition *_struct_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index); + GQuark field_name, int index, + const char *root_name); static void _struct_definition_free(struct definition *definition); @@ -95,12 +97,13 @@ static struct definition * _struct_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index) + GQuark field_name, int index, + const char *root_name) { struct declaration_struct *struct_declaration = container_of(declaration, struct declaration_struct, p); struct definition_struct *_struct; - unsigned long i; + int i; int ret; _struct = g_new(struct definition_struct, 1); @@ -108,10 +111,19 @@ struct definition * _struct->p.declaration = declaration; _struct->declaration = struct_declaration; _struct->p.ref = 1; - _struct->p.index = index; + /* + * Use INT_MAX order to ensure that all fields of the parent + * scope are seen as being prior to this scope. + */ + _struct->p.index = root_name ? INT_MAX : index; _struct->p.name = field_name; - _struct->p.path = new_definition_path(parent_scope, field_name); - _struct->scope = new_definition_scope(parent_scope, field_name); + _struct->p.path = new_definition_path(parent_scope, field_name, root_name); + _struct->scope = new_definition_scope(parent_scope, field_name, root_name); + + ret = register_field_definition(field_name, &_struct->p, + parent_scope); + assert(!ret || ret == -EPERM); + _struct->fields = g_ptr_array_sized_new(DEFAULT_NR_STRUCT_FIELDS); g_ptr_array_set_size(_struct->fields, struct_declaration->fields->len); for (i = 0; i < struct_declaration->fields->len; i++) { @@ -123,13 +135,21 @@ struct definition * *field = declaration_field->declaration->definition_new(declaration_field->declaration, _struct->scope, - declaration_field->name, i); - ret = register_field_definition(declaration_field->name, - *field, - _struct->scope); - assert(!ret); + declaration_field->name, i, NULL); + if (!*field) + goto error; } return &_struct->p; + +error: + for (i--; i >= 0; i--) { + struct definition *field = g_ptr_array_index(_struct->fields, i); + definition_unref(field); + } + free_definition_scope(_struct->scope); + declaration_unref(&struct_declaration->p); + g_free(_struct); + return NULL; } static diff --git a/types/types.c b/types/types.c index e6339469..17dcffb9 100644 --- a/types/types.c +++ b/types/types.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -110,13 +111,36 @@ static int compare_paths(GArray *a, GArray *b, int len) static int is_path_child_of(GArray *path, GArray *maybe_parent) { - if (path->len <= maybe_parent->len) - return 0; + int i, ret; + + if (babeltrace_debug) { + int need_dot = 0; + + printf_debug("Is path \""); + for (i = 0; i < path->len; need_dot = 1, i++) + printf("%s%s", need_dot ? "." : "", + g_quark_to_string(g_array_index(path, GQuark, i))); + need_dot = 0; + printf("\" child of \""); + for (i = 0; i < maybe_parent->len; need_dot = 1, i++) + printf("%s%s", need_dot ? "." : "", + g_quark_to_string(g_array_index(maybe_parent, GQuark, i))); + printf("\" ? "); + } + + if (path->len <= maybe_parent->len) { + ret = 0; + goto end; + } if (compare_paths(path, maybe_parent, maybe_parent->len) == maybe_parent->len) - return 1; + ret = 1; else - return 0; + ret = 0; +end: + if (babeltrace_debug) + printf("%s\n", ret ? "Yes" : "No"); + return ret; } static struct definition_scope * @@ -187,14 +211,41 @@ struct definition * GQuark last; int index; - while (scope) { - /* going up in the hierarchy. Check where we come from. */ - assert(is_path_child_of(cur_path, scope->scope_path)); - assert(cur_path->len - scope->scope_path->len == 1); + /* Going up in the hierarchy. Check where we come from. */ + assert(is_path_child_of(cur_path, scope->scope_path)); + assert(cur_path->len - scope->scope_path->len == 1); + + /* + * First, check if the target name is size one, present in + * our parent path, located prior to us. + */ + if (lookup_path->len == 1) { + last = g_array_index(lookup_path, GQuark, 0); + lookup_definition = lookup_field_definition_scope(last, scope); last = g_array_index(cur_path, GQuark, cur_path->len - 1); definition = lookup_field_definition_scope(last, scope); assert(definition); - index = definition->index; + if (lookup_definition && lookup_definition->index < definition->index) + return lookup_definition; + else + return NULL; + } + + while (scope) { + if (is_path_child_of(cur_path, scope->scope_path) && + cur_path->len - scope->scope_path->len == 1) { + last = g_array_index(cur_path, GQuark, cur_path->len - 1); + definition = lookup_field_definition_scope(last, scope); + assert(definition); + index = definition->index; + } else { + /* + * Getting to a dynamic scope parent. We are + * guaranteed that the parent is entirely + * located before the child. + */ + index = -1; + } lookup: if (is_path_child_of(lookup_path, scope->scope_path)) { /* Means we can lookup the field in this scope */ @@ -222,7 +273,6 @@ lookup: goto lookup; } } else { - assert(index != -1); /* lookup_path is within an upper scope */ cur_path = scope->scope_path; scope = scope->parent_scope; @@ -234,7 +284,7 @@ lookup: int register_field_definition(GQuark field_name, struct definition *definition, struct definition_scope *scope) { - if (!field_name) + if (!scope || !field_name) return -EPERM; /* Only lookup in local scope */ @@ -244,7 +294,7 @@ int register_field_definition(GQuark field_name, struct definition *definition, g_hash_table_insert(scope->definitions, (gpointer) (unsigned long) field_name, definition); - definition_ref(definition); + /* Don't keep reference on definition */ return 0; } @@ -459,9 +509,8 @@ static struct definition_scope * { struct definition_scope *scope = g_new(struct definition_scope, 1); - scope->definitions = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, - (GDestroyNotify) definition_unref); + scope->definitions = g_hash_table_new(g_direct_hash, + g_direct_equal); scope->parent_scope = parent_scope; scope->scope_path = g_array_sized_new(FALSE, TRUE, sizeof(GQuark), scope_path_len); @@ -469,49 +518,74 @@ static struct definition_scope * return scope; } -GQuark new_definition_path(struct definition_scope *parent_scope, GQuark field_name) +GQuark new_definition_path(struct definition_scope *parent_scope, + GQuark field_name, const char *root_name) { GQuark path; GString *str; gchar *c_str; int i; + int need_dot = 0; str = g_string_new(""); - if (parent_scope) { + if (root_name) { + g_string_append(str, root_name); + need_dot = 1; + } else if (parent_scope) { for (i = 0; i < parent_scope->scope_path->len; i++) { GQuark q = g_array_index(parent_scope->scope_path, GQuark, i); if (!q) continue; + if (need_dot) + g_string_append(str, "."); g_string_append(str, g_quark_to_string(q)); - g_string_append(str, "."); + need_dot = 1; } } - if (field_name) + if (field_name) { + if (need_dot) + g_string_append(str, "."); g_string_append(str, g_quark_to_string(field_name)); + } c_str = g_string_free(str, FALSE); if (c_str[0] == '\0') return 0; path = g_quark_from_string(c_str); + printf_debug("new definition path: %s\n", c_str); g_free(c_str); return path; } struct definition_scope * new_definition_scope(struct definition_scope *parent_scope, - GQuark field_name) + GQuark field_name, const char *root_name) { struct definition_scope *scope; - int scope_path_len = 1; - if (parent_scope) + if (root_name) { + scope = _new_definition_scope(parent_scope, 0); + append_scope_path(root_name, scope->scope_path); + } else { + int scope_path_len = 1; + + assert(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, + scope = _new_definition_scope(parent_scope, scope_path_len); + memcpy(scope->scope_path->data, parent_scope->scope_path->data, sizeof(GQuark) * (scope_path_len - 1)); - g_array_index(scope->scope_path, GQuark, scope_path_len - 1) = - field_name; + g_array_index(scope->scope_path, GQuark, scope_path_len - 1) = + field_name; + } + if (babeltrace_debug) { + int i, need_dot = 0; + + printf_debug("new definition scope: "); + for (i = 0; i < scope->scope_path->len; need_dot = 1, i++) + printf("%s%s", need_dot ? "." : "", + g_quark_to_string(g_array_index(scope->scope_path, GQuark, i))); + printf("\n"); + } return scope; } @@ -549,19 +623,6 @@ void append_scope_path(const char *path, GArray *q) } } -void set_dynamic_definition_scope(struct definition *definition, - struct definition_scope *scope, - const char *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. - */ - definition->index = INT_MAX; -} - void free_definition_scope(struct definition_scope *scope) { g_array_free(scope->scope_path, TRUE); diff --git a/types/variant.c b/types/variant.c index 8a781f67..96b66508 100644 --- a/types/variant.c +++ b/types/variant.c @@ -23,7 +23,8 @@ static struct definition *_variant_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index); + GQuark field_name, int index, + const char *root_name); static void _variant_definition_free(struct definition *definition); @@ -161,22 +162,33 @@ static struct definition * _variant_definition_new(struct declaration *declaration, struct definition_scope *parent_scope, - GQuark field_name, int index) + GQuark field_name, int index, + const char *root_name) { struct declaration_variant *variant_declaration = container_of(declaration, struct declaration_variant, p); struct definition_variant *variant; unsigned long i; + int ret; variant = g_new(struct definition_variant, 1); declaration_ref(&variant_declaration->p); variant->p.declaration = declaration; variant->declaration = variant_declaration; variant->p.ref = 1; - variant->p.index = index; + /* + * Use INT_MAX order to ensure that all fields of the parent + * scope are seen as being prior to this scope. + */ + variant->p.index = root_name ? INT_MAX : index; variant->p.name = field_name; - variant->p.path = new_definition_path(parent_scope, field_name); - variant->scope = new_definition_scope(parent_scope, field_name); + variant->p.path = new_definition_path(parent_scope, field_name, root_name); + variant->scope = new_definition_scope(parent_scope, field_name, root_name); + + ret = register_field_definition(field_name, &variant->p, + parent_scope); + assert(!ret); + variant->enum_tag = lookup_definition(variant->scope->scope_path, variant_declaration->tag_name, parent_scope); @@ -200,7 +212,9 @@ struct definition * */ *field = declaration_field->declaration->definition_new(declaration_field->declaration, variant->scope, - declaration_field->name, 0); + declaration_field->name, 0, NULL); + if (!*field) + goto error; } variant->current_field = NULL; return &variant->p;