[gobject-introspection/wip/structure-parsing: 2/3] scanner: Add notion of "private" structures, fix parsing



commit 43378bd809b7b9aa0f46f8257695b78ba0d28ff6
Author: Colin Walters <walters verbum org>
Date:   Wed Sep 8 15:23:22 2010 -0400

    scanner: Add notion of "private" structures, fix parsing

 giscanner/ast.py         |   20 +++++++++---
 giscanner/girparser.py   |    1 +
 giscanner/transformer.py |   76 +++++++++++++++++++++++++++-------------------
 3 files changed, 61 insertions(+), 36 deletions(-)
---
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 6e9dc89..13f290b 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -373,6 +373,7 @@ returned."""
             self._ctypes[node.symbol] = node
 
     def remove(self, node):
+        assert node.namespace is self
         if isinstance(node, Alias):
             del self._aliases[node.name]
         elif isinstance(node, Registered) and node.gtype_name is not None:
@@ -719,7 +720,8 @@ class Compound(Node, Registered):
                  gtype_name=None,
                  get_type=None,
                  c_symbol_prefix=None,
-                 disguised=False):
+                 disguised=False,
+                 private=False):
         Node.__init__(self, name)
         Registered.__init__(self, gtype_name, get_type)
         self.ctype = ctype
@@ -727,7 +729,11 @@ class Compound(Node, Registered):
         self.static_methods = []
         self.fields = []
         self.constructors = []
+        # This compound is: typedef struct Foo * Foo;
+        # note the * which hides that it's a pointer.
         self.disguised = disguised
+        # The definition of this structure is not known.
+        self.private = private
         self.gtype_name = gtype_name
         self.get_type = get_type
         self.c_symbol_prefix = c_symbol_prefix
@@ -771,13 +777,15 @@ class Record(Compound):
                  gtype_name=None,
                  get_type=None,
                  c_symbol_prefix=None,
-                 disguised=False):
+                 disguised=False,
+                 private=False):
         Compound.__init__(self, name,
                           ctype=ctype,
                           gtype_name=gtype_name,
                           get_type=get_type,
                           c_symbol_prefix=c_symbol_prefix,
-                          disguised=disguised)
+                          disguised=disguised,
+                          private=private)
         # If non-None, this record defines the FooClass C structure
         # for some Foo GObject (or similar for GInterface)
         self.is_gtype_struct_for = None
@@ -790,13 +798,15 @@ class Union(Compound):
                  gtype_name=None,
                  get_type=None,
                  c_symbol_prefix=None,
-                 disguised=False):
+                 disguised=False,
+                 private=False):
         Compound.__init__(self, name,
                           ctype=ctype,
                           gtype_name=gtype_name,
                           get_type=get_type,
                           c_symbol_prefix=c_symbol_prefix,
-                          disguised=disguised)
+                          disguised=disguised,
+                          private=private)
 
 
 class Boxed(Node, Registered):
diff --git a/giscanner/girparser.py b/giscanner/girparser.py
index ab2b29d..442fc33 100644
--- a/giscanner/girparser.py
+++ b/giscanner/girparser.py
@@ -334,6 +334,7 @@ class GIRParser(object):
         compound = cls(node.attrib.get('name'),
                        ctype=node.attrib.get(_cns('type')),
                        disguised=node.attrib.get('disguised') == '1',
+                       private=node.attrib.get('private') == '1',
                        gtype_name=node.attrib.get(_glibns('type-name')),
                        get_type=node.attrib.get(_glibns('get-type')),
                        c_symbol_prefix=node.attrib.get(_cns('symbol-prefix')))
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index 328d29e..9e35620 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -50,7 +50,8 @@ class Transformer(object):
         self._accept_unprefixed = accept_unprefixed
         self._namespace = namespace
         self._pkg_config_packages = set()
-        self._typedefs_ns = {}
+        self._typedefs = {}
+        self._hidden_structures = {}
         self._includes = {}
         self._include_names = set()
         self._includepaths = []
@@ -84,24 +85,25 @@ class Transformer(object):
             if node:
                 self._append_new_node(node)
 
-        # Now look through the namespace for things like
-        # typedef struct _Foo Foo;
-        # where we've never seen the struct _Foo.  Just create
-        # an empty structure for these as "disguised"
-        # If we do have a class/interface, merge fields
-        for typedef, compound in self._typedefs_ns.iteritems():
-            ns_compound = self._namespace.get(compound.name)
-            if not ns_compound:
-                ns_compound = self._namespace.get('_' + compound.name)
-            if (not ns_compound and isinstance(compound, (ast.Record, ast.Union))
-                and len(compound.fields) == 0):
-                disguised = ast.Record(compound.name, typedef, disguised=True)
-                self._namespace.append(disguised)
-            elif not ns_compound:
-                self._namespace.append(compound)
-            elif isinstance(ns_compound, (ast.Record, ast.Union)) and len(ns_compound.fields) == 0:
-                ns_compound.fields = compound.fields
-        self._typedefs_ns = None
+        for typedef, target_name in self._typedefs.iteritems():
+            if target_name.startswith('_'):
+                target = self._hidden_structures.get(target_name, None)
+            else:
+                continue
+            print "processing %r => %r, target=%r" % (typedef, target_name, target)
+            if target is None:
+                stub = ast.Record(typedef, typedef, private=True)
+                self._namespace.append(stub)
+            else:
+                target.name = typedef
+                self._namespace.append(target)
+                del self._hidden_structures[target_name]
+
+        for name, struct in self._hidden_structures.iteritems():
+            typedef = self._namespace.get(name[1:])
+            if not typedef:
+                message.warn_node(struct,
+"%r: Hidden structure with no corresponding typedef" % (name, ))
 
     def set_include_paths(self, paths):
         self._includepaths = list(paths)
@@ -282,7 +284,7 @@ raise ValueError."""
             return '_' + name
         return name
 
-    def _traverse_one(self, symbol, stype=None):
+    def _traverse_one(self, symbol, stype=None, is_field=False):
         assert isinstance(symbol, SourceSymbol), symbol
 
         if stype is None:
@@ -292,13 +294,13 @@ raise ValueError."""
         elif stype == CSYMBOL_TYPE_TYPEDEF:
             return self._create_typedef(symbol)
         elif stype == CSYMBOL_TYPE_STRUCT:
-            return self._create_struct(symbol)
+            return self._create_struct(symbol, is_field=is_field)
         elif stype == CSYMBOL_TYPE_ENUM:
             return self._create_enum(symbol)
         elif stype == CSYMBOL_TYPE_MEMBER:
             return self._create_member(symbol)
         elif stype == CSYMBOL_TYPE_UNION:
-            return self._create_union(symbol)
+            return self._create_union(symbol, is_field=is_field)
         elif stype == CSYMBOL_TYPE_CONST:
             return self._create_const(symbol)
         # Ignore variable declarations in the header
@@ -441,11 +443,11 @@ raise ValueError."""
             node = self._create_typedef_callback(symbol)
         elif (ctype == CTYPE_POINTER and
             symbol.base_type.base_type.type == CTYPE_STRUCT):
-            node = self._create_typedef_struct(symbol, disguised=True)
+            node = self._create_typedef_compound(ast.Struct, symbol, disguised=True)
         elif ctype == CTYPE_STRUCT:
-            node = self._create_typedef_struct(symbol)
+            node = self._create_typedef_compound(ast.Struct, symbol)
         elif ctype == CTYPE_UNION:
-            node = self._create_typedef_union(symbol)
+            node = self._create_typedef_compound(ast.Union, symbol)
         elif ctype == CTYPE_ENUM:
             return self._create_enum(symbol)
         elif ctype in (CTYPE_TYPEDEF,
@@ -597,17 +599,29 @@ raise ValueError."""
         const.add_symbol_reference(symbol)
         return const
 
-    def _create_typedef_struct(self, symbol, disguised=False):
+    def _create_typedef_compound(self, cls, symbol, disguised=False):
         try:
             name = self.strip_identifier(symbol.ident)
         except TransformerException, e:
             message.warn_symbol(symbol, e)
             return None
-        struct = ast.Record(name, symbol.ident, disguised=disguised)
-        self._parse_fields(symbol, struct)
-        struct.add_symbol_reference(symbol)
-        self._typedefs_ns[symbol.ident] = struct
-        return None
+
+        if disguised:
+            return cls(name, symbol.ident, disguised=True)
+
+        children = list(symbol.base_type.child_list)
+        if len(children) > 0:
+            compound = cls(name, symbol.ident, disguised)
+            self._parse_fields(symbol, compound)
+            compound.add_symbol_reference(symbol)
+            return compound
+        else:
+            try:
+                target_name = self.strip_identifier(symbol.base_type.name)
+            except TransformerException, e:
+                message.warn_symbol(symbol, e)
+                return None
+            self._typedefs[name] = target_name
 
     def _create_typedef_union(self, symbol):
         try:



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]