goto error_dirfd;
}
- td->streams = g_ptr_array_new();
-
/*
* Keep the metadata file separate.
*/
/* 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;
};
"." 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;
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:
*/
%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 <gs> IDENTIFIER ID_TYPE
%token ERROR
%union
{ $$ = yylval.gs; }
| TRACE
{ $$ = yylval.gs; }
+ | TOK_ALIGN
+ { $$ = yylval.gs; }
;
/* 1.5 Constants */
$$->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:
void *func_called; * events in this stream.
void *called_from; */
uint32_t event_count; /* for debug */
- };
+ };
};
/*
--- /dev/null
+/* 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;
+};
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;
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) {
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);
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:
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) {
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:
* 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 */
case NODE_ENUM:
case NODE_STRUCT_OR_VARIANT_DECLARATION:
case NODE_VARIANT:
- case NODE_STRUCT:
default:
goto errinval;
}
}
print_tabs(fd, depth);
fprintf(fd, "</struct>\n");
+ if (!cds_list_empty(&node->u._struct.min_align)) {
+ print_tabs(fd, depth);
+ fprintf(fd, "<align>\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, "</align>\n");
+ }
break;
case NODE_UNKNOWN:
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);
}
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;
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;
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;