From: Mathieu Desnoyers Date: Fri, 13 May 2011 21:41:19 +0000 (-0400) Subject: Add structure align() attribute, fix empty string support in definition paths X-Git-Tag: v0.1~56 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=b7e35badc2eac52e27b802a9078bfb7c8f3b04a7 Add structure align() attribute, fix empty string support in definition paths Signed-off-by: Mathieu Desnoyers --- diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index f4432a89..bdebaeb3 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -693,8 +693,6 @@ int ctf_open_trace_read(struct ctf_trace *td, const char *path, int flags) goto error_dirfd; } - td->streams = g_ptr_array_new(); - /* * Keep the metadata file separate. */ diff --git a/formats/ctf/metadata/ctf-ast.h b/formats/ctf/metadata/ctf-ast.h index bf6ddb42..3d8d8b00 100644 --- a/formats/ctf/metadata/ctf-ast.h +++ b/formats/ctf/metadata/ctf-ast.h @@ -245,6 +245,7 @@ struct ctf_node { /* list of typedef, typealias and declarations */ struct cds_list_head declaration_list; int has_body; + struct cds_list_head min_align; /* align() attribute */ } _struct; } u; }; diff --git a/formats/ctf/metadata/ctf-lexer.l b/formats/ctf/metadata/ctf-lexer.l index ff4f8a51..7e81add5 100644 --- a/formats/ctf/metadata/ctf-lexer.l +++ b/formats/ctf/metadata/ctf-lexer.l @@ -93,6 +93,7 @@ L\" BEGIN(string_lit); return STRING_LITERAL_START; "." return DOT; = return EQUAL; "," return COMMA; +align setstring(yyextra, yylval, yytext); return TOK_ALIGN; const setstring(yyextra, yylval, yytext); return CONST; char setstring(yyextra, yylval, yytext); return CHAR; double setstring(yyextra, yylval, yytext); return DOUBLE; diff --git a/formats/ctf/metadata/ctf-parser.y b/formats/ctf/metadata/ctf-parser.y index 8fc83dfa..ed766952 100644 --- a/formats/ctf/metadata/ctf-parser.y +++ b/formats/ctf/metadata/ctf-parser.y @@ -304,6 +304,7 @@ static struct ctf_node *make_node(struct ctf_scanner *scanner, break; case NODE_STRUCT: CDS_INIT_LIST_HEAD(&node->u._struct.declaration_list); + CDS_INIT_LIST_HEAD(&node->u._struct.min_align); break; case NODE_UNKNOWN: @@ -858,7 +859,7 @@ void ctf_scanner_free(struct ctf_scanner *scanner) */ %expect 2 %start file -%token CHARACTER_CONSTANT_START SQUOTE STRING_LITERAL_START DQUOTE ESCSEQ CHAR_STRING_TOKEN LSBRAC RSBRAC LPAREN RPAREN LBRAC RBRAC RARROW STAR PLUS MINUS LT GT TYPEASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA CONST CHAR DOUBLE ENUM EVENT FLOATING_POINT FLOAT INTEGER INT LONG SHORT SIGNED STREAM STRING STRUCT TRACE TYPEALIAS TYPEDEF UNSIGNED VARIANT VOID _BOOL _COMPLEX _IMAGINARY DECIMAL_CONSTANT OCTAL_CONSTANT HEXADECIMAL_CONSTANT +%token CHARACTER_CONSTANT_START SQUOTE STRING_LITERAL_START DQUOTE ESCSEQ CHAR_STRING_TOKEN LSBRAC RSBRAC LPAREN RPAREN LBRAC RBRAC RARROW STAR PLUS MINUS LT GT TYPEASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA CONST CHAR DOUBLE ENUM EVENT FLOATING_POINT FLOAT INTEGER INT LONG SHORT SIGNED STREAM STRING STRUCT TRACE TYPEALIAS TYPEDEF UNSIGNED VARIANT VOID _BOOL _COMPLEX _IMAGINARY DECIMAL_CONSTANT OCTAL_CONSTANT HEXADECIMAL_CONSTANT TOK_ALIGN %token IDENTIFIER ID_TYPE %token ERROR %union @@ -971,6 +972,8 @@ keywords: { $$ = yylval.gs; } | TRACE { $$ = yylval.gs; } + | TOK_ALIGN + { $$ = yylval.gs; } ; /* 1.5 Constants */ @@ -1595,6 +1598,32 @@ struct_type_specifier: $$->u._struct.has_body = 0; $$->u._struct.name = $1->s; } + | struct_declaration_begin struct_or_variant_declaration_list struct_declaration_end TOK_ALIGN LPAREN unary_expression RPAREN + { + $$ = make_node(scanner, NODE_STRUCT); + $$->u._struct.has_body = 1; + cds_list_add_tail(&($6)->siblings, &$$->u._struct.min_align); + if ($2 && set_parent_node($2, $$)) + reparent_error(scanner, "struct reparent error"); + } + | IDENTIFIER struct_declaration_begin struct_or_variant_declaration_list struct_declaration_end TOK_ALIGN LPAREN unary_expression RPAREN + { + $$ = make_node(scanner, NODE_STRUCT); + $$->u._struct.has_body = 1; + $$->u._struct.name = $1->s; + cds_list_add_tail(&($7)->siblings, &$$->u._struct.min_align); + if ($3 && set_parent_node($3, $$)) + reparent_error(scanner, "struct reparent error"); + } + | ID_TYPE struct_declaration_begin struct_or_variant_declaration_list struct_declaration_end TOK_ALIGN LPAREN unary_expression RPAREN + { + $$ = make_node(scanner, NODE_STRUCT); + $$->u._struct.has_body = 1; + $$->u._struct.name = $1->s; + cds_list_add_tail(&($7)->siblings, &$$->u._struct.min_align); + if ($3 && set_parent_node($3, $$)) + reparent_error(scanner, "struct reparent error"); + } ; struct_declaration_begin: diff --git a/formats/ctf/metadata/ctf-test/succeed/ctf-embedded-1.txt b/formats/ctf/metadata/ctf-test/succeed/ctf-embedded-1.txt index 4a97cdf7..1de88232 100644 --- a/formats/ctf/metadata/ctf-test/succeed/ctf-embedded-1.txt +++ b/formats/ctf/metadata/ctf-test/succeed/ctf-embedded-1.txt @@ -21,7 +21,7 @@ stream { void *func_called; * events in this stream. void *called_from; */ uint32_t event_count; /* for debug */ - }; + }; }; /* diff --git a/formats/ctf/metadata/ctf-test/succeed/ctf-test-align-attribute.txt b/formats/ctf/metadata/ctf-test/succeed/ctf-test-align-attribute.txt new file mode 100644 index 00000000..f9eefe32 --- /dev/null +++ b/formats/ctf/metadata/ctf-test/succeed/ctf-test-align-attribute.txt @@ -0,0 +1,48 @@ +/* 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; } := uint32_t; +typealias integer { size = 32; align = 32; signed = false; } := 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 { + void *func_called; + void *called_from; + }; +}; + +event { + name = func_exit; + id = 1; + stream_id = 0; +}; diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 37d17f58..23734284 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -653,7 +653,8 @@ int ctf_variant_declaration_list_visit(FILE *fd, int depth, static 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 cds_list_head *min_align, + struct declaration_scope *declaration_scope, struct ctf_trace *trace) { struct declaration_struct *struct_declaration; @@ -672,6 +673,8 @@ struct declaration *ctf_declaration_struct_visit(FILE *fd, declaration_scope); return &struct_declaration->p; } else { + uint64_t min_align_value = 0; + /* For unnamed struct, create type */ /* For named struct (with body), create type and add to declaration scope */ if (name) { @@ -682,7 +685,16 @@ struct declaration *ctf_declaration_struct_visit(FILE *fd, return NULL; } } - struct_declaration = struct_declaration_new(declaration_scope); + if (!cds_list_empty(min_align)) { + ret = get_unary_unsigned(min_align, &min_align_value); + if (ret) { + fprintf(fd, "[error] %s: unexpected unary expression for structure \"align\" attribute\n", __func__); + ret = -EINVAL; + goto error; + } + } + struct_declaration = struct_declaration_new(declaration_scope, + min_align_value); cds_list_for_each_entry(iter, declaration_list, siblings) { ret = ctf_struct_declaration_list_visit(fd, depth + 1, iter, struct_declaration, trace); @@ -1265,6 +1277,7 @@ struct declaration *ctf_type_specifier_list_visit(FILE *fd, node->u._struct.name, &node->u._struct.declaration_list, node->u._struct.has_body, + &node->u._struct.min_align, declaration_scope, trace); case TYPESPEC_VARIANT: @@ -1978,6 +1991,7 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node, printf_verbose("CTF visitor: metadata construction... "); trace->root_declaration_scope = new_declaration_scope(NULL); + trace->streams = g_ptr_array_new(); trace->byte_order = byte_order; switch (node->type) { diff --git a/formats/ctf/metadata/ctf-visitor-parent-links.c b/formats/ctf/metadata/ctf-visitor-parent-links.c index 49d067c6..ce2fb0d9 100644 --- a/formats/ctf/metadata/ctf-visitor-parent-links.c +++ b/formats/ctf/metadata/ctf-visitor-parent-links.c @@ -401,6 +401,13 @@ int ctf_visitor_parent_links(FILE *fd, int depth, struct ctf_node *node) if (ret) return ret; } + cds_list_for_each_entry(iter, &node->u._struct.min_align, + siblings) { + iter->parent = node; + ret = ctf_visitor_parent_links(fd, depth + 1, iter); + if (ret) + return ret; + } break; case NODE_UNKNOWN: diff --git a/formats/ctf/metadata/ctf-visitor-semantic-validator.c b/formats/ctf/metadata/ctf-visitor-semantic-validator.c index af55eb48..be5ed8f4 100644 --- a/formats/ctf/metadata/ctf-visitor-semantic-validator.c +++ b/formats/ctf/metadata/ctf-visitor-semantic-validator.c @@ -70,14 +70,27 @@ int ctf_visitor_unary_expression(FILE *fd, int depth, struct ctf_node *node) * We are the length of a type declarator. */ switch (node->u.unary_expression.type) { - case UNARY_SIGNED_CONSTANT: case UNARY_UNSIGNED_CONSTANT: break; default: - fprintf(fd, "[error]: semantic error (children of type declarator and enum can only be numeric constants)\n"); + fprintf(fd, "[error]: semantic error (children of type declarator and enum can only be unsigned numeric constants)\n"); goto errperm; } break; /* OK */ + + case NODE_STRUCT: + /* + * We are the size of a struct align attribute. + */ + switch (node->u.unary_expression.type) { + case UNARY_UNSIGNED_CONSTANT: + break; + default: + fprintf(fd, "[error]: semantic error (structure alignment attribute can only be unsigned numeric constants)\n"); + goto errperm; + } + break; + case NODE_ENUMERATOR: /* The enumerator's parent has validated its validity already. */ break; /* OK */ @@ -106,7 +119,6 @@ int ctf_visitor_unary_expression(FILE *fd, int depth, struct ctf_node *node) case NODE_ENUM: case NODE_STRUCT_OR_VARIANT_DECLARATION: case NODE_VARIANT: - case NODE_STRUCT: default: goto errinval; } diff --git a/formats/ctf/metadata/ctf-visitor-xml.c b/formats/ctf/metadata/ctf-visitor-xml.c index f73c3671..0236fbae 100644 --- a/formats/ctf/metadata/ctf-visitor-xml.c +++ b/formats/ctf/metadata/ctf-visitor-xml.c @@ -677,6 +677,17 @@ int ctf_visitor_print_xml(FILE *fd, int depth, struct ctf_node *node) } print_tabs(fd, depth); fprintf(fd, "\n"); + if (!cds_list_empty(&node->u._struct.min_align)) { + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u._struct.min_align, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + } break; case NODE_UNKNOWN: diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 2c7650e6..a4dcdee9 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -427,7 +427,8 @@ struct declaration_string * string_declaration_new(enum ctf_string_encoding encoding); struct declaration_struct * - struct_declaration_new(struct declaration_scope *parent_scope); + struct_declaration_new(struct declaration_scope *parent_scope, + uint64_t min_align); void struct_declaration_add_field(struct declaration_struct *struct_declaration, const char *field_name, struct declaration *field_declaration); diff --git a/types/struct.c b/types/struct.c index ba312111..a6b7e3b9 100644 --- a/types/struct.c +++ b/types/struct.c @@ -68,7 +68,8 @@ void _struct_declaration_free(struct declaration *declaration) } struct declaration_struct * - struct_declaration_new(struct declaration_scope *parent_scope) + struct_declaration_new(struct declaration_scope *parent_scope, + uint64_t min_align) { struct declaration_struct *struct_declaration; struct declaration *declaration; @@ -82,7 +83,7 @@ struct declaration_struct * DEFAULT_NR_STRUCT_FIELDS); struct_declaration->scope = new_declaration_scope(parent_scope); declaration->id = CTF_TYPE_STRUCT; - declaration->alignment = 1; + declaration->alignment = max(1, min_align); declaration->declaration_free = _struct_declaration_free; declaration->definition_new = _struct_definition_new; declaration->definition_free = _struct_definition_free; diff --git a/types/types.c b/types/types.c index 7369f30d..e6339469 100644 --- a/types/types.c +++ b/types/types.c @@ -481,13 +481,17 @@ GQuark new_definition_path(struct definition_scope *parent_scope, GQuark field_n for (i = 0; i < parent_scope->scope_path->len; i++) { GQuark q = g_array_index(parent_scope->scope_path, GQuark, i); - + if (!q) + continue; g_string_append(str, g_quark_to_string(q)); g_string_append(str, "."); } } - g_string_append(str, g_quark_to_string(field_name)); + if (field_name) + 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); g_free(c_str); return path;