From ac88af7594050b366fadec583e60ac26bb2aff75 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sun, 27 Feb 2011 12:34:06 -0500 Subject: [PATCH] Declaration scope lookup Signed-off-by: Mathieu Desnoyers --- include/babeltrace/types.h | 10 +++++- types/struct.c | 19 +++++++++++ types/types.c | 67 +++++++++++++++++++++++++++++--------- types/variant.c | 15 +++++++++ 4 files changed, 94 insertions(+), 17 deletions(-) diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 3d396c86..718d391a 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -91,6 +91,8 @@ struct declaration; struct declaration_scope { /* Hash table mapping type name GQuark to struct type */ GHashTable *types; + /* Hash table mapping field name GQuark to struct declaration */ + GHashTable *declarations; struct declaration_scope *parent_scope; }; @@ -229,6 +231,7 @@ struct type_field { }; struct field { + GQuark name; struct declaration *declaration; }; @@ -287,9 +290,14 @@ struct declaration_sequence { struct field current_element; /* struct field */ }; -struct type *lookup_type(GQuark qname, struct declaration_scope *scope); +struct type *lookup_type(GQuark type_name, struct declaration_scope *scope); int register_type(struct type *type, struct declaration_scope *scope); +struct declaration * + lookup_declaration(GQuark field_name, struct declaration_scope *scope); +int register_declaration(GQuark field_name, struct declaration *declaration, + struct declaration_scope *scope); + void type_ref(struct type *type); void type_unref(struct type *type); diff --git a/types/struct.c b/types/struct.c index 92ede586..baedbddb 100644 --- a/types/struct.c +++ b/types/struct.c @@ -102,6 +102,8 @@ struct declaration * struct type_struct *struct_type = container_of(type, struct type_struct, p); struct declaration_struct *_struct; + unsigned long i; + int ret; _struct = g_new(struct declaration_struct, 1); type_ref(&struct_type->p); @@ -112,6 +114,22 @@ struct declaration * _struct->fields = g_array_sized_new(FALSE, TRUE, sizeof(struct field), DEFAULT_NR_STRUCT_FIELDS); + g_array_set_size(_struct->fields, struct_type->fields->len); + for (i = 0; i < struct_type->fields->len; i++) { + struct type_field *type_field = + &g_array_index(struct_type->fields, + struct type_field, i); + struct field *field = &g_array_index(_struct->fields, + struct field, i); + + field->name = type_field->name; + field->declaration = + type_field->type->declaration_new(type_field->type, + _struct->scope); + ret = register_declaration(field->name, + field->declaration, _struct->scope); + assert(!ret); + } return &_struct->p; } @@ -122,6 +140,7 @@ void _struct_declaration_free(struct declaration *declaration) container_of(declaration, struct declaration_struct, p); unsigned long i; + assert(_struct->fields->len == _struct->type->fields->len); for (i = 0; i < _struct->fields->len; i++) { struct field *field = &g_array_index(_struct->fields, struct field, i); diff --git a/types/types.c b/types/types.c index 8272b814..e001dd02 100644 --- a/types/types.c +++ b/types/types.c @@ -23,18 +23,19 @@ #include static -struct type *lookup_type_scope(GQuark qname, struct declaration_scope *scope) +struct type * + lookup_type_scope(GQuark type_name, struct declaration_scope *scope) { return g_hash_table_lookup(scope->types, - (gconstpointer) (unsigned long) qname); + (gconstpointer) (unsigned long) type_name); } -struct type *lookup_type(GQuark qname, struct declaration_scope *scope) +struct type *lookup_type(GQuark type_name, struct declaration_scope *scope) { struct type *type; while (scope) { - type = lookup_type_scope(qname, scope); + type = lookup_type_scope(type_name, scope); if (type) return type; scope = scope->parent_scope; @@ -42,16 +43,6 @@ struct type *lookup_type(GQuark qname, struct declaration_scope *scope) return NULL; } -static void free_type(struct type *type) -{ - type->type_free(type); -} - -static void free_declaration(struct declaration *declaration) -{ - declaration->type->declaration_free(declaration); -} - int register_type(struct type *type, struct declaration_scope *scope) { if (!type->name) @@ -64,6 +55,46 @@ int register_type(struct type *type, struct declaration_scope *scope) g_hash_table_insert(scope->types, (gpointer) (unsigned long) type->name, type); + type_ref(type); + return 0; +} + +static +struct declaration * + lookup_declaration_scope(GQuark field_name, struct declaration_scope *scope) +{ + return g_hash_table_lookup(scope->declarations, + (gconstpointer) (unsigned long) field_name); +} + +struct declaration * + lookup_declaration(GQuark field_name, struct declaration_scope *scope) +{ + struct declaration *declaration; + + while (scope) { + declaration = lookup_declaration_scope(field_name, scope); + if (declaration) + return declaration; + scope = scope->parent_scope; + } + return NULL; +} + +int register_declaration(GQuark field_name, struct declaration *declaration, + struct declaration_scope *scope) +{ + if (!field_name) + return -EPERM; + + /* Only lookup in local scope */ + if (lookup_declaration_scope(field_name, scope)) + return -EEXIST; + + g_hash_table_insert(scope->declarations, + (gpointer) (unsigned long) field_name, + declaration); + declaration_ref(declaration); return 0; } @@ -75,7 +106,7 @@ void type_ref(struct type *type) void type_unref(struct type *type) { if (!--type->ref) - free_type(type); + type->type_free(type); } void declaration_ref(struct declaration *declaration) @@ -86,7 +117,7 @@ void declaration_ref(struct declaration *declaration) void declaration_unref(struct declaration *declaration) { if (!--declaration->ref) - free_declaration(declaration); + declaration->type->declaration_free(declaration); } struct declaration_scope * @@ -97,12 +128,16 @@ struct declaration_scope * scope->types = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) type_unref); + scope->declarations = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, + (GDestroyNotify) declaration_unref); scope->parent_scope = parent_scope; return scope; } void free_declaration_scope(struct declaration_scope *scope) { + g_hash_table_destroy(scope->declarations); g_hash_table_destroy(scope->types); g_free(scope); } diff --git a/types/variant.c b/types/variant.c index 91b323ff..3c2244be 100644 --- a/types/variant.c +++ b/types/variant.c @@ -96,6 +96,7 @@ struct declaration * struct type_variant *variant_type = container_of(type, struct type_variant, p); struct declaration_variant *variant; + unsigned long i; variant = g_new(struct declaration_variant, 1); type_ref(&variant_type->p); @@ -106,6 +107,19 @@ struct declaration * variant->fields = g_array_sized_new(FALSE, TRUE, sizeof(struct field), DEFAULT_NR_STRUCT_FIELDS); + g_array_set_size(variant->fields, variant_type->fields->len); + for (i = 0; i < variant_type->fields->len; i++) { + struct type_field *type_field = + &g_array_index(variant_type->fields, + struct type_field, i); + struct field *field = &g_array_index(variant->fields, + struct field, i); + + field->name = type_field->name; + field->declaration = + type_field->type->declaration_new(type_field->type, + variant->scope); + } variant->current_field = NULL; return &variant->p; } @@ -117,6 +131,7 @@ void _variant_declaration_free(struct declaration *declaration) container_of(declaration, struct declaration_variant, p); unsigned long i; + assert(variant->fields->len == variant->type->fields->len); for (i = 0; i < variant->fields->len; i++) { struct field *field = &g_array_index(variant->fields, struct field, i); -- 2.34.1