Bug 563591 – Flags not recognized when there is no introspection data
authorJohan Dahlin <jdahlin@async.com.br>
Mon, 12 Jan 2009 23:24:01 +0000 (23:24 +0000)
committerJohan Dahlin <johan@src.gnome.org>
Mon, 12 Jan 2009 23:24:01 +0000 (23:24 +0000)
2009-01-12  Johan Dahlin  <jdahlin@async.com.br>

        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

14 files changed:
ChangeLog
giscanner/ast.py
giscanner/girwriter.py
giscanner/giscannermodule.c
giscanner/glibast.py
giscanner/glibtransformer.py
giscanner/scannerparser.y
giscanner/sourcescanner.c
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

index d94ffd6..7e4c22b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2009-01-12  Johan Dahlin  <jdahlin@async.com.br>
+
+       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  <hp@pobox.com>
 
        Bug 563386 – scanner ignores "const" on boxed return values
index c5dc436..b141691 100644 (file)
@@ -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):
index f82a73e..e72b028 100644 (file)
@@ -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)),
index afa4c29..7d75f55 100644 (file)
@@ -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 }
 };
 
index 637dc63..a804f62 100644 (file)
@@ -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):
index ee39862..d46c3c0 100644 (file)
@@ -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)
 
index 64cf11b..dffe90e 100644 (file)
@@ -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
          {
index cf41236..1a2508d 100644 (file)
@@ -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;
 }
 
index 69417d1..f36a808 100644 (file)
@@ -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);
index 5018bf4..56aac93 100644 (file)
@@ -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']
index 8e335ff..b7e8c5d 100644 (file)
@@ -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,
index 84a5cc3..17fd520 100644 (file)
       <member name="trois" value="3" c:identifier="FOO_ENUM_TROIS"/>
       <member name="neuf" value="9" c:identifier="FOO_ENUM_NEUF"/>
     </enumeration>
+    <bitfield name="FlagsNoType" c:type="FooFlagsNoType">
+      <member name="ett" value="1" c:identifier="FOO_FLAGS_ETT"/>
+      <member name="tva" value="2" c:identifier="FOO_FLAGS_TVA"/>
+      <member name="fyra" value="4" c:identifier="FOO_FLAGS_FYRA"/>
+    </bitfield>
     <enumeration name="EnumFullname" c:type="FooEnumFullname">
       <member name="one" value="1" c:identifier="FOO_ENUM_FULLNAME_ONE"/>
       <member name="two" value="2" c:identifier="FOO_ENUM_FULLNAME_TWO"/>
index 8c205a9..2cb29d3 100644 (file)
       <member name="trois" value="3"/>
       <member name="neuf" value="9"/>
     </enumeration>
+    <bitfield name="FlagsNoType">
+      <member name="ett" value="1"/>
+      <member name="tva" value="2"/>
+      <member name="fyra" value="4"/>
+    </bitfield>
     <enumeration name="EnumFullname">
       <member name="one" value="1"/>
       <member name="two" value="2"/>
index dbef015..f08fc3c 100644 (file)
@@ -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
 {