From 9256e916164ec557ed66f92a0d6d95bb286cdf8b Mon Sep 17 00:00:00 2001 From: Johan Dahlin Date: Mon, 12 Jan 2009 23:24:01 +0000 Subject: =?UTF-8?q?Bug=20563591=20=E2=80=93=20Flags=20not=20recognized=20w?= =?UTF-8?q?hen=20there=20is=20no=20introspection=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2009-01-12 Johan Dahlin Bug 563591 – Flags not recognized when there is no introspection data * giscanner/ast.py: * giscanner/girwriter.py: * giscanner/giscannermodule.c (type_get_is_bitfield): * giscanner/glibast.py: * giscanner/glibtransformer.py: * giscanner/scannerparser.y: * giscanner/sourcescanner.c (gi_source_type_copy): * giscanner/sourcescanner.h: * giscanner/sourcescanner.py: * giscanner/transformer.py: * tests/scanner/foo-1.0-expected.gir: * tests/scanner/foo-1.0-expected.tgir: * tests/scanner/foo.h: Large parts of this patch was done by Jürg Billeter. svn path=/trunk/; revision=1025 --- ChangeLog | 20 ++++++++++++++++++++ giscanner/ast.py | 11 +++++++++++ giscanner/girwriter.py | 29 +++++++++++++++++++++-------- giscanner/giscannermodule.c | 8 ++++++++ giscanner/glibast.py | 23 +++++++++++++++-------- giscanner/glibtransformer.py | 9 +++++++-- giscanner/scannerparser.y | 20 ++++++++++++++++++-- giscanner/sourcescanner.c | 1 + giscanner/sourcescanner.h | 1 + giscanner/sourcescanner.py | 6 +++++- giscanner/transformer.py | 12 ++++++++---- tests/scanner/foo-1.0-expected.gir | 5 +++++ tests/scanner/foo-1.0-expected.tgir | 5 +++++ tests/scanner/foo.h | 9 ++++++++- 14 files changed, 133 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index d94ffd69..7e4c22b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2009-01-12 Johan Dahlin + + Bug 563591 – Flags not recognized when there is no introspection data + + * giscanner/ast.py: + * giscanner/girwriter.py: + * giscanner/giscannermodule.c (type_get_is_bitfield): + * giscanner/glibast.py: + * giscanner/glibtransformer.py: + * giscanner/scannerparser.y: + * giscanner/sourcescanner.c (gi_source_type_copy): + * giscanner/sourcescanner.h: + * giscanner/sourcescanner.py: + * giscanner/transformer.py: + * tests/scanner/foo-1.0-expected.gir: + * tests/scanner/foo-1.0-expected.tgir: + * tests/scanner/foo.h: + + Large parts of this patch was done by Jürg Billeter. + 2009-01-12 Havoc Pennington Bug 563386 – scanner ignores "const" on boxed return values diff --git a/giscanner/ast.py b/giscanner/ast.py index c5dc436c..b141691d 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -328,6 +328,17 @@ class Enum(Node): return 'Enum(%r, %r)' % (self.name, self.members) +class Bitfield(Node): + + def __init__(self, name, symbol, members): + Node.__init__(self, name) + self.symbol = symbol + self.members = members + + def __repr__(self): + return 'Bitfield(%r, %r)' % (self.name, self.members) + + class Member(Node): def __init__(self, name, value, symbol): diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index f82a73e5..e72b0289 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -23,8 +23,9 @@ from __future__ import with_statement import os from ctypes.util import find_library -from .ast import (Callback, Class, Constant, Enum, Function, Interface, Member, - Array, Struct, Alias, Union, List, Map, Varargs) +from .ast import (Alias, Array, Bitfield, Callback, Class, Constant, Enum, + Function, Interface, List, Map, Member, Struct, Union, + Varargs) from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags, GLibObject, GLibInterface) from .xmlwriter import XMLWriter @@ -72,6 +73,8 @@ class GIRWriter(XMLWriter): self._write_function(node) elif isinstance(node, Enum): self._write_enum(node) + elif isinstance(node, Bitfield): + self._write_bitfield(node) elif isinstance(node, (Class, Interface)): self._write_class(node) elif isinstance(node, Callback): @@ -221,20 +224,30 @@ class GIRWriter(XMLWriter): attrs = [('name', enum.name)] self._append_version(enum, attrs) self._append_deprecated(enum, attrs) - if isinstance(enum, GLibFlags): - tag_name = 'bitfield' - else: - tag_name = 'enumeration' - if isinstance(enum, GLibEnum) or isinstance(enum, GLibFlags): + if isinstance(enum, GLibEnum): attrs.extend([('glib:type-name', enum.type_name), ('glib:get-type', enum.get_type), ('c:type', enum.ctype)]) else: attrs.append(('c:type', enum.symbol)) - with self.tagcontext(tag_name, attrs): + with self.tagcontext('enumeration', attrs): for member in enum.members: self._write_member(member) + def _write_bitfield(self, bitfield): + attrs = [('name', bitfield.name)] + self._append_version(bitfield, attrs) + self._append_deprecated(bitfield, attrs) + if isinstance(bitfield, GLibFlags): + attrs.extend([('glib:type-name', bitfield.type_name), + ('glib:get-type', bitfield.get_type), + ('c:type', bitfield.ctype)]) + else: + attrs.append(('c:type', bitfield.symbol)) + with self.tagcontext('bitfield', attrs): + for member in bitfield.members: + self._write_member(member) + def _write_member(self, member): attrs = [('name', member.name), ('value', str(member.value)), diff --git a/giscanner/giscannermodule.c b/giscanner/giscannermodule.c index afa4c29c..7d75f55b 100644 --- a/giscanner/giscannermodule.c +++ b/giscanner/giscannermodule.c @@ -256,6 +256,13 @@ type_get_child_list (PyGISourceType *self, return list; } +static PyObject * +type_get_is_bitfield (PyGISourceType *self, + void *context) +{ + return PyInt_FromLong (self->type->is_bitfield); +} + static const PyGetSetDef _PyGISourceType_getsets[] = { { "type", (getter)type_get_type, NULL, NULL}, { "storage_class_specifier", (getter)type_get_storage_class_specifier, NULL, NULL}, @@ -264,6 +271,7 @@ static const PyGetSetDef _PyGISourceType_getsets[] = { { "name", (getter)type_get_name, NULL, NULL}, { "base_type", (getter)type_get_base_type, NULL, NULL}, { "child_list", (getter)type_get_child_list, NULL, NULL}, + { "is_bitfield", (getter)type_get_is_bitfield, NULL, NULL}, { 0 } }; diff --git a/giscanner/glibast.py b/giscanner/glibast.py index 637dc633..a804f620 100644 --- a/giscanner/glibast.py +++ b/giscanner/glibast.py @@ -18,7 +18,8 @@ # Boston, MA 02111-1307, USA. # -from .ast import Class, Enum, Interface, Member, Node, Property, Struct, Union +from .ast import (Bitfield, Class, Enum, Interface, Member, Node, + Property, Struct, Union) from .ast import ( type_names, default_array_types, TYPE_STRING, TYPE_INT8, TYPE_UINT8, TYPE_INT16, TYPE_UINT16, @@ -71,15 +72,21 @@ class GLibEnum(Enum): self.get_type = get_type def __repr__(self): - return '%s(%r, %r, %r)' % ( - self.__class__.__name__, - self.name, - self.members, - self.get_type) + return 'GlibEnum(%r, %r, %r)' % (self.name, self.members, + self.get_type) -class GLibFlags(GLibEnum): - pass +class GLibFlags(Bitfield): + + def __init__(self, name, type_name, members, get_type): + Bitfield.__init__(self, name, type_name, members) + self.ctype = type_name + self.type_name = type_name + self.get_type = get_type + + def __repr__(self): + return 'GlibFlags(%r, %r, %r)' % (self.name, self.members, + self.get_type) class GLibEnumMember(Member): diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py index ee39862e..d46c3c0f 100644 --- a/giscanner/glibtransformer.py +++ b/giscanner/glibtransformer.py @@ -25,8 +25,8 @@ import tempfile import shutil import subprocess -from .ast import (Callback, Constant, Enum, Function, Member, Namespace, - Parameter, Property, Return, Struct, Type, Alias, +from .ast import (Alias, Bitfield, Callback, Constant, Enum, Function, Member, + Namespace, Parameter, Property, Return, Struct, Type, Union, Field, type_name_from_ctype, default_array_types, TYPE_UINT8, PARAM_TRANSFER_FULL) from .transformer import Names @@ -259,6 +259,8 @@ class GLibTransformer(object): def _parse_node(self, node): if isinstance(node, Enum): self._parse_enum(node) + elif isinstance(node, Bitfield): + self._parse_bitfield(node) elif isinstance(node, Function): self._parse_function(node) elif isinstance(node, Struct): @@ -283,6 +285,9 @@ class GLibTransformer(object): def _parse_enum(self, enum): self._add_attribute(enum) + def _parse_bitfield(self, enum): + self._add_attribute(enum) + def _parse_constant(self, constant): self._add_attribute(constant) diff --git a/giscanner/scannerparser.y b/giscanner/scannerparser.y index 64cf11b3..dffe90e2 100644 --- a/giscanner/scannerparser.y +++ b/giscanner/scannerparser.y @@ -46,6 +46,7 @@ static void yyerror (GISourceScanner *scanner, const char *str); extern void ctype_free (GISourceType * type); static int last_enum_value = -1; +static gboolean is_bitfield; static GHashTable *const_table = NULL; %} @@ -381,6 +382,12 @@ shift_expression $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST); $$->const_int_set = TRUE; $$->const_int = $1->const_int << $3->const_int; + + /* assume this is a bitfield/flags declaration + * if a left shift operator is sued in an enum value + * This mimics the glib-mkenum behavior. + */ + is_bitfield = TRUE; } | shift_expression SR additive_expression { @@ -818,24 +825,28 @@ enum_specifier { $$ = gi_source_enum_new ($2); $$->child_list = $4; + $$->is_bitfield = is_bitfield; last_enum_value = -1; } | ENUM '{' enumerator_list '}' { $$ = gi_source_enum_new (NULL); $$->child_list = $3; + $$->is_bitfield = is_bitfield; last_enum_value = -1; } | ENUM identifier_or_typedef_name '{' enumerator_list ',' '}' { $$ = gi_source_enum_new ($2); $$->child_list = $4; + $$->is_bitfield = is_bitfield; last_enum_value = -1; } | ENUM '{' enumerator_list ',' '}' { $$ = gi_source_enum_new (NULL); $$->child_list = $3; + $$->is_bitfield = is_bitfield; last_enum_value = -1; } | ENUM identifier_or_typedef_name @@ -845,9 +856,14 @@ enum_specifier ; enumerator_list - : enumerator + : { - $$ = g_list_append (NULL, $1); + /* reset flag before the first enum value */ + is_bitfield = FALSE; + } + enumerator + { + $$ = g_list_append (NULL, $2); } | enumerator_list ',' enumerator { diff --git a/giscanner/sourcescanner.c b/giscanner/sourcescanner.c index cf412362..1a2508d9 100644 --- a/giscanner/sourcescanner.c +++ b/giscanner/sourcescanner.c @@ -108,6 +108,7 @@ gi_source_type_copy (GISourceType * type) result->base_type = gi_source_type_copy (type->base_type); for (l = type->child_list; l; l = l->next) result->child_list = g_list_append (result->child_list, gi_source_symbol_ref (l->data)); + result->is_bitfield = type->is_bitfield; return result; } diff --git a/giscanner/sourcescanner.h b/giscanner/sourcescanner.h index 69417d11..f36a8084 100644 --- a/giscanner/sourcescanner.h +++ b/giscanner/sourcescanner.h @@ -127,6 +127,7 @@ struct _GISourceType char *name; GISourceType *base_type; GList *child_list; /* list of GISourceSymbol */ + gboolean is_bitfield; }; GISourceScanner * gi_source_scanner_new (void); diff --git a/giscanner/sourcescanner.py b/giscanner/sourcescanner.py index 5018bf43..56aac93e 100644 --- a/giscanner/sourcescanner.py +++ b/giscanner/sourcescanner.py @@ -104,7 +104,7 @@ def ctype_name(ctype): class SourceType(object): __members__ = ['type', 'base_type', 'name', 'type_qualifier', - 'child_list'] + 'child_list', 'is_bitfield'] def __init__(self, scanner, stype): self._scanner = scanner @@ -140,6 +140,10 @@ class SourceType(object): continue yield SourceSymbol(self._scanner, symbol) + @property + def is_bitfield(self): + return self._stype.is_bitfield + class SourceSymbol(object): __members__ = ['const_int', 'const_string', 'ident', 'type', 'base_type'] diff --git a/giscanner/transformer.py b/giscanner/transformer.py index 8e335ff6..b7e8c5df 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -20,7 +20,7 @@ import os -from .ast import (Callback, Enum, Function, Namespace, Member, +from .ast import (Bitfield, Callback, Enum, Function, Namespace, Member, Parameter, Return, Struct, Field, Type, Array, Alias, Interface, Class, Node, Union, Varargs, Constant, type_name_from_ctype, @@ -210,9 +210,13 @@ class Transformer(object): child.ident)) enum_name = self.remove_prefix(symbol.ident) - enum = Enum(enum_name, symbol.ident, members) - self._names.type_names[symbol.ident] = (None, enum) - return enum + if symbol.base_type.is_bitfield: + klass = Bitfield + else: + klass = Enum + node = klass(enum_name, symbol.ident, members) + self._names.type_names[symbol.ident] = (None, node) + return node def _create_object(self, symbol): return Member(symbol.ident, symbol.base_type.name, diff --git a/tests/scanner/foo-1.0-expected.gir b/tests/scanner/foo-1.0-expected.gir index 84a5cc3a..17fd5200 100644 --- a/tests/scanner/foo-1.0-expected.gir +++ b/tests/scanner/foo-1.0-expected.gir @@ -301,6 +301,11 @@ + + + + + diff --git a/tests/scanner/foo-1.0-expected.tgir b/tests/scanner/foo-1.0-expected.tgir index 8c205a9c..2cb29d39 100644 --- a/tests/scanner/foo-1.0-expected.tgir +++ b/tests/scanner/foo-1.0-expected.tgir @@ -193,6 +193,11 @@ + + + + + diff --git a/tests/scanner/foo.h b/tests/scanner/foo.h index dbef015b..f08fc3c7 100644 --- a/tests/scanner/foo.h +++ b/tests/scanner/foo.h @@ -128,6 +128,8 @@ typedef enum FOO_FLAGS_THIRD = 1 << 2 } FooFlagsType; +GType foo_flags_type_get_type (void); + typedef enum { FOO_ENUM_UN = 1, @@ -136,7 +138,12 @@ typedef enum FOO_ENUM_NEUF = 9 } FooEnumNoType; -GType foo_flags_type_get_type (void); +typedef enum +{ + FOO_FLAGS_ETT = 1 << 0, + FOO_FLAGS_TVA = 1 << 1, + FOO_FLAGS_FYRA = 1 << 2 +} FooFlagsNoType; typedef enum { -- cgit v1.2.1