diff options
-rw-r--r-- | ChangeLog | 37 | ||||
-rw-r--r-- | girepository/girparser.c | 73 | ||||
-rw-r--r-- | giscanner/girwriter.py | 43 | ||||
-rw-r--r-- | giscanner/glibtransformer.py | 8 | ||||
-rw-r--r-- | giscanner/transformer.py | 22 | ||||
-rw-r--r-- | tests/repository/Makefile.am | 3 | ||||
-rw-r--r-- | tests/scanner/utility-1.0-expected.gir | 29 | ||||
-rw-r--r-- | tests/scanner/utility-1.0-expected.tgir | 12 | ||||
-rw-r--r-- | tests/scanner/utility.h | 21 |
9 files changed, 206 insertions, 42 deletions
@@ -1,4 +1,41 @@ 2009-02-03 Andreas Rottmann <a.rottmann@gmx.at> + + * tests/scanner/utility.h (UtilityTaggedValue): Make the union + member anonymous. + (UtilityByte): New union typedef with an unnamed struct in it. + + * giscanner/transformer.py (Transformer._create_struct): Create + unnamed structs for symbols with a None ident. + (Transformer._create_union): Likewise. + + * giscanner/girwriter.py (GIRWriter._write_record): Allow name + being None. + (GIRWriter._write_union): Likewise. + + * girepository/girparser.c (start_struct): Allow a NULL name for + non-toplevel structs. + (start_union): Likewise. + + * tests/scanner/utility.h (UtilityTaggedValue): New struct + typedef, which has a nested union member. + * tests/scanner/utility-expected.gir: Adapted. + + * giscanner/transformer.py (Transformer._create_member): Create + struct/union members if appropriate. + (Transformer._create_struct, Transformer._create_union): Allow for + structs/unions without a C type. + + * giscanner/glibtransformer.py (GLibTransformer._resolve_field): + We don't need to resolve non-typef'd + (GLibTransformer._resolve_field): Add cases for non-typedef'd + struct/union "fields". + + * giscanner/girwriter.py (GIRWriter._write_record): Allow for + records without a C type. + (GIRWriter._write_field): structs and unions may appear in places + where fields do. + +2009-02-03 Andreas Rottmann <a.rottmann@gmx.at> * girepository/girparser.c (ParseContext): Removed member current_node, added node_stack instead. diff --git a/girepository/girparser.c b/girepository/girparser.c index 46c16e5b..3e1f9dfe 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -2112,7 +2112,10 @@ start_struct (GMarkupParseContext *context, GError **error) { if (strcmp (element_name, "record") == 0 && - ctx->state == STATE_NAMESPACE) + (ctx->state == STATE_NAMESPACE || + ctx->state == STATE_UNION || + ctx->state == STATE_STRUCT || + ctx->state == STATE_CLASS)) { const gchar *name; const gchar *deprecated; @@ -2127,7 +2130,7 @@ start_struct (GMarkupParseContext *context, gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values); gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values); - if (name == NULL) + if (name == NULL && ctx->node_stack == NULL) { MISSING_ATTRIBUTE (context, error, element_name, "name"); return FALSE; @@ -2145,7 +2148,7 @@ start_struct (GMarkupParseContext *context, struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT); - ((GIrNode *)struct_)->name = g_strdup (name); + ((GIrNode *)struct_)->name = g_strdup (name ? name : ""); if (deprecated) struct_->deprecated = TRUE; else @@ -2156,9 +2159,10 @@ start_struct (GMarkupParseContext *context, struct_->gtype_name = g_strdup (gtype_name); struct_->gtype_init = g_strdup (gtype_init); - - ctx->current_module->entries = - g_list_append (ctx->current_module->entries, struct_); + + if (ctx->node_stack == NULL) + ctx->current_module->entries = + g_list_append (ctx->current_module->entries, struct_); push_node (ctx, (GIrNode *)struct_); state_switch (ctx, STATE_STRUCT); @@ -2176,8 +2180,11 @@ start_union (GMarkupParseContext *context, ParseContext *ctx, GError **error) { - if (strcmp (element_name, "union") == 0 && - ctx->state == STATE_NAMESPACE) + if (strcmp (element_name, "union") == 0 && + (ctx->state == STATE_NAMESPACE || + ctx->state == STATE_UNION || + ctx->state == STATE_STRUCT || + ctx->state == STATE_CLASS)) { const gchar *name; const gchar *deprecated; @@ -2189,7 +2196,7 @@ start_union (GMarkupParseContext *context, typename = find_attribute ("glib:type-name", attribute_names, attribute_values); typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values); - if (name == NULL) + if (name == NULL && ctx->node_stack == NULL) MISSING_ATTRIBUTE (context, error, element_name, "name"); else { @@ -2197,7 +2204,7 @@ start_union (GMarkupParseContext *context, union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION); - ((GIrNode *)union_)->name = g_strdup (name); + ((GIrNode *)union_)->name = g_strdup (name ? name : ""); union_->gtype_name = g_strdup (typename); union_->gtype_init = g_strdup (typeinit); if (deprecated) @@ -2205,8 +2212,9 @@ start_union (GMarkupParseContext *context, else union_->deprecated = FALSE; - ctx->current_module->entries = - g_list_append (ctx->current_module->entries, union_); + if (ctx->node_stack == NULL) + ctx->current_module->entries = + g_list_append (ctx->current_module->entries, union_); push_node (ctx, (GIrNode *)union_); state_switch (ctx, STATE_UNION); @@ -2685,6 +2693,41 @@ require_one_of_end_elements (GMarkupParseContext *context, } static gboolean +state_switch_end_struct_or_union (GMarkupParseContext *context, + ParseContext *ctx, + const gchar *element_name, + GError **error) +{ + pop_node (ctx); + if (ctx->node_stack == NULL) + { + state_switch (ctx, STATE_NAMESPACE); + } + else + { + if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT) + state_switch (ctx, STATE_STRUCT); + else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION) + state_switch (ctx, STATE_UNION); + else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT) + state_switch (ctx, STATE_CLASS); + else + { + int line_number, char_number; + g_markup_parse_context_get_position (context, &line_number, &char_number); + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Unexpected end tag '%s' on line %d char %d", + element_name, + line_number, char_number); + return FALSE; + } + } + return TRUE; +} + +static gboolean require_end_element (GMarkupParseContext *context, ParseContext *ctx, const char *expected_name, @@ -2897,8 +2940,7 @@ end_element_handler (GMarkupParseContext *context, case STATE_STRUCT: if (require_end_element (context, ctx, "record", element_name, error)) { - pop_node (ctx); - state_switch (ctx, STATE_NAMESPACE); + state_switch_end_struct_or_union (context, ctx, element_name, error); } break; @@ -2914,8 +2956,7 @@ end_element_handler (GMarkupParseContext *context, case STATE_UNION: if (require_end_element (context, ctx, "union", element_name, error)) { - pop_node (ctx); - state_switch (ctx, STATE_NAMESPACE); + state_switch_end_struct_or_union (context, ctx, element_name, error); } break; case STATE_IMPLEMENTS: diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index 51a208d7..cd19e989 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -366,8 +366,11 @@ and/or use gtk-doc annotations. ''') ('glib:get-type', boxed.get_type)] def _write_record(self, record): - attrs = [('name', record.name), - ('c:type', record.symbol)] + attrs = [] + if record.name is not None: + attrs.append(('name', record.name)) + if record.symbol is not None: # the record might be anonymous + attrs.append(('c:type', record.symbol)) if record.disguised: attrs.append(('disguised', '1')) if record.doc: @@ -386,8 +389,11 @@ and/or use gtk-doc annotations. ''') self._write_method(method) def _write_union(self, union): - attrs = [('name', union.name), - ('c:type', union.symbol)] + attrs = [] + if union.name is not None: + attrs.append(('name', union.name)) + if union.symbol is not None: # the union might be anonymous + attrs.append(('c:type', union.symbol)) if union.doc: attrs.append(('doc', union.doc)) self._append_version(union, attrs) @@ -410,19 +416,22 @@ and/or use gtk-doc annotations. ''') if isinstance(field, Callback): self._write_callback(field) - return - - attrs = [('name', field.name)] - # Fields are assumed to be read-only - # (see also girparser.c and generate.c) - if not field.readable: - attrs.append(('readable', '0')) - if field.writable: - attrs.append(('writable', '1')) - if field.bits: - attrs.append(('bits', str(field.bits))) - with self.tagcontext('field', attrs): - self._write_type(field.type) + elif isinstance(field, Struct): + self._write_record(field) + elif isinstance(field, Union): + self._write_union(field) + else: + attrs = [('name', field.name)] + # Fields are assumed to be read-only + # (see also girparser.c and generate.c) + if not field.readable: + attrs.append(('readable', '0')) + if field.writable: + attrs.append(('writable', '1')) + if field.bits: + attrs.append(('bits', str(field.bits))) + with self.tagcontext('field', attrs): + self._write_type(field.type) def _write_signal(self, signal): attrs = [('name', signal.name)] diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py index 51076a2f..749b6524 100644 --- a/giscanner/glibtransformer.py +++ b/giscanner/glibtransformer.py @@ -870,8 +870,12 @@ class GLibTransformer(object): def _resolve_field(self, field): if isinstance(field, Callback): self._resolve_function(field) - return - field.type = self._resolve_param_type(field.type) + elif isinstance(field, Record): # non-typedef'd struct + self._resolve_record(field) + elif isinstance(field, Union): # non-typedef'd union + self._resolve_union(field) + else: + field.type = self._resolve_param_type(field.type) def _resolve_alias(self, alias): alias.target = self._resolve_type_name(alias.target, alias.target) diff --git a/giscanner/transformer.py b/giscanner/transformer.py index 1d781c60..f6e89ce1 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -307,6 +307,10 @@ class Transformer(object): if (source_type.type == CTYPE_POINTER and symbol.base_type.base_type.type == CTYPE_FUNCTION): node = self._create_callback(symbol) + elif source_type.type == CTYPE_STRUCT and source_type.name is None: + node = self._create_struct(symbol, anonymous=True) + elif source_type.type == CTYPE_UNION and source_type.name is None: + node = self._create_union(symbol, anonymous=True) else: # Special handling for fields; we don't have annotations on them # to apply later, yet. @@ -478,8 +482,14 @@ class Transformer(object): self._typedefs_ns[callback.name] = callback return callback - def _create_compound(self, klass, symbol): - compound = self._typedefs_ns.get(symbol.ident, None) + def _create_compound(self, klass, symbol, anonymous): + if symbol.ident is None: + # the compound is an anonymous member of another union or a struct + assert anonymous + compound = klass(None, None) + else: + compound = self._typedefs_ns.get(symbol.ident, None) + if compound is None: # This is a bit of a hack; really we should try # to resolve through the typedefs to find the real @@ -500,11 +510,11 @@ class Transformer(object): return compound - def _create_struct(self, symbol): - return self._create_compound(Struct, symbol) + def _create_struct(self, symbol, anonymous=False): + return self._create_compound(Struct, symbol, anonymous) - def _create_union(self, symbol): - return self._create_compound(Union, symbol) + def _create_union(self, symbol, anonymous=False): + return self._create_compound(Union, symbol, anonymous) def _create_callback(self, symbol): parameters = self._create_parameters(symbol.base_type.base_type) diff --git a/tests/repository/Makefile.am b/tests/repository/Makefile.am index 1dd5c4c7..e21cff43 100644 --- a/tests/repository/Makefile.am +++ b/tests/repository/Makefile.am @@ -13,4 +13,5 @@ gitestthrows_CPPFLAGS = $(GIREPO_CFLAGS) -I$(top_srcdir)/girepository gitestthrows_LDADD = $(top_builddir)/girepository/libgirepository-1.0.la $(GIREPO_LIBS) TESTS = gitestrepo gitestthrows -TESTS_ENVIRONMENT=env top_builddir="$(top_builddir)" $(DEBUG) +TESTS_ENVIRONMENT=env top_builddir="$(top_builddir)" $(DEBUG) \ + XDG_DATA_DIRS="$(top_srcdir)/gir:$(XDG_DATA_DIRS)" diff --git a/tests/scanner/utility-1.0-expected.gir b/tests/scanner/utility-1.0-expected.gir index 81c1a6b8..bb5a5e46 100644 --- a/tests/scanner/utility-1.0-expected.gir +++ b/tests/scanner/utility-1.0-expected.gir @@ -46,6 +46,35 @@ and/or use gtk-doc annotations. --> <type name="GObject.ObjectClass" c:type="GObjectClass"/> </field> </record> + <record name="TaggedValue" c:type="UtilityTaggedValue"> + <field name="tag" writable="1"> + <type name="int" c:type="int"/> + </field> + <union> + <field name="v_pointer" writable="1"> + <type name="any" c:type="gpointer"/> + </field> + <field name="v_real" writable="1"> + <type name="double" c:type="double"/> + </field> + <field name="v_integer" writable="1"> + <type name="long" c:type="long"/> + </field> + </union> + </record> + <union name="Byte" c:type="UtilityByte"> + <field name="value" writable="1"> + <type name="uint8" c:type="guint8"/> + </field> + <record> + <field name="first_nibble" writable="1" bits="4"> + <type name="uint8" c:type="guint8"/> + </field> + <field name="second_nibble" writable="1" bits="4"> + <type name="uint8" c:type="guint8"/> + </field> + </record> + </union> <callback name="FileFunc" c:type="UtilityFileFunc"> <return-value transfer-ownership="none"> <type name="none" c:type="void"/> diff --git a/tests/scanner/utility-1.0-expected.tgir b/tests/scanner/utility-1.0-expected.tgir index 26e6d196..7a2364ea 100644 --- a/tests/scanner/utility-1.0-expected.tgir +++ b/tests/scanner/utility-1.0-expected.tgir @@ -35,6 +35,18 @@ <type name="GObject.ObjectClass"/> </field> </record> + <record name="TaggedValue"> + <field name="tag" writable="1"> + <type name="int"/> + </field> + <!-- FIXME: anonymous union member missing --> + </record> + <union name="Byte"> + <field name="value" writable="1"> + <type name="uint8"/> + </field> + <!-- FIXME: anonymous struct member missing --> + </union> <callback name="FileFunc"> <return-value transfer-ownership="none"> <type name="none"/> diff --git a/tests/scanner/utility.h b/tests/scanner/utility.h index a744f037..b493a677 100644 --- a/tests/scanner/utility.h +++ b/tests/scanner/utility.h @@ -23,6 +23,27 @@ struct _UtilityObjectClass /* This one is similar to Pango.Glyph */ typedef guint32 UtilityGlyph; +typedef struct +{ + int tag; + union + { + gpointer v_pointer; + double v_real; + long v_integer; + }; +} UtilityTaggedValue; + +typedef union +{ + guint8 value; + struct + { + guint8 first_nibble : 4; + guint8 second_nibble : 4; + }; +} UtilityByte; + typedef void (*UtilityFileFunc)(const char *path, gpointer user_data); GType utility_object_get_type (void) G_GNUC_CONST; |