/* Hash table mapping field name GQuark to "struct definition" */
GHashTable *definitions;
struct definition_scope *parent_scope;
+ /*
+ * Complete "path" leading to this definition scope.
+ * Includes trace/stream/event '.' field name '.' field name '.' ....
+ * Array of GQuark elements (which are each separated by dots).
+ */
+ GArray *scope_path; /* array of GQuark */
};
enum ctf_type_id {
void (*declaration_free)(struct declaration *declaration);
struct definition *
(*definition_new)(struct declaration *declaration,
- struct definition_scope *parent_scope);
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index);
/*
* definition_free called with definition ref is decremented to 0.
*/
struct definition {
struct declaration *declaration;
+ int index; /* Position of the definition in its container */
int ref; /* number of references to the definition */
};
* definition scopes.
*/
struct definition *
- lookup_field_definition(GQuark field_name,
- struct definition_scope *scope);
+ lookup_definition(GArray *cur_path, /* array of GQuark */
+ GArray *lookup_path, /* array of GQuark */
+ struct definition_scope *scope);
int register_field_definition(GQuark field_name,
struct definition *definition,
struct definition_scope *scope);
struct definition_scope *
- new_definition_scope(struct definition_scope *parent_scope);
+ new_definition_scope(struct definition_scope *parent_scope,
+ GQuark field_name);
void free_definition_scope(struct definition_scope *scope);
void declaration_ref(struct declaration *declaration);
static
struct definition *_array_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope);
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index);
static
void _array_definition_free(struct definition *definition);
static
struct definition *
_array_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope)
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index)
{
struct declaration_array *array_declaration =
container_of(declaration, struct declaration_array, p);
array->p.declaration = declaration;
array->declaration = array_declaration;
array->p.ref = 1;
- array->scope = new_definition_scope(parent_scope);
+ array->p.index = index;
+ array->scope = new_definition_scope(parent_scope, field_name);
array->current_element.definition =
array_declaration->elem->definition_new(array_declaration->elem,
- parent_scope);
+ parent_scope,
+ g_quark_from_static_string("[]"),
+ 0);
return &array->p;
}
static
struct definition *_enum_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope);
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index);
static
void _enum_definition_free(struct definition *definition);
static
struct definition *
_enum_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope)
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index)
{
struct declaration_enum *enum_declaration =
container_of(declaration, struct declaration_enum, p);
_enum->p.declaration = declaration;
_enum->declaration = enum_declaration;
_enum->p.ref = 1;
+ _enum->p.index = index;
_enum->value = NULL;
definition_integer_parent =
enum_declaration->integer_declaration->p.definition_new(&enum_declaration->integer_declaration->p,
- parent_scope);
+ parent_scope, field_name, 0);
_enum->integer = container_of(definition_integer_parent,
struct definition_integer, p);
return &_enum->p;
static
struct definition *_float_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope);
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index);
static
void _float_definition_free(struct definition *definition);
static
struct definition *
_float_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope)
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index)
{
struct declaration_float *float_declaration =
container_of(declaration, struct declaration_float, p);
_float = g_new(struct definition_float, 1);
declaration_ref(&float_declaration->p);
- _float->p.declaration= declaration;
- _float->declaration= float_declaration;
+ _float->p.declaration = declaration;
+ _float->declaration = float_declaration;
_float->p.ref = 1;
+ _float->p.index = index;
_float->value = 0.0;
return &_float->p;
}
static
struct definition *_integer_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope);
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index);
static
void _integer_definition_free(struct definition *definition);
static
struct definition *
_integer_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope)
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index)
{
struct declaration_integer *integer_declaration =
container_of(declaration, struct declaration_integer, p);
integer->p.declaration = declaration;
integer->declaration = integer_declaration;
integer->p.ref = 1;
+ integer->p.index = index;
integer->value._unsigned = 0;
return &integer->p;
}
static
struct definition *_sequence_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope);
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index);
static
void _sequence_definition_free(struct definition *definition);
static
struct definition *_sequence_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope)
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index)
{
struct declaration_sequence *sequence_declaration =
container_of(declaration, struct declaration_sequence, p);
sequence->p.declaration = declaration;
sequence->declaration = sequence_declaration;
sequence->p.ref = 1;
- sequence->scope = new_definition_scope(parent_scope);
+ sequence->p.index = index;
+ sequence->scope = new_definition_scope(parent_scope, field_name);
len_parent = sequence_declaration->len_declaration->p.definition_new(&sequence_declaration->len_declaration->p,
- parent_scope);
+ parent_scope,
+ g_quark_from_static_string("length"), 0);
sequence->len =
container_of(len_parent, struct definition_integer, p);
sequence->current_element.definition =
sequence_declaration->elem->definition_new(sequence_declaration->elem,
- parent_scope);
+ parent_scope,
+ g_quark_from_static_string("[]"), 1);
return &sequence->p;
}
static
struct definition *_string_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope);
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index);
static
void _string_definition_free(struct definition *definition);
static
struct definition *
_string_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope)
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index)
{
struct declaration_string *string_declaration =
container_of(declaration, struct declaration_string, p);
string->p.declaration = declaration;
string->declaration = string_declaration;
string->p.ref = 1;
+ string->p.index = index;
string->value = NULL;
return &string->p;
}
static
struct definition *_struct_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope);
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index);
static
void _struct_definition_free(struct definition *definition);
static
struct definition *
_struct_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope)
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index)
{
struct declaration_struct *struct_declaration =
container_of(declaration, struct declaration_struct, p);
_struct->p.declaration = declaration;
_struct->declaration = struct_declaration;
_struct->p.ref = 1;
- _struct->scope = new_definition_scope(parent_scope);
+ _struct->p.index = index;
+ _struct->scope = new_definition_scope(parent_scope, field_name);
_struct->fields = g_array_sized_new(FALSE, TRUE,
sizeof(struct field),
DEFAULT_NR_STRUCT_FIELDS);
field->name = declaration_field->name;
field->definition =
declaration_field->declaration->definition_new(declaration_field->declaration,
- _struct->scope);
+ _struct->scope,
+ field->name, i);
ret = register_field_definition(field->name,
field->definition,
_struct->scope);
(gconstpointer) (unsigned long) field_name);
}
+/*
+ * Returns the index at which the paths differ.
+ * If the value returned equals len, it means the paths are identical
+ * from index 0 to len-1.
+ */
+static int compare_paths(GArray *a, GArray *b, int len)
+{
+ int i;
+
+ assert(len <= a->len);
+ assert(len <= b->len);
+
+ for (i = 0; i < len; i++) {
+ GQuark qa, qb;
+
+ qa = g_array_index(a, GQuark, i);
+ qb = g_array_index(b, GQuark, i);
+ if (qa != qb)
+ return i;
+ }
+ return i;
+}
+
+static int is_path_child_of(GArray *path, GArray *maybe_parent)
+{
+ if (path->len <= maybe_parent->len)
+ return 0;
+ if (compare_paths(path, maybe_parent, maybe_parent->len)
+ == maybe_parent->len)
+ return 1;
+ else
+ return 0;
+}
+
+static struct definition_scope *
+ get_definition_scope(struct definition *definition)
+{
+ switch (definition->declaration->id) {
+ case CTF_TYPE_STRUCT:
+ {
+ struct definition_struct *def =
+ container_of(definition, struct definition_struct, p);
+ return def->scope;
+ }
+ case CTF_TYPE_VARIANT:
+ {
+ struct definition_variant *def =
+ container_of(definition, struct definition_variant, p);
+ return def->scope;
+ }
+ case CTF_TYPE_ARRAY:
+ {
+ struct definition_array *def =
+ container_of(definition, struct definition_array, p);
+ return def->scope;
+ }
+ case CTF_TYPE_SEQUENCE:
+ {
+ struct definition_sequence *def =
+ container_of(definition, struct definition_sequence, p);
+ return def->scope;
+ }
+
+ case CTF_TYPE_INTEGER:
+ case CTF_TYPE_FLOAT:
+ case CTF_TYPE_ENUM:
+ case CTF_TYPE_STRING:
+ case CTF_TYPE_UNKNOWN:
+ default:
+ return NULL;
+ }
+}
+
+/*
+ * OK, here is the fun. We want to lookup a field that is:
+ * - either in the current scope, but prior to the current field.
+ * - or in a parent scope (or parent of parent ...) still in a field
+ * prior to the current field position within the parents.
+ * A reaching through a dynamic scoping (e.g. from payload structure to
+ * event header structure), the parent fields are always entirely prior
+ * to the child.
+ * If we cannot find such a field that is prior to our current path, we
+ * return NULL.
+ *
+ * cur_path: the path leading to the variant definition.
+ * lookup_path: the path leading to the enum we want to look for.
+ * scope: the definition scope containing the variant definition.
+ */
struct definition *
- lookup_field_definition(GQuark field_name,
- struct definition_scope *scope)
+ lookup_definition(GArray *cur_path,
+ GArray *lookup_path,
+ struct definition_scope *scope)
{
- struct definition *definition;
+ struct definition *definition, *lookup_definition;
+ GQuark last;
+ int index;
while (scope) {
- definition = lookup_field_definition_scope(field_name, scope);
- if (definition)
- return definition;
- scope = scope->parent_scope;
+ /* going up in the hierarchy. Check where we come from. */
+ assert(is_path_child_of(cur_path, scope->scope_path));
+ assert(cur_path->len - scope->scope_path->len == 1);
+ last = g_array_index(cur_path, GQuark, cur_path->len - 1);
+ definition = lookup_field_definition_scope(last, scope);
+ assert(definition);
+ index = definition->index;
+lookup:
+ if (is_path_child_of(lookup_path, scope->scope_path)) {
+ /* Means we can lookup the field in this scope */
+ last = g_array_index(lookup_path, GQuark,
+ scope->scope_path->len);
+ lookup_definition = lookup_field_definition_scope(last, scope);
+ if (!lookup_definition || ((index != -1) && lookup_definition->index >= index))
+ return NULL;
+ /* Found it! And it is prior to the current field. */
+ if (lookup_path->len - scope->scope_path->len == 1) {
+ /* Direct child */
+ return lookup_definition;
+ } else {
+ scope = get_definition_scope(lookup_definition);
+ /* Check if the definition has a sub-scope */
+ if (!scope)
+ return NULL;
+ /*
+ * Don't compare index anymore, because we are
+ * going within a scope that has been validated
+ * to be entirely prior to the current scope.
+ */
+ cur_path = NULL;
+ index = -1;
+ goto lookup;
+ }
+ } else {
+ assert(index != -1);
+ /* lookup_path is within an upper scope */
+ cur_path = scope->scope_path;
+ scope = scope->parent_scope;
+ }
}
return NULL;
}
}
struct definition_scope *
- new_definition_scope(struct definition_scope *parent_scope)
+ new_definition_scope(struct definition_scope *parent_scope,
+ GQuark field_name)
{
struct definition_scope *scope = g_new(struct definition_scope, 1);
+ int scope_path_len = 1;
scope->definitions = g_hash_table_new_full(g_direct_hash,
g_direct_equal, NULL,
(GDestroyNotify) definition_unref);
scope->parent_scope = parent_scope;
+ if (scope->parent_scope)
+ scope_path_len += scope->parent_scope->scope_path->len;
+ scope->scope_path = g_array_sized_new(FALSE, TRUE, sizeof(GQuark),
+ scope_path_len);
+ g_array_set_size(scope->scope_path, scope_path_len);
+ if (scope->parent_scope)
+ memcpy(scope->scope_path, scope->parent_scope->scope_path,
+ sizeof(GQuark) * (scope_path_len - 1));
+ g_array_index(scope->scope_path, GQuark, scope_path_len - 1) =
+ field_name;
return scope;
}
void free_definition_scope(struct definition_scope *scope)
{
+ g_array_free(scope->scope_path, TRUE);
g_hash_table_destroy(scope->definitions);
g_free(scope);
}
static
struct definition *_variant_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope);
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index);
static
void _variant_definition_free(struct definition *definition);
static
struct definition *
_variant_definition_new(struct declaration *declaration,
- struct definition_scope *parent_scope)
+ struct definition_scope *parent_scope,
+ GQuark field_name, int index)
{
struct declaration_variant *variant_declaration =
container_of(declaration, struct declaration_variant, p);
variant->p.declaration = declaration;
variant->declaration = variant_declaration;
variant->p.ref = 1;
- variant->scope = new_definition_scope(parent_scope);
+ variant->p.index = index;
+ variant->scope = new_definition_scope(parent_scope, field_name);
variant->fields = g_array_sized_new(FALSE, TRUE,
sizeof(struct field),
DEFAULT_NR_STRUCT_FIELDS);
struct field, i);
field->name = declaration_field->name;
+ /*
+ * All child definition are at index 0, because they are
+ * various choices of the same field.
+ */
field->definition =
declaration_field->declaration->definition_new(declaration_field->declaration,
- variant->scope);
+ variant->scope,
+ field->name, 0);
}
variant->current_field = NULL;
return &variant->p;