#include <inttypes.h>
#include <endian.h>
#include <errno.h>
+#include <babeltrace/babeltrace.h>
#include <babeltrace/list.h>
#include <babeltrace/types.h>
#include <babeltrace/ctf/metadata.h>
cds_list_entry((ptr)->next, type, member)
static
-struct declaration *ctf_declaration_specifier_visit(FILE *fd,
- int depth, struct cds_list_head *head,
+struct declaration *ctf_type_specifier_list_visit(FILE *fd,
+ int depth, struct ctf_node *type_specifier_list,
struct declaration_scope *declaration_scope,
struct ctf_trace *trace);
+static
+int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
+ struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace);
+
/*
* String returned must be freed by the caller using g_free.
*/
}
static
-struct ctf_stream *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
+struct ctf_stream_class *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
{
if (trace->streams->len <= stream_id)
return NULL;
}
static
-int visit_declaration_specifier(struct cds_list_head *declaration_specifier, GString *str)
+int visit_type_specifier(FILE *fd, struct ctf_node *type_specifier, GString *str)
+{
+ assert(type_specifier->type == NODE_TYPE_SPECIFIER);
+
+ switch (type_specifier->u.type_specifier.type) {
+ case TYPESPEC_VOID:
+ g_string_append(str, "void");
+ break;
+ case TYPESPEC_CHAR:
+ g_string_append(str, "char");
+ break;
+ case TYPESPEC_SHORT:
+ g_string_append(str, "short");
+ break;
+ case TYPESPEC_INT:
+ g_string_append(str, "int");
+ break;
+ case TYPESPEC_LONG:
+ g_string_append(str, "long");
+ break;
+ case TYPESPEC_FLOAT:
+ g_string_append(str, "float");
+ break;
+ case TYPESPEC_DOUBLE:
+ g_string_append(str, "double");
+ break;
+ case TYPESPEC_SIGNED:
+ g_string_append(str, "signed");
+ break;
+ case TYPESPEC_UNSIGNED:
+ g_string_append(str, "unsigned");
+ break;
+ case TYPESPEC_BOOL:
+ g_string_append(str, "bool");
+ break;
+ case TYPESPEC_COMPLEX:
+ g_string_append(str, "_Complex");
+ break;
+ case TYPESPEC_IMAGINARY:
+ g_string_append(str, "_Imaginary");
+ break;
+ case TYPESPEC_CONST:
+ g_string_append(str, "const");
+ break;
+ case TYPESPEC_ID_TYPE:
+ if (type_specifier->u.type_specifier.id_type)
+ g_string_append(str, type_specifier->u.type_specifier.id_type);
+ break;
+ case TYPESPEC_STRUCT:
+ {
+ struct ctf_node *node = type_specifier->u.type_specifier.node;
+
+ if (!node->u._struct.name) {
+ fprintf(fd, "[error] %s: unexpected empty variant name\n", __func__);
+ return -EINVAL;
+ }
+ g_string_append(str, "struct ");
+ g_string_append(str, node->u._struct.name);
+ break;
+ }
+ case TYPESPEC_VARIANT:
+ {
+ struct ctf_node *node = type_specifier->u.type_specifier.node;
+
+ if (!node->u.variant.name) {
+ fprintf(fd, "[error] %s: unexpected empty variant name\n", __func__);
+ return -EINVAL;
+ }
+ g_string_append(str, "variant ");
+ g_string_append(str, node->u.variant.name);
+ break;
+ }
+ case TYPESPEC_ENUM:
+ {
+ struct ctf_node *node = type_specifier->u.type_specifier.node;
+
+ if (!node->u._enum.enum_id) {
+ fprintf(fd, "[error] %s: unexpected empty enum ID\n", __func__);
+ return -EINVAL;
+ }
+ g_string_append(str, "enum ");
+ g_string_append(str, node->u._enum.enum_id);
+ break;
+ }
+ case TYPESPEC_FLOATING_POINT:
+ case TYPESPEC_INTEGER:
+ case TYPESPEC_STRING:
+ default:
+ fprintf(fd, "[error] %s: unknown specifier\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static
+int visit_type_specifier_list(FILE *fd, struct ctf_node *type_specifier_list, GString *str)
{
struct ctf_node *iter;
int alias_item_nr = 0;
- int err;
+ int ret;
- cds_list_for_each_entry(iter, declaration_specifier, siblings) {
+ cds_list_for_each_entry(iter, &type_specifier_list->u.type_specifier_list.head, siblings) {
if (alias_item_nr != 0)
g_string_append(str, " ");
alias_item_nr++;
-
- switch (iter->type) {
- case NODE_TYPE_SPECIFIER:
- switch (iter->u.type_specifier.type) {
- case TYPESPEC_VOID:
- g_string_append(str, "void");
- break;
- case TYPESPEC_CHAR:
- g_string_append(str, "char");
- break;
- case TYPESPEC_SHORT:
- g_string_append(str, "short");
- break;
- case TYPESPEC_INT:
- g_string_append(str, "int");
- break;
- case TYPESPEC_LONG:
- g_string_append(str, "long");
- break;
- case TYPESPEC_FLOAT:
- g_string_append(str, "float");
- break;
- case TYPESPEC_DOUBLE:
- g_string_append(str, "double");
- break;
- case TYPESPEC_SIGNED:
- g_string_append(str, "signed");
- break;
- case TYPESPEC_UNSIGNED:
- g_string_append(str, "unsigned");
- break;
- case TYPESPEC_BOOL:
- g_string_append(str, "bool");
- break;
- case TYPESPEC_COMPLEX:
- g_string_append(str, "_Complex");
- break;
- case TYPESPEC_IMAGINARY:
- g_string_append(str, "_Imaginary");
- break;
- case TYPESPEC_CONST:
- g_string_append(str, "const");
- break;
- case TYPESPEC_ID_TYPE:
- if (iter->u.type_specifier.id_type)
- g_string_append(str, iter->u.type_specifier.id_type);
- break;
- default:
- fprintf(stderr, "[error] %s: unknown specifier\n", __func__);
- err = -EINVAL;
- goto error;
- }
- break;
- case NODE_ENUM:
- if (!iter->u._enum.enum_id) {
- fprintf(stderr, "[error] %s: unexpected empty enum ID\n", __func__);
- err = -EINVAL;
- goto error;
- }
- g_string_append(str, "enum ");
- g_string_append(str, iter->u._enum.enum_id);
- break;
- case NODE_VARIANT:
- if (!iter->u.variant.name) {
- fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__);
- err = -EINVAL;
- goto error;
- }
- g_string_append(str, "variant ");
- g_string_append(str, iter->u.variant.name);
- break;
- case NODE_STRUCT:
- if (!iter->u._struct.name) {
- fprintf(stderr, "[error] %s: unexpected empty variant name\n", __func__);
- err = -EINVAL;
- goto error;
- }
- g_string_append(str, "struct ");
- g_string_append(str, iter->u._struct.name);
- break;
- default:
- fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
- err = -EINVAL;
- goto error;
- }
+ ret = visit_type_specifier(fd, iter, str);
+ if (ret)
+ return ret;
}
return 0;
-error:
- return err;
}
static
GQuark create_typealias_identifier(FILE *fd, int depth,
- struct cds_list_head *declaration_specifier,
+ struct ctf_node *type_specifier_list,
struct ctf_node *node_type_declarator)
{
struct ctf_node *iter;
int ret;
str = g_string_new("");
- ret = visit_declaration_specifier(declaration_specifier, str);
+ ret = visit_type_specifier_list(fd, type_specifier_list, str);
if (ret) {
g_string_free(str, TRUE);
return 0;
static
struct declaration *ctf_type_declarator_visit(FILE *fd, int depth,
- struct cds_list_head *declaration_specifier,
+ struct ctf_node *type_specifier_list,
GQuark *field_name,
struct ctf_node *node_type_declarator,
struct declaration_scope *declaration_scope,
/* TODO: gcc bitfields not supported yet. */
if (node_type_declarator->u.type_declarator.bitfield_len != NULL) {
- fprintf(stderr, "[error] %s: gcc bitfields are not supported yet.\n", __func__);
+ fprintf(fd, "[error] %s: gcc bitfields are not supported yet.\n", __func__);
return NULL;
}
}
* the typealiases (else fail).
*/
alias_q = create_typealias_identifier(fd, depth,
- declaration_specifier, node_type_declarator);
+ type_specifier_list, node_type_declarator);
nested_declaration = lookup_declaration(alias_q, declaration_scope);
if (!nested_declaration) {
- fprintf(stderr, "[error] %s: cannot find typealias \"%s\".\n", __func__, g_quark_to_string(alias_q));
+ fprintf(fd, "[error] %s: cannot find typealias \"%s\".\n", __func__, g_quark_to_string(alias_q));
return NULL;
}
} else {
- nested_declaration = ctf_declaration_specifier_visit(fd, depth,
- declaration_specifier, declaration_scope, trace);
+ nested_declaration = ctf_type_specifier_list_visit(fd, depth,
+ type_specifier_list, declaration_scope, trace);
}
}
return nested_declaration;
} else {
struct declaration *declaration;
- struct cds_list_head *length;
- struct ctf_node *first;
+ struct ctf_node *length;
/* TYPEDEC_NESTED */
/* create array/sequence, pass nested_declaration as child. */
- length = &node_type_declarator->u.type_declarator.u.nested.length;
- if (cds_list_empty(length)) {
- fprintf(stderr, "[error] %s: expecting length type or value.\n", __func__);
+ length = node_type_declarator->u.type_declarator.u.nested.length;
+ if (!length) {
+ fprintf(fd, "[error] %s: expecting length type or value.\n", __func__);
return NULL;
}
- first = _cds_list_first_entry(length, struct ctf_node, siblings);
- switch (first->type) {
+ switch (length->type) {
case NODE_UNARY_EXPRESSION:
{
struct declaration_array *array_declaration;
size_t len;
- if (first->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
- fprintf(stderr, "[error] %s: array: unexpected unary expression.\n", __func__);
+ if (length->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
+ fprintf(fd, "[error] %s: array: unexpected unary expression.\n", __func__);
return NULL;
}
- len = first->u.unary_expression.u.unsigned_constant;
+ len = length->u.unary_expression.u.unsigned_constant;
array_declaration = array_declaration_new(len, nested_declaration,
declaration_scope);
declaration = &array_declaration->p;
break;
}
- case NODE_INTEGER:
- case NODE_TYPE_SPECIFIER:
+ case NODE_TYPE_SPECIFIER_LIST:
{
struct declaration_sequence *sequence_declaration;
struct declaration_integer *integer_declaration;
- GQuark dummy_id;
- declaration = ctf_type_declarator_visit(fd, depth,
- length,
- &dummy_id, NULL,
- declaration_scope,
- NULL, trace);
- assert(declaration->id == CTF_TYPE_INTEGER);
+ 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);
+ 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;
/* Pass it as content of outer container */
declaration = ctf_type_declarator_visit(fd, depth,
- declaration_specifier, field_name,
+ type_specifier_list, field_name,
node_type_declarator->u.type_declarator.u.nested.type_declarator,
declaration_scope, declaration, trace);
return declaration;
static
int ctf_struct_type_declarators_visit(FILE *fd, int depth,
struct declaration_struct *struct_declaration,
- struct cds_list_head *declaration_specifier,
+ struct ctf_node *type_specifier_list,
struct cds_list_head *type_declarators,
struct declaration_scope *declaration_scope,
struct ctf_trace *trace)
struct declaration *field_declaration;
field_declaration = ctf_type_declarator_visit(fd, depth,
- declaration_specifier,
+ type_specifier_list,
&field_name, iter,
struct_declaration->scope,
NULL, trace);
+ if (!field_declaration) {
+ fprintf(fd, "[error] %s: unable to find struct field declaration type\n", __func__);
+ return -EINVAL;
+ }
struct_declaration_add_field(struct_declaration,
g_quark_to_string(field_name),
field_declaration);
static
int ctf_variant_type_declarators_visit(FILE *fd, int depth,
struct declaration_untagged_variant *untagged_variant_declaration,
- struct cds_list_head *declaration_specifier,
+ struct ctf_node *type_specifier_list,
struct cds_list_head *type_declarators,
struct declaration_scope *declaration_scope,
struct ctf_trace *trace)
struct declaration *field_declaration;
field_declaration = ctf_type_declarator_visit(fd, depth,
- declaration_specifier,
+ type_specifier_list,
&field_name, iter,
untagged_variant_declaration->scope,
NULL, trace);
+ if (!field_declaration) {
+ fprintf(fd, "[error] %s: unable to find variant field declaration type\n", __func__);
+ return -EINVAL;
+ }
untagged_variant_declaration_add_field(untagged_variant_declaration,
g_quark_to_string(field_name),
field_declaration);
static
int ctf_typedef_visit(FILE *fd, int depth, struct declaration_scope *scope,
- struct cds_list_head *declaration_specifier,
+ struct ctf_node *type_specifier_list,
struct cds_list_head *type_declarators,
struct ctf_trace *trace)
{
int ret;
type_declaration = ctf_type_declarator_visit(fd, depth,
- declaration_specifier,
+ type_specifier_list,
&identifier, iter,
scope, NULL, trace);
+ if (!type_declaration) {
+ fprintf(fd, "[error] %s: problem creating type declaration\n", __func__);
+ return -EINVAL;
+ }
+ /*
+ * Don't allow typedef and typealias of untagged
+ * variants.
+ */
+ if (type_declaration->id == CTF_TYPE_UNTAGGED_VARIANT) {
+ fprintf(fd, "[error] %s: typedef of untagged variant is not permitted.\n", __func__);
+ declaration_unref(type_declaration);
+ return -EPERM;
+ }
ret = register_declaration(identifier, type_declaration, scope);
if (ret) {
type_declaration->declaration_free(type_declaration);
* Create target type declaration.
*/
- if (cds_list_empty(&alias->u.typealias_target.type_declarators))
+ if (cds_list_empty(&target->u.typealias_target.type_declarators))
node = NULL;
else
- node = _cds_list_first_entry(&alias->u.typealias_target.type_declarators,
+ node = _cds_list_first_entry(&target->u.typealias_target.type_declarators,
struct ctf_node, siblings);
type_declaration = ctf_type_declarator_visit(fd, depth,
- &target->u.typealias_target.declaration_specifier,
+ target->u.typealias_target.type_specifier_list,
&dummy_id, node,
scope, NULL, trace);
if (!type_declaration) {
- fprintf(stderr, "[error] %s: problem creating type declaration\n", __func__);
+ fprintf(fd, "[error] %s: problem creating type declaration\n", __func__);
err = -EINVAL;
goto error;
}
+ /*
+ * Don't allow typedef and typealias of untagged
+ * variants.
+ */
+ if (type_declaration->id == CTF_TYPE_UNTAGGED_VARIANT) {
+ fprintf(fd, "[error] %s: typedef of untagged variant is not permitted.\n", __func__);
+ declaration_unref(type_declaration);
+ return -EPERM;
+ }
/*
* The semantic validator does not check whether the target is
* abstract or not (if it has an identifier). Check it here.
*/
if (dummy_id != 0) {
- fprintf(stderr, "[error] %s: expecting empty identifier\n", __func__);
+ fprintf(fd, "[error] %s: expecting empty identifier\n", __func__);
err = -EINVAL;
goto error;
}
node = _cds_list_first_entry(&alias->u.typealias_alias.type_declarators,
struct ctf_node, siblings);
alias_q = create_typealias_identifier(fd, depth,
- &alias->u.typealias_alias.declaration_specifier, node);
+ alias->u.typealias_alias.type_specifier_list, node);
err = register_declaration(alias_q, type_declaration, scope);
if (err)
goto error;
/* For each declarator, declare type and add type to struct declaration scope */
ret = ctf_typedef_visit(fd, depth,
struct_declaration->scope,
- &iter->u._typedef.declaration_specifier,
+ iter->u._typedef.type_specifier_list,
&iter->u._typedef.type_declarators, trace);
if (ret)
return ret;
/* Add field to structure declaration */
ret = ctf_struct_type_declarators_visit(fd, depth,
struct_declaration,
- &iter->u.struct_or_variant_declaration.declaration_specifier,
+ iter->u.struct_or_variant_declaration.type_specifier_list,
&iter->u.struct_or_variant_declaration.type_declarators,
struct_declaration->scope, trace);
if (ret)
return ret;
break;
default:
- fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
+ fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
assert(0);
}
return 0;
/* For each declarator, declare type and add type to variant declaration scope */
ret = ctf_typedef_visit(fd, depth,
untagged_variant_declaration->scope,
- &iter->u._typedef.declaration_specifier,
+ iter->u._typedef.type_specifier_list,
&iter->u._typedef.type_declarators, trace);
if (ret)
return ret;
/* Add field to structure declaration */
ret = ctf_variant_type_declarators_visit(fd, depth,
untagged_variant_declaration,
- &iter->u.struct_or_variant_declaration.declaration_specifier,
+ iter->u.struct_or_variant_declaration.type_specifier_list,
&iter->u.struct_or_variant_declaration.type_declarators,
untagged_variant_declaration->scope, trace);
if (ret)
return ret;
break;
default:
- fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
+ fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) iter->type);
assert(0);
}
return 0;
static
struct declaration *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) {
if (lookup_struct_declaration(g_quark_from_string(name),
declaration_scope)) {
- fprintf(stderr, "[error] %s: struct %s already declared in scope\n", __func__, name);
+ fprintf(fd, "[error] %s: struct %s already declared in scope\n", __func__, 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);
if (lookup_variant_declaration(g_quark_from_string(name),
declaration_scope)) {
- fprintf(stderr, "[error] %s: variant %s already declared in scope\n", __func__, name);
+ fprintf(fd, "[error] %s: variant %s already declared in scope\n", __func__, name);
return NULL;
}
}
return &variant_declaration->p;
}
error:
- untagged_variant_declaration->p.declaration_free(&variant_declaration->p);
+ untagged_variant_declaration->p.declaration_free(&untagged_variant_declaration->p);
return NULL;
}
*target = iter->u.unary_expression.u.unsigned_constant;
break;
default:
- fprintf(stderr, "[error] %s: invalid enumerator\n", __func__);
+ fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
return -EINVAL;
}
if (nr_vals > 1) {
- fprintf(stderr, "[error] %s: invalid enumerator\n", __func__);
+ fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
return -EINVAL;
}
nr_vals++;
* We don't accept signed constants for enums with unsigned
* container type.
*/
- fprintf(stderr, "[error] %s: invalid enumerator (signed constant encountered, but enum container type is unsigned)\n", __func__);
+ fprintf(fd, "[error] %s: invalid enumerator (signed constant encountered, but enum container type is unsigned)\n", __func__);
return -EINVAL;
default:
- fprintf(stderr, "[error] %s: invalid enumerator\n", __func__);
+ fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
return -EINVAL;
}
if (nr_vals > 1) {
- fprintf(stderr, "[error] %s: invalid enumerator\n", __func__);
+ fprintf(fd, "[error] %s: invalid enumerator\n", __func__);
return -EINVAL;
}
nr_vals++;
static
struct declaration *ctf_declaration_enum_visit(FILE *fd, int depth,
const char *name,
- struct cds_list_head *container_type,
+ struct ctf_node *container_type,
struct cds_list_head *enumerator_list,
int has_body,
struct declaration_scope *declaration_scope,
struct declaration *declaration;
struct declaration_enum *enum_declaration;
struct declaration_integer *integer_declaration;
- struct ctf_node *iter, *first;
+ struct ctf_node *iter;
GQuark dummy_id;
int ret;
if (lookup_enum_declaration(g_quark_from_string(name),
declaration_scope)) {
- fprintf(stderr, "[error] %s: enum %s already declared in scope\n", __func__, name);
+ fprintf(fd, "[error] %s: enum %s already declared in scope\n", __func__, name);
return NULL;
}
}
- if (cds_list_empty(container_type)) {
- fprintf(stderr, "[error] %s: missing container type for enumeration\n", __func__);
+ if (!container_type) {
+ declaration = lookup_declaration(g_quark_from_static_string("int"),
+ declaration_scope);
+ if (!declaration) {
+ fprintf(fd, "[error] %s: \"int\" type declaration missing for enumeration\n", __func__);
return NULL;
-
- }
- first = _cds_list_first_entry(container_type, struct ctf_node, siblings);
- switch (first->type) {
- case NODE_INTEGER:
- case NODE_TYPE_SPECIFIER:
+ }
+ } else {
declaration = ctf_type_declarator_visit(fd, depth,
container_type,
&dummy_id, NULL,
declaration_scope,
NULL, trace);
- assert(declaration->id == CTF_TYPE_INTEGER);
- integer_declaration = container_of(declaration, struct declaration_integer, p);
- break;
- default:
- assert(0);
}
+ if (!declaration) {
+ fprintf(fd, "[error] %s: unable to create container type for enumeration\n", __func__);
+ return NULL;
+ }
+ if (declaration->id != CTF_TYPE_INTEGER) {
+ fprintf(fd, "[error] %s: container type for enumeration is not integer\n", __func__);
+ return NULL;
+ }
+ integer_declaration = container_of(declaration, struct declaration_integer, p);
enum_declaration = enum_declaration_new(integer_declaration);
declaration_unref(&integer_declaration->p); /* leave ref to enum */
cds_list_for_each_entry(iter, enumerator_list, siblings) {
static
struct declaration *ctf_declaration_type_specifier_visit(FILE *fd, int depth,
- struct cds_list_head *declaration_specifier,
+ struct ctf_node *type_specifier_list,
struct declaration_scope *declaration_scope)
{
GString *str;
GQuark id_q;
str = g_string_new("");
- ret = visit_declaration_specifier(declaration_specifier, str);
+ ret = visit_type_specifier_list(fd, type_specifier_list, str);
if (ret)
return NULL;
str_c = g_string_free(str, FALSE);
int get_boolean(FILE *fd, int depth, struct ctf_node *unary_expression)
{
if (unary_expression->type != NODE_UNARY_EXPRESSION) {
- fprintf(stderr, "[error] %s: expecting unary expression\n",
+ fprintf(fd, "[error] %s: expecting unary expression\n",
__func__);
return -EINVAL;
}
else if (!strcmp(unary_expression->u.unary_expression.u.string, "FALSE"))
return 0;
else {
- fprintf(stderr, "[error] %s: unexpected string \"%s\"\n",
+ fprintf(fd, "[error] %s: unexpected string \"%s\"\n",
__func__, unary_expression->u.unary_expression.u.string);
return -EINVAL;
}
break;
default:
- fprintf(stderr, "[error] %s: unexpected unary expression type\n",
+ fprintf(fd, "[error] %s: unexpected unary expression type\n",
__func__);
return -EINVAL;
}
}
+static
+int get_trace_byte_order(FILE *fd, int depth, struct ctf_node *unary_expression)
+{
+ int byte_order;
+
+ if (unary_expression->u.unary_expression.type != UNARY_STRING) {
+ fprintf(fd, "[error] %s: byte_order: expecting string\n",
+ __func__);
+ return -EINVAL;
+ }
+ if (!strcmp(unary_expression->u.unary_expression.u.string, "be"))
+ byte_order = BIG_ENDIAN;
+ else if (!strcmp(unary_expression->u.unary_expression.u.string, "le"))
+ byte_order = LITTLE_ENDIAN;
+ else {
+ fprintf(fd, "[error] %s: unexpected string \"%s\". Should be \"native\", \"network\", \"be\" or \"le\".\n",
+ __func__, unary_expression->u.unary_expression.u.string);
+ return -EINVAL;
+ }
+ return byte_order;
+}
+
static
int get_byte_order(FILE *fd, int depth, struct ctf_node *unary_expression,
struct ctf_trace *trace)
int byte_order;
if (unary_expression->u.unary_expression.type != UNARY_STRING) {
- fprintf(stderr, "[error] %s: byte_order: expecting string\n",
+ fprintf(fd, "[error] %s: byte_order: expecting string\n",
__func__);
return -EINVAL;
}
else if (!strcmp(unary_expression->u.unary_expression.u.string, "le"))
byte_order = LITTLE_ENDIAN;
else {
- fprintf(stderr, "[error] %s: unexpected string \"%s\". Should be \"native\", \"network\", \"be\" or \"le\".\n",
+ fprintf(fd, "[error] %s: unexpected string \"%s\". Should be \"native\", \"network\", \"be\" or \"le\".\n",
__func__, unary_expression->u.unary_expression.u.string);
return -EINVAL;
}
return NULL;
} else if (!strcmp(left->u.unary_expression.u.string, "size")) {
if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
- fprintf(stderr, "[error] %s: size: expecting unsigned constant\n",
+ fprintf(fd, "[error] %s: size: expecting unsigned constant\n",
__func__);
return NULL;
}
has_size = 1;
} else if (!strcmp(left->u.unary_expression.u.string, "align")) {
if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
- fprintf(stderr, "[error] %s: align: expecting unsigned constant\n",
+ fprintf(fd, "[error] %s: align: expecting unsigned constant\n",
__func__);
return NULL;
}
alignment = right->u.unary_expression.u.unsigned_constant;
+ /* Make sure alignment is a power of two */
+ if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
+ fprintf(fd, "[error] %s: align: expecting power of two\n",
+ __func__);
+ return NULL;
+ }
has_alignment = 1;
} else {
- fprintf(stderr, "[error] %s: unknown attribute name %s\n",
+ fprintf(fd, "[error] %s: unknown attribute name %s\n",
__func__, left->u.unary_expression.u.string);
return NULL;
}
}
if (!has_size) {
- fprintf(stderr, "[error] %s: missing size attribute\n", __func__);
+ fprintf(fd, "[error] %s: missing size attribute\n", __func__);
return NULL;
}
if (!has_alignment) {
return NULL;
} else if (!strcmp(left->u.unary_expression.u.string, "exp_dig")) {
if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
- fprintf(stderr, "[error] %s: exp_dig: expecting unsigned constant\n",
+ fprintf(fd, "[error] %s: exp_dig: expecting unsigned constant\n",
__func__);
return NULL;
}
has_exp_dig = 1;
} else if (!strcmp(left->u.unary_expression.u.string, "mant_dig")) {
if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
- fprintf(stderr, "[error] %s: mant_dig: expecting unsigned constant\n",
+ fprintf(fd, "[error] %s: mant_dig: expecting unsigned constant\n",
__func__);
return NULL;
}
has_mant_dig = 1;
} else if (!strcmp(left->u.unary_expression.u.string, "align")) {
if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
- fprintf(stderr, "[error] %s: align: expecting unsigned constant\n",
+ fprintf(fd, "[error] %s: align: expecting unsigned constant\n",
__func__);
return NULL;
}
alignment = right->u.unary_expression.u.unsigned_constant;
+ /* Make sure alignment is a power of two */
+ if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
+ fprintf(fd, "[error] %s: align: expecting power of two\n",
+ __func__);
+ return NULL;
+ }
has_alignment = 1;
} else {
- fprintf(stderr, "[error] %s: unknown attribute name %s\n",
+ fprintf(fd, "[error] %s: unknown attribute name %s\n",
__func__, left->u.unary_expression.u.string);
return NULL;
}
}
if (!has_mant_dig) {
- fprintf(stderr, "[error] %s: missing mant_dig attribute\n", __func__);
+ fprintf(fd, "[error] %s: missing mant_dig attribute\n", __func__);
return NULL;
}
if (!has_exp_dig) {
- fprintf(stderr, "[error] %s: missing exp_dig attribute\n", __func__);
+ fprintf(fd, "[error] %s: missing exp_dig attribute\n", __func__);
return NULL;
}
if (!has_alignment) {
assert(left->u.unary_expression.type == UNARY_STRING);
if (!strcmp(left->u.unary_expression.u.string, "encoding")) {
if (right->u.unary_expression.type != UNARY_STRING) {
- fprintf(stderr, "[error] %s: encoding: expecting string\n",
+ fprintf(fd, "[error] %s: encoding: expecting string\n",
__func__);
return NULL;
}
encoding_c = right->u.unary_expression.u.string;
} else {
- fprintf(stderr, "[error] %s: unknown attribute name %s\n",
+ fprintf(fd, "[error] %s: unknown attribute name %s\n",
__func__, left->u.unary_expression.u.string);
return NULL;
}
}
-/*
- * Also add named variant, struct or enum to the current declaration scope.
- * FIXME: we are only taking the first one. check for root declaration specifiers list.
- */
static
-struct declaration *ctf_declaration_specifier_visit(FILE *fd,
- int depth, struct cds_list_head *head,
+struct declaration *ctf_type_specifier_list_visit(FILE *fd,
+ int depth, struct ctf_node *type_specifier_list,
struct declaration_scope *declaration_scope,
struct ctf_trace *trace)
{
struct ctf_node *first;
+ struct ctf_node *node;
- first = _cds_list_first_entry(head, struct ctf_node, siblings);
+ assert(type_specifier_list->type == NODE_TYPE_SPECIFIER_LIST);
- switch (first->type) {
- case NODE_STRUCT:
+ first = _cds_list_first_entry(&type_specifier_list->u.type_specifier_list.head, struct ctf_node, siblings);
+
+ assert(first->type == NODE_TYPE_SPECIFIER);
+
+ node = first->u.type_specifier.node;
+
+ switch (first->u.type_specifier.type) {
+ case TYPESPEC_FLOATING_POINT:
+ return ctf_declaration_floating_point_visit(fd, depth,
+ &node->u.floating_point.expressions, trace);
+ case TYPESPEC_INTEGER:
+ return ctf_declaration_integer_visit(fd, depth,
+ &node->u.integer.expressions, trace);
+ case TYPESPEC_STRING:
+ return ctf_declaration_string_visit(fd, depth,
+ &node->u.string.expressions, trace);
+ case TYPESPEC_STRUCT:
return ctf_declaration_struct_visit(fd, depth,
- first->u._struct.name,
- &first->u._struct.declaration_list,
- first->u._struct.has_body,
+ node->u._struct.name,
+ &node->u._struct.declaration_list,
+ node->u._struct.has_body,
+ &node->u._struct.min_align,
declaration_scope,
trace);
- case NODE_VARIANT:
+ case TYPESPEC_VARIANT:
return ctf_declaration_variant_visit(fd, depth,
- first->u.variant.name,
- first->u.variant.choice,
- &first->u.variant.declaration_list,
- first->u.variant.has_body,
+ node->u.variant.name,
+ node->u.variant.choice,
+ &node->u.variant.declaration_list,
+ node->u.variant.has_body,
declaration_scope,
trace);
- case NODE_ENUM:
+ case TYPESPEC_ENUM:
return ctf_declaration_enum_visit(fd, depth,
- first->u._enum.enum_id,
- &first->u._enum.container_type,
- &first->u._enum.enumerator_list,
- first->u._enum.has_body,
+ node->u._enum.enum_id,
+ node->u._enum.container_type,
+ &node->u._enum.enumerator_list,
+ node->u._enum.has_body,
declaration_scope,
trace);
- case NODE_INTEGER:
- return ctf_declaration_integer_visit(fd, depth,
- &first->u.integer.expressions, trace);
- case NODE_FLOATING_POINT:
- return ctf_declaration_floating_point_visit(fd, depth,
- &first->u.floating_point.expressions, trace);
- case NODE_STRING:
- return ctf_declaration_string_visit(fd, depth,
- &first->u.string.expressions, trace);
- case NODE_TYPE_SPECIFIER:
+
+ case TYPESPEC_VOID:
+ case TYPESPEC_CHAR:
+ case TYPESPEC_SHORT:
+ case TYPESPEC_INT:
+ case TYPESPEC_LONG:
+ case TYPESPEC_FLOAT:
+ case TYPESPEC_DOUBLE:
+ case TYPESPEC_SIGNED:
+ case TYPESPEC_UNSIGNED:
+ case TYPESPEC_BOOL:
+ case TYPESPEC_COMPLEX:
+ case TYPESPEC_IMAGINARY:
+ case TYPESPEC_CONST:
+ case TYPESPEC_ID_TYPE:
return ctf_declaration_type_specifier_visit(fd, depth,
- head, declaration_scope);
+ type_specifier_list, declaration_scope);
default:
- fprintf(stderr, "[error] %s: unexpected node type %d\n", __func__, (int) first->type);
+ fprintf(fd, "[error] %s: unexpected node type %d\n", __func__, (int) first->u.type_specifier.type);
return NULL;
}
}
case NODE_TYPEDEF:
ret = ctf_typedef_visit(fd, depth + 1,
event->declaration_scope,
- &node->u._typedef.declaration_specifier,
+ node->u._typedef.type_specifier_list,
&node->u._typedef.type_declarators,
trace);
if (ret)
if (!strcmp(left, "name")) {
char *right;
- if (CTF_EVENT_FIELD_IS_SET(event, name))
- return -EPERM;
+ if (CTF_EVENT_FIELD_IS_SET(event, name)) {
+ fprintf(fd, "[error] %s: name already declared in event declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
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;
+ fprintf(fd, "[error] %s: unexpected unary expression for event name\n", __func__);
+ ret = -EINVAL;
+ goto error;
}
event->name = g_quark_from_string(right);
g_free(right);
CTF_EVENT_SET_FIELD(event, name);
} else if (!strcmp(left, "id")) {
- if (CTF_EVENT_FIELD_IS_SET(event, id))
- return -EPERM;
+ if (CTF_EVENT_FIELD_IS_SET(event, id)) {
+ fprintf(fd, "[error] %s: id already declared in event declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
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;
+ fprintf(fd, "[error] %s: unexpected unary expression for event id\n", __func__);
+ ret = -EINVAL;
+ goto error;
}
CTF_EVENT_SET_FIELD(event, id);
} else if (!strcmp(left, "stream_id")) {
- if (CTF_EVENT_FIELD_IS_SET(event, stream_id))
- return -EPERM;
+ if (CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
+ fprintf(fd, "[error] %s: stream_id already declared in event declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
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;
+ fprintf(fd, "[error] %s: unexpected unary expression for event stream_id\n", __func__);
+ ret = -EINVAL;
+ goto error;
}
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;
+ fprintf(fd, "[error] %s: stream id %" PRIu64 " cannot be found\n", __func__, event->stream_id);
+ ret = -EINVAL;
+ goto error;
}
CTF_EVENT_SET_FIELD(event, stream_id);
} else if (!strcmp(left, "context")) {
struct declaration *declaration;
- declaration = ctf_declaration_specifier_visit(fd, depth,
- &node->u.ctf_expression.right,
+ if (event->context_decl) {
+ fprintf(fd, "[error] %s: context already declared in event declaration\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ declaration = ctf_type_specifier_list_visit(fd, depth,
+ _cds_list_first_entry(&node->u.ctf_expression.right,
+ struct ctf_node, siblings),
event->declaration_scope, trace);
- if (!declaration)
- return -EPERM;
- if (declaration->id != CTF_TYPE_STRUCT)
- return -EPERM;
+ if (!declaration) {
+ ret = -EPERM;
+ goto error;
+ }
+ if (declaration->id != CTF_TYPE_STRUCT) {
+ ret = -EPERM;
+ goto error;
+ }
event->context_decl = container_of(declaration, struct declaration_struct, p);
} else if (!strcmp(left, "fields")) {
struct declaration *declaration;
- declaration = ctf_declaration_specifier_visit(fd, depth,
- &node->u.ctf_expression.right,
+ if (event->fields_decl) {
+ fprintf(fd, "[error] %s: fields already declared in event declaration\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ declaration = ctf_type_specifier_list_visit(fd, depth,
+ _cds_list_first_entry(&node->u.ctf_expression.right,
+ struct ctf_node, siblings),
event->declaration_scope, trace);
- if (!declaration)
- return -EPERM;
- if (declaration->id != CTF_TYPE_STRUCT)
- return -EPERM;
+ if (!declaration) {
+ ret = -EPERM;
+ goto error;
+ }
+ if (declaration->id != CTF_TYPE_STRUCT) {
+ ret = -EPERM;
+ goto error;
+ }
event->fields_decl = container_of(declaration, struct declaration_struct, p);
}
+error:
g_free(left);
break;
}
/* TODO: declaration specifier should be added. */
}
- return 0;
+ return ret;
}
static
}
if (!CTF_EVENT_FIELD_IS_SET(event, name)) {
ret = -EPERM;
- goto error;
- }
- if (!CTF_EVENT_FIELD_IS_SET(event, id)) {
- ret = -EPERM;
+ fprintf(fd, "[error] %s: missing name field in event declaration\n", __func__);
goto error;
}
if (!CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
+ /* Allow missing stream_id if there is only a single stream */
+ switch (trace->streams->len) {
+ case 0: /* Create stream if there was none. */
+ ret = ctf_stream_visit(fd, depth, NULL, trace->root_declaration_scope, trace);
+ if (ret)
+ goto error;
+ /* Fall-through */
+ case 1:
+ event->stream_id = 0;
+ event->stream = trace_stream_lookup(trace, event->stream_id);
+ break;
+ default:
+ ret = -EPERM;
+ fprintf(fd, "[error] %s: missing stream_id field in event declaration\n", __func__);
+ goto error;
+ }
+ }
+ /* Allow only one event without id per stream */
+ if (!CTF_EVENT_FIELD_IS_SET(event, id)
+ && event->stream->events_by_id->len != 0) {
ret = -EPERM;
+ fprintf(fd, "[error] %s: missing id field in event declaration\n", __func__);
goto error;
}
if (event->stream->events_by_id->len <= event->id)
static
-int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream *stream, struct ctf_trace *trace)
+int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream_class *stream, struct ctf_trace *trace)
{
int ret = 0;
case NODE_TYPEDEF:
ret = ctf_typedef_visit(fd, depth + 1,
stream->declaration_scope,
- &node->u._typedef.declaration_specifier,
+ node->u._typedef.type_specifier_list,
&node->u._typedef.type_declarators,
trace);
if (ret)
char *left;
left = concatenate_unary_strings(&node->u.ctf_expression.left);
- if (!strcmp(left, "stream_id")) {
- if (CTF_STREAM_FIELD_IS_SET(stream, stream_id))
- return -EPERM;
+ if (!strcmp(left, "id")) {
+ if (CTF_STREAM_FIELD_IS_SET(stream, stream_id)) {
+ fprintf(fd, "[error] %s: id already declared in stream declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
ret = get_unary_unsigned(&node->u.ctf_expression.right, &stream->stream_id);
if (ret) {
- fprintf(stderr, "[error] %s: unexpected unary expression for event stream_id\n", __func__);
- return -EINVAL;
+ fprintf(fd, "[error] %s: unexpected unary expression for stream id\n", __func__);
+ ret = -EINVAL;
+ goto error;
}
CTF_STREAM_SET_FIELD(stream, stream_id);
} else if (!strcmp(left, "event.header")) {
struct declaration *declaration;
- declaration = ctf_declaration_specifier_visit(fd, depth,
- &node->u.ctf_expression.right,
+ if (stream->event_header_decl) {
+ fprintf(fd, "[error] %s: event.header already declared in stream declaration\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ declaration = ctf_type_specifier_list_visit(fd, depth,
+ _cds_list_first_entry(&node->u.ctf_expression.right,
+ struct ctf_node, siblings),
stream->declaration_scope, trace);
- if (!declaration)
- return -EPERM;
- if (declaration->id != CTF_TYPE_STRUCT)
- return -EPERM;
+ if (!declaration) {
+ ret = -EPERM;
+ goto error;
+ }
+ if (declaration->id != CTF_TYPE_STRUCT) {
+ ret = -EPERM;
+ goto error;
+ }
stream->event_header_decl = container_of(declaration, struct declaration_struct, p);
} else if (!strcmp(left, "event.context")) {
struct declaration *declaration;
- declaration = ctf_declaration_specifier_visit(fd, depth,
- &node->u.ctf_expression.right,
+ if (stream->event_context_decl) {
+ fprintf(fd, "[error] %s: event.context already declared in stream declaration\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ declaration = ctf_type_specifier_list_visit(fd, depth,
+ _cds_list_first_entry(&node->u.ctf_expression.right,
+ struct ctf_node, siblings),
stream->declaration_scope, trace);
- if (!declaration)
- return -EPERM;
- if (declaration->id != CTF_TYPE_STRUCT)
- return -EPERM;
+ if (!declaration) {
+ ret = -EPERM;
+ goto error;
+ }
+ if (declaration->id != CTF_TYPE_STRUCT) {
+ ret = -EPERM;
+ goto error;
+ }
stream->event_context_decl = container_of(declaration, struct declaration_struct, p);
} else if (!strcmp(left, "packet.context")) {
struct declaration *declaration;
- declaration = ctf_declaration_specifier_visit(fd, depth,
- &node->u.ctf_expression.right,
+ if (stream->packet_context_decl) {
+ fprintf(fd, "[error] %s: packet.context already declared in stream declaration\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ declaration = ctf_type_specifier_list_visit(fd, depth,
+ _cds_list_first_entry(&node->u.ctf_expression.right,
+ struct ctf_node, siblings),
stream->declaration_scope, trace);
- if (!declaration)
- return -EPERM;
- if (declaration->id != CTF_TYPE_STRUCT)
- return -EPERM;
+ if (!declaration) {
+ ret = -EPERM;
+ goto error;
+ }
+ if (declaration->id != CTF_TYPE_STRUCT) {
+ ret = -EPERM;
+ goto error;
+ }
stream->packet_context_decl = container_of(declaration, struct declaration_struct, p);
}
+error:
g_free(left);
break;
}
/* TODO: declaration specifier should be added. */
}
- return 0;
+ return ret;
}
static
{
int ret = 0;
struct ctf_node *iter;
- struct ctf_stream *stream;
+ struct ctf_stream_class *stream;
struct definition_scope *parent_def_scope;
- stream = g_new0(struct ctf_stream, 1);
+ stream = g_new0(struct ctf_stream_class, 1);
stream->declaration_scope = new_declaration_scope(parent_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;
+ stream->event_quark_to_id = g_hash_table_new(g_direct_hash, g_direct_equal);
+ stream->files = g_ptr_array_new();
+ if (node) {
+ 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_STREAM_FIELD_IS_SET(stream, stream_id)) {
- ret = -EPERM;
- goto error;
+ if (CTF_STREAM_FIELD_IS_SET(stream, stream_id)) {
+ /* check that packet header has stream_id field. */
+ if (!trace->packet_header_decl
+ || struct_declaration_lookup_field_index(trace->packet_header_decl, g_quark_from_static_string("stream_id")) < 0) {
+ ret = -EPERM;
+ fprintf(fd, "[error] %s: missing stream_id field in packet header declaration, but stream_id attribute is declared for stream.\n", __func__);
+ goto error;
+ }
+ } else {
+ /* Allow only one id-less stream */
+ if (trace->streams->len != 0) {
+ ret = -EPERM;
+ fprintf(fd, "[error] %s: missing id field in stream declaration\n", __func__);
+ goto error;
+ }
+ stream->stream_id = 0;
}
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;
- parent_def_scope = NULL;
+ parent_def_scope = trace->definition_scope;
if (stream->packet_context_decl) {
stream->packet_context =
container_of(
declaration_unref(&stream->event_header_decl->p);
declaration_unref(&stream->event_context_decl->p);
declaration_unref(&stream->packet_context_decl->p);
+ g_ptr_array_free(stream->files, TRUE);
g_ptr_array_free(stream->events_by_id, TRUE);
g_hash_table_destroy(stream->event_quark_to_id);
free_declaration_scope(stream->declaration_scope);
case NODE_TYPEDEF:
ret = ctf_typedef_visit(fd, depth + 1,
trace->declaration_scope,
- &node->u._typedef.declaration_specifier,
+ node->u._typedef.type_specifier_list,
&node->u._typedef.type_declarators,
trace);
if (ret)
left = concatenate_unary_strings(&node->u.ctf_expression.left);
if (!strcmp(left, "major")) {
- if (CTF_TRACE_FIELD_IS_SET(trace, major))
- return -EPERM;
+ if (CTF_TRACE_FIELD_IS_SET(trace, major)) {
+ fprintf(fd, "[error] %s: major already declared in trace declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
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;
+ fprintf(fd, "[error] %s: unexpected unary expression for trace major number\n", __func__);
+ ret = -EINVAL;
+ goto error;
}
CTF_TRACE_SET_FIELD(trace, major);
} else if (!strcmp(left, "minor")) {
- if (CTF_TRACE_FIELD_IS_SET(trace, minor))
- return -EPERM;
+ if (CTF_TRACE_FIELD_IS_SET(trace, minor)) {
+ fprintf(fd, "[error] %s: minor already declared in trace declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
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;
+ fprintf(fd, "[error] %s: unexpected unary expression for trace minor number\n", __func__);
+ ret = -EINVAL;
+ goto error;
}
CTF_TRACE_SET_FIELD(trace, minor);
- } else if (!strcmp(left, "word_size")) {
- if (CTF_TRACE_FIELD_IS_SET(trace, word_size))
- return -EPERM;
- ret = get_unary_unsigned(&node->u.ctf_expression.right, &trace->word_size);
- if (ret) {
- fprintf(stderr, "[error] %s: unexpected unary expression for trace word_size\n", __func__);
- return -EINVAL;
- }
- CTF_TRACE_SET_FIELD(trace, word_size);
} else if (!strcmp(left, "uuid")) {
- if (CTF_TRACE_FIELD_IS_SET(trace, uuid))
- return -EPERM;
+ if (CTF_TRACE_FIELD_IS_SET(trace, uuid)) {
+ fprintf(fd, "[error] %s: uuid already declared in trace declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
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;
+ fprintf(fd, "[error] %s: unexpected unary expression for trace uuid\n", __func__);
+ ret = -EINVAL;
+ goto error;
}
CTF_TRACE_SET_FIELD(trace, uuid);
+ } else if (!strcmp(left, "byte_order")) {
+ struct ctf_node *right;
+ int byte_order;
+
+ if (CTF_TRACE_FIELD_IS_SET(trace, byte_order)) {
+ fprintf(fd, "[error] %s: endianness already declared in trace declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+ right = _cds_list_first_entry(&node->u.ctf_expression.right, struct ctf_node, siblings);
+ byte_order = get_trace_byte_order(fd, depth, right);
+ if (byte_order < 0)
+ return -EINVAL;
+ trace->byte_order = byte_order;
+ CTF_TRACE_SET_FIELD(trace, byte_order);
+ } else if (!strcmp(left, "packet.header")) {
+ struct declaration *declaration;
+
+ if (trace->packet_header_decl) {
+ fprintf(fd, "[error] %s: packet.header already declared in trace declaration\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ declaration = ctf_type_specifier_list_visit(fd, depth,
+ _cds_list_first_entry(&node->u.ctf_expression.right,
+ struct ctf_node, siblings),
+ trace->declaration_scope, trace);
+ if (!declaration) {
+ ret = -EPERM;
+ goto error;
+ }
+ if (declaration->id != CTF_TYPE_STRUCT) {
+ ret = -EPERM;
+ goto error;
+ }
+ trace->packet_header_decl = container_of(declaration, struct declaration_struct, p);
}
+error:
g_free(left);
break;
}
/* TODO: declaration specifier should be added. */
}
- return 0;
+ return ret;
}
static
int ctf_trace_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
{
+ struct definition_scope *parent_def_scope;
int ret = 0;
struct ctf_node *iter;
}
if (!CTF_TRACE_FIELD_IS_SET(trace, major)) {
ret = -EPERM;
+ fprintf(fd, "[error] %s: missing major field in trace declaration\n", __func__);
goto error;
}
if (!CTF_TRACE_FIELD_IS_SET(trace, minor)) {
ret = -EPERM;
+ fprintf(fd, "[error] %s: missing minor field in trace declaration\n", __func__);
goto error;
}
if (!CTF_TRACE_FIELD_IS_SET(trace, uuid)) {
ret = -EPERM;
+ fprintf(fd, "[error] %s: missing uuid field in trace declaration\n", __func__);
goto error;
}
- if (!CTF_TRACE_FIELD_IS_SET(trace, word_size)) {
+ if (!CTF_TRACE_FIELD_IS_SET(trace, byte_order)) {
ret = -EPERM;
+ fprintf(fd, "[error] %s: missing byte_order field in trace declaration\n", __func__);
goto error;
}
+
+ parent_def_scope = NULL;
+ if (trace->packet_header_decl) {
+ trace->packet_header =
+ container_of(
+ 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 = trace->packet_header->scope;
+ declaration_unref(&trace->packet_header_decl->p);
+ }
+ trace->definition_scope = parent_def_scope;
+
+ if (!CTF_TRACE_FIELD_IS_SET(trace, byte_order)) {
+ /* check that the packet header contains a "magic" field */
+ if (!trace->packet_header
+ || 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;
+ }
+ }
return 0;
+error_free_def:
+ definition_unref(&trace->packet_header->p);
error:
g_ptr_array_free(trace->streams, TRUE);
free_declaration_scope(trace->declaration_scope);
return ret;
}
+static
+int ctf_root_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,
+ trace->root_declaration_scope,
+ node->u._typedef.type_specifier_list,
+ &node->u._typedef.type_declarators,
+ trace);
+ if (ret)
+ return ret;
+ break;
+ case NODE_TYPEALIAS:
+ ret = ctf_typealias_visit(fd, depth + 1,
+ trace->root_declaration_scope,
+ node->u.typealias.target, node->u.typealias.alias,
+ trace);
+ if (ret)
+ return ret;
+ break;
+ case NODE_TYPE_SPECIFIER_LIST:
+ {
+ struct declaration *declaration;
+
+ /*
+ * Just add the type specifier to the root scope
+ * declaration scope. Release local reference.
+ */
+ declaration = ctf_type_specifier_list_visit(fd, depth + 1,
+ node, trace->root_declaration_scope, trace);
+ if (!declaration)
+ return -ENOMEM;
+ declaration_unref(declaration);
+ break;
+ }
+ default:
+ return -EPERM;
+ }
+
+ return 0;
+}
+
int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
struct ctf_trace *trace, int byte_order)
{
int ret = 0;
struct ctf_node *iter;
+ 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) {
case NODE_ROOT:
cds_list_for_each_entry(iter, &node->u.root.declaration_list,
siblings) {
- switch (iter->type) {
- case NODE_TYPEDEF:
- ret = ctf_typedef_visit(fd, depth + 1,
- trace->root_declaration_scope,
- &iter->u._typedef.declaration_specifier,
- &iter->u._typedef.type_declarators,
- trace);
- if (ret)
- return ret;
- break;
- case NODE_TYPEALIAS:
- ret = ctf_typealias_visit(fd, depth + 1,
- trace->root_declaration_scope,
- iter->u.typealias.target, iter->u.typealias.alias,
- trace);
- if (ret)
- return ret;
- break;
- case NODE_DECLARATION_SPECIFIER:
- ret = ctf_declaration_specifier_visit(fd, depth, iter,
- trace->root_declaration_scope, trace);
- if (ret)
- return ret;
- break;
- default:
- fprintf(stderr, "[error] %s: unexpected root child type %d\n", __func__,
- (int) iter->type);
- return -EINVAL;
+ ret = ctf_root_declaration_visit(fd, depth + 1, iter, trace);
+ if (ret) {
+ fprintf(fd, "[error] %s: root declaration error\n", __func__);
+ return ret;
+ }
}
cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
ret = ctf_trace_visit(fd, depth + 1, iter, trace);
- if (ret)
+ if (ret) {
+ fprintf(fd, "[error] %s: trace declaration error\n", __func__);
return ret;
+ }
+ }
+ if (!trace->streams) {
+ fprintf(fd, "[error] %s: missing trace declaration\n", __func__);
+ return -EINVAL;
}
cds_list_for_each_entry(iter, &node->u.root.stream, siblings) {
ret = ctf_stream_visit(fd, depth + 1, iter,
trace->root_declaration_scope, trace);
- if (ret)
+ if (ret) {
+ fprintf(fd, "[error] %s: stream declaration error\n", __func__);
return ret;
+ }
}
cds_list_for_each_entry(iter, &node->u.root.event, siblings) {
ret = ctf_event_visit(fd, depth + 1, iter,
trace->root_declaration_scope, trace);
- if (ret)
+ if (ret) {
+ fprintf(fd, "[error] %s: event declaration error\n", __func__);
return ret;
+ }
}
break;
case NODE_UNKNOWN:
default:
- fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+ fprintf(fd, "[error] %s: unknown node type %d\n", __func__,
(int) node->type);
return -EINVAL;
}
+ printf_verbose("done.\n");
return ret;
}