From 05628561ca57ff5d269571a72a12cb86854c5f70 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 26 Mar 2011 16:26:18 -0400 Subject: [PATCH] I/O structures accessors generation (work in progress) Signed-off-by: Mathieu Desnoyers --- formats/ctf/metadata/Makefile.am | 1 + formats/ctf/metadata/ctf-parser.y | 4 + .../metadata/ctf-visitor-generate-io-struct.c | 938 ++++++++++++++++++ include/babeltrace/ctf/metadata.h | 29 +- include/babeltrace/types.h | 14 + types/array.c | 1 + types/enum.c | 1 + types/float.c | 1 + types/integer.c | 1 + types/sequence.c | 1 + types/string.c | 1 + types/struct.c | 1 + types/variant.c | 1 + 13 files changed, 986 insertions(+), 8 deletions(-) create mode 100644 formats/ctf/metadata/ctf-visitor-generate-io-struct.c diff --git a/formats/ctf/metadata/Makefile.am b/formats/ctf/metadata/Makefile.am index 00b12d27..499141eb 100644 --- a/formats/ctf/metadata/Makefile.am +++ b/formats/ctf/metadata/Makefile.am @@ -11,4 +11,5 @@ ctf_parser_test_SOURCES = \ ctf-parser-test.c ctf-visitor-xml.c \ ctf-visitor-parent-links.c \ ctf-visitor-semantic-validator.c \ + ctf-visitor-generate-io-struct.c \ ctf-lexer.l ctf-parser.y diff --git a/formats/ctf/metadata/ctf-parser.y b/formats/ctf/metadata/ctf-parser.y index f3b40d75..8d8c29ce 100644 --- a/formats/ctf/metadata/ctf-parser.y +++ b/formats/ctf/metadata/ctf-parser.y @@ -30,6 +30,10 @@ #include "ctf-parser.h" #include "ctf-ast.h" +/* + * TODO: support enum, variant and struct declarations in scopes. + */ + /* Join two lists, put "add" at the end of "head". */ static inline void _cds_list_splice_tail (struct cds_list_head *add, struct cds_list_head *head) diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c new file mode 100644 index 00000000..3bd4238c --- /dev/null +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -0,0 +1,938 @@ +/* + * ctf-visitor-generate-io-struct.c + * + * Common Trace Format Metadata Visitor (generate I/O structures). + * + * Copyright 2010 - Mathieu Desnoyers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ctf-scanner.h" +#include "ctf-parser.h" +#include "ctf-ast.h" + +#define fprintf_dbg(fd, fmt, args...) fprintf(fd, "%s: " fmt, __func__, ## args) + + +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_CONST: + fprintf(fd, "const"); + break; + case TYPESPEC_ID_TYPE: + fprintf(fd, "%s", node->u.type_specifier.id_type); + break; + + case TYPESPEC_UNKNOWN: + default: + fprintf(stderr, "[error] %s: unknown type specifier %d\n", __func__, + (int) node->u.type_specifier.type); + return -EINVAL; + } + fprintf(fd, "\"/>\n"); + return 0; +} + +static +int ctf_visitor_print_type_declarator(FILE *fd, int depth, struct ctf_node *node) +{ + int ret = 0; + struct ctf_node *iter; + + print_tabs(fd, depth); + fprintf(fd, "\n"); + depth++; + + if (!cds_list_empty(&node->u.type_declarator.pointers)) { + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, + siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + } + + switch (node->u.type_declarator.type) { + case TYPEDEC_ID: + if (node->u.type_declarator.u.id) { + print_tabs(fd, depth); + fprintf(fd, "u.type_declarator.u.id); + fprintf(fd, "\" />\n"); + } + break; + case TYPEDEC_NESTED: + if (node->u.type_declarator.u.nested.type_declarator) { + print_tabs(fd, depth); + fprintf(fd, "\n"); + ret = ctf_visitor_print_xml(fd, depth + 1, + node->u.type_declarator.u.nested.type_declarator); + if (ret) + return ret; + print_tabs(fd, depth); + fprintf(fd, "\n"); + } + if (node->u.type_declarator.u.nested.length) { + print_tabs(fd, depth); + fprintf(fd, "\n"); + ret = ctf_visitor_print_xml(fd, depth + 1, + node->u.type_declarator.u.nested.length); + if (ret) + return ret; + print_tabs(fd, depth); + fprintf(fd, "\n"); + } + if (node->u.type_declarator.u.nested.abstract_array) { + print_tabs(fd, depth); + fprintf(fd, "\n"); + print_tabs(fd, depth); + fprintf(fd, "\n"); + } + if (node->u.type_declarator.bitfield_len) { + print_tabs(fd, depth); + fprintf(fd, "\n"); + ret = ctf_visitor_print_xml(fd, depth + 1, + node->u.type_declarator.bitfield_len); + if (ret) + return ret; + print_tabs(fd, depth); + fprintf(fd, "\n"); + } + break; + case TYPEDEC_UNKNOWN: + default: + fprintf(stderr, "[error] %s: unknown type declarator %d\n", __func__, + (int) node->u.type_declarator.type); + return -EINVAL; + } + + depth--; + print_tabs(fd, depth); + fprintf(fd, "\n"); + return 0; +} + +/* + * String returned must be freed by the caller. + */ +static +char *concatenate_unary_strings(struct list_head *head) +{ + +} + +static +int get_unary_unsigned(struct list_head *head, uint64_t *value) +{ + +} + +static +int get_unary_uuid(struct list_head *head, uuid_t *uuid) +{ + +} + +static +struct ctf_stream *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id) +{ + if (trace->streams->len <= stream_id) + return NULL; + return g_ptr_array_index(trace->streams, stream_id); +} + +static +struct ctf_declaration *ctf_declaration_specifier_visit(FILE *fd, + int depth, struct list_head *head, + struct type_scope *type_scope, + struct declaration_scope *declaration_scope) +{ + +} + +/* + * Use declaration specifier visitor, and add resulting variant, struct + * or enum to the current type scope. + */ +static +int ctf_type_specifier_visit(FILE *fd, + int depth, struct list_head *head, + struct type_scope *type_scope, + struct declaration_scope *declaration_scope) +{ + +} + +static +int ctf_typedef_declarator_visit(FILE *fd, int depth, + struct list_head *declaration_specifier, + struct node *type_declarator, struct type_scope *type_scope, + struct declaration_scope *declaration_scope) +{ + /* + * Build the type using declaration specifier, then apply type + * declarator, add the resulting type to the current type scope. + */ + cds_list_for_each_entry(iter, declaration_specifier, siblings) { + + + } + return 0; +} + +static +int ctf_typedef_visit(FILE *fd, int depth, + struct list_head *declaration_specifier, + struct list_head *type_declarators, + struct type_scope *type_scope, + struct declaration_scope *declaration_scope) +{ + struct ctf_node *iter; + + cds_list_for_each_entry(iter, type_declarators, siblings) { + ret = ctf_typedef_declarator_visit(fd, depth + 1, + &node->u._typedef.declaration_specifier, iter, + type_scope, declaration_scope); + if (ret) + return ret; + } + return 0; +} + +static +int ctf_typealias_visit(FILE *fd, int depth, struct ctf_node *target, + struct ctf_node *alias, struct type_scope *type_scope, + struct declaration_scope *declaration_scope) +{ + /* Build target type, check that it is reachable in current type scope. */ + /* Only one type declarator is allowed */ + + /* Build alias type, add to current type scope. */ + /* Only one type declarator is allowed */ +} + +static +int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_event *event, struct ctf_trace *trace) +{ + int ret = 0; + + switch (node->type) { + case NODE_TYPEDEF: + ret = ctf_typedef_visit(fd, depth + 1, + &node->u._typedef.declaration_specifier, + &node->u._typedef.type_declarators, + event->type_scope, event->declaration_scope); + if (ret) + return ret; + break; + case NODE_TYPEALIAS: + ret = ctf_typealias_visit(fd, depth + 1, + &node->u.typealias.target, &node->u.typealias.alias + event->type_scope, event->declaration_scope); + if (ret) + return ret; + break; + case NODE_CTF_EXPRESSION: + { + char *left; + + left = concatenate_unary_strings(&node->u.ctf_expression.left); + if (!strcmp(left, "name")) { + char *right; + + if (CTF_EVENT_FIELD_IS_SET(event, name)) + 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__); + return -EINVAL; + } + event->name = g_quark_from_string(right); + free(right); + CTF_EVENT_SET_FIELD(event, name); + } else if (!strcmp(left, "id")) { + if (CTF_EVENT_FIELD_IS_SET(event, id)) + 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__); + return -EINVAL; + } + CTF_EVENT_SET_FIELD(event, id); + } else if (!strcmp(left, "stream_id")) { + if (CTF_EVENT_FIELD_IS_SET(event, stream_id)) + 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__); + 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); + return -EINVAL; + } + event->declaration_scope = new_declaration_scope(stream->declaration_scope); + if (!event->declaration_scope) { + fprintf(stderr, "[error] %s: Error allocating declaration scope\n", __func__); + return -EPERM; + } + CTF_EVENT_SET_FIELD(event, stream_id); + } else if (!strcmp(left, "context")) { + struct declaration *declaration; + + if (!event->declaration_scope) + return -EPERM; + declaration = ctf_declaration_specifier_visit(fd, depth, + &node->u.ctf_expression.right, + event->type_scope, event->declaration_scope); + if (!declaration) + return -EPERM; + if (declaration->type->id != CTF_TYPE_STRUCT) + return -EPERM; + event->context = container_of(declaration, struct declaration_struct, p); + } else if (!strcmp(left, "fields")) { + struct declaration *declaration; + + if (!event->declaration_scope) + return -EPERM; + declaration = ctf_declaration_specifier_visit(fd, depth, + &node->u.ctf_expression.right, + event->type_scope, event->declaration_scope); + if (!declaration) + return -EPERM; + if (declaration->type->id != CTF_TYPE_STRUCT) + return -EPERM; + event->fields = container_of(declaration, struct declaration_struct, p); + } + free(left); + break; + } + default: + return -EPERM; + /* TODO: declaration specifier should be added. */ + } + + return 0; +} + +static +int ctf_event_visit(FILE *fd, int depth, struct ctf_node *node, + struct type_scope *parent_type_scope, struct ctf_trace *trace) +{ + int ret = 0; + struct ctf_node *iter; + struct ctf_event *event; + + event = g_new0(struct ctf_event, 1); + event->type_scope = new_type_scope(parent_type_scope); + cds_list_for_each_entry(iter, &node->u.event.declaration_list, siblings) { + ret = ctf_event_declaration_visit(fd, depth + 1, iter, event, trace); + if (ret) + goto error; + } + if (!CTF_EVENT_FIELD_IS_SET(event, name)) { + ret = -EPERM; + goto error; + } + if (!CTF_EVENT_FIELD_IS_SET(event, id)) { + ret = -EPERM; + goto error; + } + if (!CTF_EVENT_FIELD_IS_SET(event, stream_id)) { + ret = -EPERM; + goto error; + } + if (event->stream->events_by_id->len <= event->id) + g_ptr_array_set_size(event->stream->events_by_id, event->id + 1); + g_ptr_array_index(event->stream->events_by_id, event->id) = event; + g_hash_table_insert(event->stream->event_quark_to_id, + (gpointer)(unsigned long) event->name, + &event->id); + return 0; + +error: + declaration_unref(event->fields); + declaration_unref(event->context); + free_declaration_scope(event->declaration_scope); + free_type_scope(event->type_scope); + g_free(event); + return ret; +} + + +static +int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream *stream, struct ctf_trace *trace) +{ + int ret = 0; + + switch (node->type) { + case NODE_TYPEDEF: + ret = ctf_typedef_visit(fd, depth + 1, + &node->u._typedef.declaration_specifier, + &node->u._typedef.type_declarators, + stream->type_scope, stream->declaration_scope); + if (ret) + return ret; + break; + case NODE_TYPEALIAS: + ret = ctf_typealias_visit(fd, depth + 1, + &node->u.typealias.target, &node->u.typealias.alias + stream->type_scope, stream->declaration_scope); + if (ret) + return ret; + break; + case NODE_CTF_EXPRESSION: + { + char *left; + + left = concatenate_unary_strings(&node->u.ctf_expression.left); + if (!strcmp(left, "stream_id")) { + if (CTF_EVENT_FIELD_IS_SET(event, stream_id)) + 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__); + return -EINVAL; + } + CTF_EVENT_SET_FIELD(event, stream_id); + } else if (!strcmp(left, "event_header")) { + struct declaration *declaration; + + declaration = ctf_declaration_specifier_visit(fd, depth, + &node->u.ctf_expression.right, + stream->type_scope, stream->declaration_scope); + if (!declaration) + return -EPERM; + if (declaration->type->id != CTF_TYPE_STRUCT) + return -EPERM; + stream->event_header = 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->type_scope, stream->declaration_scope); + if (!declaration) + return -EPERM; + if (declaration->type->id != CTF_TYPE_STRUCT) + return -EPERM; + stream->event_context = 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->type_scope, stream->declaration_scope); + if (!declaration) + return -EPERM; + if (declaration->type->id != CTF_TYPE_STRUCT) + return -EPERM; + stream->packet_context = container_of(declaration, struct declaration_struct, p); + } + free(left); + break; + } + default: + return -EPERM; + /* TODO: declaration specifier should be added. */ + } + + return 0; +} + +static +int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node, + struct type_scope *parent_type_scope, struct ctf_trace *trace) +{ + int ret = 0; + struct ctf_node *iter; + struct ctf_stream *stream; + + stream = g_new0(struct ctf_stream, 1); + stream->type_scope = new_type_scope(parent_type_scope); + stream->declaration_scope = new_declaration_scope(trace->declaration_scope); + stream->events_by_id = g_ptr_array_new(); + stream->event_quark_to_id = g_hash_table_new(g_int_hash, g_int_equal); + cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) { + ret = ctf_stream_declaration_visit(fd, depth + 1, iter, stream, trace); + if (ret) + goto error; + } + if (!CTF_EVENT_FIELD_IS_SET(stream, stream_id)) { + ret = -EPERM; + goto error; + } + if (trace->streams->len <= stream->stream_id) + g_ptr_array_set_size(trace->streams, stream->stream_id + 1); + g_ptr_array_index(trace->streams, stream->stream_id) = stream; + return 0; + +error: + declaration_unref(stream->event_header); + declaration_unref(stream->event_context); + declaration_unref(stream->packet_context); + g_ptr_array_free(stream->events_by_id, TRUE); + g_hash_table_free(stream->event_quark_to_id); + free_declaration_scope(stream->declaration_scope); + free_type_scope(stream->type_scope); + g_free(stream); + return ret; +} + +static +int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace) +{ + int ret = 0; + + switch (node->type) { + case NODE_TYPEDEF: + ret = ctf_typedef_visit(fd, depth + 1, + &node->u._typedef.declaration_specifier, + &node->u._typedef.type_declarators, + trace->type_scope, trace->declaration_scope); + if (ret) + return ret; + break; + case NODE_TYPEALIAS: + ret = ctf_typealias_visit(fd, depth + 1, + &node->u.typealias.target, &node->u.typealias.alias + trace->type_scope, trace->declaration_scope); + if (ret) + return ret; + break; + case NODE_CTF_EXPRESSION: + { + char *left; + + left = concatenate_unary_strings(&node->u.ctf_expression.left); + if (!strcmp(left, "major")) { + if (CTF_EVENT_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__); + return -EINVAL; + } + CTF_EVENT_SET_FIELD(trace, major); + } else if (!strcmp(left, "minor")) { + if (CTF_EVENT_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__); + return -EINVAL; + } + CTF_EVENT_SET_FIELD(trace, minor); + } else if (!strcmp(left, "word_size")) { + if (CTF_EVENT_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__); + return -EINVAL; + } + CTF_EVENT_SET_FIELD(trace, word_size); + } else if (!strcmp(left, "uuid")) { + if (CTF_EVENT_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__); + return -EINVAL; + } + CTF_EVENT_SET_FIELD(trace, uuid); + } + free(left); + break; + } + default: + return -EPERM; + /* TODO: declaration specifier should be added. */ + } + + return 0; +} + + +static +int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace) +{ + int ret = 0; + struct ctf_node *iter; + + if (trace->type_scope) + return -EEXIST; + trace->type_scope = new_type_scope(trace->root_type_scope); + trace->declaration_scope = new_declaration_scope(trace->root_declaration_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)) { + ret = -EPERM; + goto error; + } + if (!CTF_EVENT_FIELD_IS_SET(trace, minor)) { + ret = -EPERM; + goto error; + } + if (!CTF_EVENT_FIELD_IS_SET(trace, uuid)) { + ret = -EPERM; + goto error; + } + if (!CTF_EVENT_FIELD_IS_SET(trace, word_size)) { + ret = -EPERM; + goto error; + } + return 0; + +error: + g_ptr_array_free(trace->streams, TRUE); + free_declaration_scope(stream->declaration_scope); + free_type_scope(stream->type_scope); + return ret; +} + +int _ctf_visitor(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->type_scope, trace->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->type_scope, trace->declaration_scope); + if (ret) + return ret; + } + cds_list_for_each_entry(iter, &node->u.root.declaration_specifier, siblings) { + ret = ctf_type_specifier_visit(fd, depth, iter, + trace->root_type_scope, + 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->type_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->type_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); + if (ret) + return ret; + break; + case NODE_POINTER: + print_tabs(fd, depth); + if (node->u.pointer.const_qualifier) + fprintf(fd, "\n"); + else + fprintf(fd, "\n"); + break; + case NODE_TYPE_DECLARATOR: + ret = ctf_visitor_print_type_declarator(fd, depth, node); + if (ret) + return ret; + break; + + case NODE_FLOATING_POINT: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.floating_point.expressions, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_INTEGER: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.integer.expressions, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_STRING: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.string.expressions, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_ENUMERATOR: + print_tabs(fd, depth); + fprintf(fd, "u.enumerator.id) + fprintf(fd, " id=\"%s\"", node->u.enumerator.id); + fprintf(fd, ">\n"); + cds_list_for_each_entry(iter, &node->u.enumerator.values, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_ENUM: + print_tabs(fd, depth); + if (node->u._struct.name) + fprintf(fd, "\n", + node->u._enum.enum_id); + else + fprintf(fd, "\n"); + depth++; + + if (node->u._enum.container_type) { + print_tabs(fd, depth); + fprintf(fd, "\n"); + ret = ctf_visitor_print_xml(fd, depth + 1, node->u._enum.container_type); + if (ret) + return ret; + print_tabs(fd, depth); + fprintf(fd, "\n"); + } + + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u._enum.enumerator_list, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + + depth--; + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_STRUCT_OR_VARIANT_DECLARATION: + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.declaration_specifier, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + + print_tabs(fd, depth); + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.type_declarators, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_VARIANT: + print_tabs(fd, depth); + fprintf(fd, "u.variant.name) + fprintf(fd, " name=\"%s\"", node->u.variant.name); + if (node->u.variant.choice) + fprintf(fd, " choice=\"%s\"", node->u.variant.choice); + fprintf(fd, ">\n"); + cds_list_for_each_entry(iter, &node->u.variant.declaration_list, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + case NODE_STRUCT: + print_tabs(fd, depth); + if (node->u._struct.name) + fprintf(fd, "\n", + node->u._struct.name); + else + fprintf(fd, "\n"); + cds_list_for_each_entry(iter, &node->u._struct.declaration_list, siblings) { + ret = ctf_visitor_print_xml(fd, depth + 1, iter); + if (ret) + return ret; + } + print_tabs(fd, depth); + fprintf(fd, "\n"); + break; + + case NODE_UNKNOWN: + default: + fprintf(stderr, "[error] %s: unknown node type %d\n", __func__, + (int) node->type); + return -EINVAL; + } + return ret; +} diff --git a/include/babeltrace/ctf/metadata.h b/include/babeltrace/ctf/metadata.h index aea04e8c..e9ab83dd 100644 --- a/include/babeltrace/ctf/metadata.h +++ b/include/babeltrace/ctf/metadata.h @@ -43,9 +43,16 @@ struct ctf_event; (ctf_trace)->(field); \ }) + struct ctf_trace { - struct declaration_scope *scope; /* root scope */ - GArray *streams; /* Array of struct ctf_stream */ + /* root scope */ + struct type_scope *root_type_scope; + /* root scope */ + struct declaration_scope *root_declaration_scope; + + struct type_scope *type_scope; + struct declaration_scope *declaration_scope; + GPtrArray *streams; /* Array of struct ctf_stream pointers*/ uint64_t major; uint64_t minor; @@ -77,8 +84,11 @@ struct ctf_trace { struct ctf_stream { struct ctf_trace *trace; - struct declaration_scope *scope; /* parent is trace scope */ - GArray *events_by_id; /* Array of struct ctf_event indexed by id */ + /* parent is lexical scope conaining the stream scope */ + struct type_scope *type_scope; + /* parent is trace scope */ + struct declaration_scope *declaration_scope; + GPtrArray *events_by_id; /* Array of struct ctf_event pointers indexed by id */ GHashTable *event_quark_to_id; /* GQuark to numeric id */ struct declaration_struct *event_header; @@ -92,9 +102,8 @@ struct ctf_stream { } field_mask; }; -#define CTF_EVENT_SET_FIELD(ctf_event, field, value) \ +#define CTF_EVENT_SET_FIELD(ctf_event, field) \ do { \ - (ctf_event)->(field) = (value); \ (ctf_event)->field_mask |= CTF_EVENT_ ## field; \ } while (0) @@ -108,8 +117,12 @@ struct ctf_stream { }) struct ctf_event { - struct ctf_stream *stream; /* stream mapped by stream_id */ - struct declaration_scope *scope; /* parent is stream scope */ + /* stream mapped by stream_id */ + struct ctf_stream *stream; + /* parent is lexical scope conaining the event scope */ + struct type_scope *type_scope; + /* parent is stream scope */ + struct declaration_scope *declaration_scope; struct declaration_struct *context; struct declaration_struct *fields; diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index cee6c5a3..e8480122 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -101,7 +101,21 @@ struct declaration_scope { struct declaration_scope *parent_scope; }; +enum ctf_type_id { + CTF_TYPE_UNKNOWN = 0, + CTF_TYPE_INTEGER, + CTF_TYPE_FLOAT, + CTF_TYPE_ENUM, + CTF_TYPE_STRING, + CTF_TYPE_STRUCT, + CTF_TYPE_VARIANT, + CTF_TYPE_ARRAY, + CTF_TYPE_SEQUENCE, + NR_CTF_TYPES, +}; + struct type { + enum ctf_type_id id; GQuark name; /* type name */ size_t alignment; /* type alignment, in bits */ int ref; /* number of references to the type */ diff --git a/types/array.c b/types/array.c index 35415ec8..02a154e9 100644 --- a/types/array.c +++ b/types/array.c @@ -69,6 +69,7 @@ struct type_array * type_ref(elem_type); array_type->elem = elem_type; array_type->scope = new_type_scope(parent_scope); + type->id = CTF_TYPE_ARRAY; type->name = g_quark_from_string(name); /* No need to align the array, the first element will align itself */ type->alignment = 1; diff --git a/types/enum.c b/types/enum.c index e29df080..b17551fa 100644 --- a/types/enum.c +++ b/types/enum.c @@ -406,6 +406,7 @@ struct type_enum * NULL, enum_range_set_free); type_ref(&integer_type->p); enum_type->integer_type = integer_type; + enum_type->p.id = CTF_TYPE_ENUM; enum_type->p.name = g_quark_from_string(name); enum_type->p.alignment = 1; enum_type->p.copy = enum_copy; diff --git a/types/float.c b/types/float.c index ae23a96c..5ceb9f3a 100644 --- a/types/float.c +++ b/types/float.c @@ -66,6 +66,7 @@ struct type_float * float_type = g_new(struct type_float, 1); type = &float_type->p; + type->id = CTF_TYPE_FLOAT; type->name = g_quark_from_string(name); type->alignment = alignment; type->copy = float_copy; diff --git a/types/integer.c b/types/integer.c index 1a8601eb..373e4bc4 100644 --- a/types/integer.c +++ b/types/integer.c @@ -63,6 +63,7 @@ struct type_integer * struct type_integer *integer_type; integer_type = g_new(struct type_integer, 1); + integer_type->p.id = CTF_TYPE_INTEGER; integer_type->p.name = g_quark_from_string(name); integer_type->p.alignment = alignment; integer_type->p.copy = integer_copy; diff --git a/types/sequence.c b/types/sequence.c index c379f983..9d84d0ee 100644 --- a/types/sequence.c +++ b/types/sequence.c @@ -81,6 +81,7 @@ struct type_sequence * type_ref(elem_type); sequence_type->elem = elem_type; sequence_type->scope = new_type_scope(parent_scope); + type->id = CTF_TYPE_SEQUENCE; type->name = g_quark_from_string(name); type->alignment = max(len_type->p.alignment, elem_type->alignment); type->copy = sequence_copy; diff --git a/types/string.c b/types/string.c index c6cbb54c..9a80b038 100644 --- a/types/string.c +++ b/types/string.c @@ -58,6 +58,7 @@ struct type_string *string_type_new(const char *name) struct type_string *string_type; string_type = g_new(struct type_string, 1); + string_type->p.id = CTF_TYPE_STRING; string_type->p.name = g_quark_from_string(name); string_type->p.alignment = CHAR_BIT; string_type->p.copy = string_copy; diff --git a/types/struct.c b/types/struct.c index 5e7e2b4e..779cca5c 100644 --- a/types/struct.c +++ b/types/struct.c @@ -87,6 +87,7 @@ struct type_struct *struct_type_new(const char *name, sizeof(struct type_field), DEFAULT_NR_STRUCT_FIELDS); struct_type->scope = new_type_scope(parent_scope); + type->id = CTF_TYPE_STRUCT; type->name = g_quark_from_string(name); type->alignment = 1; type->copy = struct_copy; diff --git a/types/variant.c b/types/variant.c index 98f68745..ea20808b 100644 --- a/types/variant.c +++ b/types/variant.c @@ -81,6 +81,7 @@ struct type_variant *variant_type_new(const char *name, sizeof(struct type_field), DEFAULT_NR_STRUCT_FIELDS); variant_type->scope = new_type_scope(parent_scope); + type->id = CTF_TYPE_VARIANT; type->name = g_quark_from_string(name); type->alignment = 1; type->copy = variant_copy; -- 2.34.1