[gobject-introspection/transformer] g-ir-scanner --passthrough-gir basically works



commit 5ebd93da24adfced551d476935b0c9eda47b8700
Author: Colin Walters <walters verbum org>
Date:   Thu Jun 17 15:55:37 2010 -0400

    g-ir-scanner --passthrough-gir basically works

 docs/g-ir-scanner.1           |    3 -
 gir/Makefile.am               |    7 +-
 giscanner/annotationparser.py |    4 +-
 giscanner/ast.py              |  399 +++++++++++++++++---------------
 giscanner/girparser.py        |  298 +++++++++++++++--------
 giscanner/girwriter.py        |  123 +++++-----
 giscanner/glibast.py          |   14 +-
 giscanner/glibtransformer.py  |  525 +++++++++++++----------------------------
 giscanner/scannermain.py      |   76 ++-----
 giscanner/sourcescanner.py    |   10 +-
 giscanner/transformer.py      |  302 +++++------------------
 11 files changed, 736 insertions(+), 1025 deletions(-)
---
diff --git a/docs/g-ir-scanner.1 b/docs/g-ir-scanner.1
index b43d3f1..750660a 100644
--- a/docs/g-ir-scanner.1
+++ b/docs/g-ir-scanner.1
@@ -106,9 +106,6 @@ several pkg-config packages.
 .B \--verbose
 Be verbose, include some debugging information.
 .TP
-.B \--noclosure
-Do not delete unknown types from the resulting format.
-.TP
 .B \--typelib-xml
 Convert the resulting xml to only output the types relevant
 to the typelib compiler. This is mainly useful for verifying the
diff --git a/gir/Makefile.am b/gir/Makefile.am
index 8fa02b0..2300297 100644
--- a/gir/Makefile.am
+++ b/gir/Makefile.am
@@ -31,7 +31,7 @@ GLIB_LIBRARY=glib-2.0
 endif
 
 GLib_2_0_gir_LIBS = $(GLIB_LIBRARY)
-GLib_2_0_gir_SCANNERFLAGS = --noclosure --strip-prefix=g --c-include="glib.h"
+GLib_2_0_gir_SCANNERFLAGS = --strip-prefix=g --c-include="glib.h"
 GLib_2_0_gir_PACKAGES = glib-2.0
 GLib_2_0_gir_CFLAGS = \
             -I$(GLIB_INCLUDEDIR) \
@@ -61,7 +61,7 @@ endif
 GObject-2.0.gir: GLib-2.0.gir
 
 GObject_2_0_gir_LIBS = $(GOBJECT_LIBRARY)
-GObject_2_0_gir_SCANNERFLAGS = --noclosure --strip-prefix=g --c-include="glib-object.h" --add-include-path=.
+GObject_2_0_gir_SCANNERFLAGS = --strip-prefix=g --c-include="glib-object.h" --add-include-path=.
 GObject_2_0_gir_PACKAGES = gobject-2.0
 GObject_2_0_gir_INCLUDES = GLib-2.0
 GObject_2_0_gir_CFLAGS = \
@@ -87,7 +87,7 @@ endif
 GModule-2.0.gir: GLib-2.0.gir
 
 GModule_2_0_gir_LIBS = $(GMODULE_LIBRARY)
-GModule_2_0_gir_SCANNERFLAGS = --noclosure --strip-prefix=g --c-include="gmodule.h" --add-include-path=.
+GModule_2_0_gir_SCANNERFLAGS = --strip-prefix=g --c-include="gmodule.h" --add-include-path=.
 GModule_2_0_gir_PACKAGES = gmodule-2.0
 GModule_2_0_gir_INCLUDES = GLib-2.0
 GModule_2_0_gir_CFLAGS = \
@@ -137,7 +137,6 @@ GIRepository-2.0.gir: GObject-2.0.gir $(top_builddir)/girepository/libgireposito
 
 GIRepository_2_0_gir_LIBS = girepository-1.0
 GIRepository_2_0_gir_SCANNERFLAGS = \
-        --noclosure \
         --strip-prefix=g \
         --c-include="girepository.h" \
         --pkg-export gobject-introspection-1.0 \
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py
index 03ffb54..4af6c03 100644
--- a/giscanner/annotationparser.py
+++ b/giscanner/annotationparser.py
@@ -323,7 +323,7 @@ class AnnotationApplier(object):
 
     def parse(self, namespace):
         self._namespace = namespace
-        for node in namespace.nodes[:]:
+        for node in namespace:
             self._parse_node(node)
         del self._namespace
 
@@ -779,7 +779,7 @@ class AnnotationApplier(object):
                 element_type is None):
                 # FIXME: unsigned char/guchar should be uint8
                 container_type.element_type = Type('int8')
-        container_type.size = array_values.get(OPT_ARRAY_FIXED_SIZE)
+        container_type.size = int(array_values.get(OPT_ARRAY_FIXED_SIZE))
         return container_type
 
     def _resolve(self, type_str, orig_node=None):
diff --git a/giscanner/ast.py b/giscanner/ast.py
index a70f2d8..53e0b68 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -19,6 +19,8 @@
 # Boston, MA 02111-1307, USA.
 #
 
+from .odict import odict
+
 """AST nodes
 This file descbribes abstract data type nodes independent on the
 implementation language.
@@ -168,21 +170,136 @@ default_out_types = (TYPE_SHORT, TYPE_USHORT, TYPE_INT, TYPE_UINT,
 def type_name_from_ctype(ctype):
     return type_names.get(ctype, ctype)
 
+class Namespace(object):
+    names = property(lambda self: self._names)
+    aliases = property(lambda self: self._aliases)
+    type_names = property(lambda self: self._type_names)
+    ctypes = property(lambda self: self._ctypes)
 
-class Node(object):
+    def __init__(self, name, version, c_prefix=None):
+        self.name = name
+        self.version = version
+        self.c_prefix = c_prefix
+        self._names = odict() # Maps from GIName -> node
+        self._aliases = {} # Maps from GIName -> GIName
+        self._type_names = {} # Maps from GTName -> node
+        self._ctypes = {} # Maps from CType -> node
+
+    def type_from_name(self, name, ctype=None):
+        """Backwards compatibility method for older .gir files, which
+only use the 'name' attribute.  If name refers to a fundamental type,
+create a Type object referncing it.  If name is already a
+fully-qualified GIName like 'Foo.Bar', returns a Type targeting it .
+Otherwise a Type targeting name qualififed with the namespace name is
+returned."""
+        if name in GIR_TYPES:
+            return Type(target_fundamental=name, ctype=ctype)
+        if '.' in name:
+            target = name
+        else:
+            target = '%s.%s' % (self.name, name)
+        return Type(target_giname=target, ctype=ctype)
+
+    def append(self, node, replace=False):
+        previous = self._names.get(node.name)
+        if previous is not None:
+            if not replace:
+                raise SystemExit(
+                    "transformer: conflict: ns=%r orig=%r new=%r" % 
+                    (self.name, previous, node))
+            self.remove(previous)
+        # A layering violation...but oh well.
+        from .glibast import GLibBoxed
+        if isinstance(node, Alias):
+            self._aliases[node.name] = node
+        elif isinstance(node, (GLibBoxed, Interface, Class)):
+            self._type_names[node.type_name] = node
+        assert isinstance(node, Node)
+        assert node.namespace is None
+        node.namespace = self
+        self._names[node.name] = node
+        if hasattr(node, 'ctype'):
+            self._ctypes[node.ctype] = node
+        elif hasattr(node, 'symbol'):
+            self._ctypes[node.symbol] = node
+
+    def remove(self, node):
+        from .glibast import GLibBoxed
+        if isinstance(node, Alias):
+            del self._aliases[node.name]
+        elif isinstance(node, (GLibBoxed, Interface, Class)):
+            del self._type_names[node.type_name]
+        node.namespace = None
+        if hasattr(node, 'ctype'):
+            del self._ctypes[node.ctype]
+        if hasattr(node, 'symbol'):
+            del self._ctypes[node.symbol]
+
+    def __iter__(self):
+        return iter(self._names)
+
+    def iteritems(self):
+        return self._names.iteritems()
+
+    def itervalues(self):
+        return self._names.itervalues()
+
+    def get(self, name):
+        return self._names.get(name)
+
+
+class Include(object):
 
-    def __init__(self, name=None):
+    def __init__(self, name, version):
         self.name = name
+        self.version = version
+
+    @classmethod
+    def from_string(self, string):
+        return Include(*string.split('-', 1))
+
+    def __cmp__(self, other):
+        if not isinstance(other, Include):
+            return cmp(self, other)
+        namecmp = cmp(self.name, other.name)
+        if namecmp != 0:
+            return namecmp
+        return cmp(self.version, other.version)
+
+    def __hash__(self):
+        return hash((self.name, self.version))
+
+    def __str__(self):
+        return '%s-%s' % (self.name, self.version)
+
+class Annotated(object):
+    """An object which has a few generic metadata
+properties."""
+    def __init__(self):
+        self.version = None
         self.skip = False
         self.introspectable = True
         self.attributes = [] # (key, value)*
         self.deprecated = None
         self.deprecated_version = None
-        self.version = None
+        self.doc = None
+
+class Node(Annotated):
+    """A node is a type of object which is uniquely identified by its
+(namespace, name) pair.  When combined with a ., this is called a
+GIName.  It's possible for nodes to contain or point to other nodes."""
+
+    def __init__(self, name=None):
+        Annotated.__init__(self)
+        self.namespace = None # Should be set later by Namespace.append()
+        self.name = name
         self.foreign = False
         self.file_positions = set()
 
     def __cmp__(self, other):
+        nscmp = cmp(self.namespace, other.namespace)
+        if nscmp != 0:
+            return nscmp
         return cmp(self.name, other.name)
 
     def __repr__(self):
@@ -201,49 +318,6 @@ class Node(object):
         if symbol.source_filename:
             self.add_file_position(symbol.source_filename, symbol.line, -1)
 
-class Namespace(Node):
-
-    def __init__(self, name, version):
-        Node.__init__(self, name)
-        self.version = version
-        self.nodes = []
-
-    def __repr__(self):
-        return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
-                                   self.version, self.nodes)
-
-    def remove_matching(self, pred):
-
-        def recursive_pred(node):
-            node.remove_matching_children(pred)
-            return pred(node)
-
-        self.nodes = filter(recursive_pred, self.nodes)
-
-class Include(Node):
-
-    def __init__(self, name, version):
-        Node.__init__(self, 'include')
-        self.name = name
-        self.version = version
-
-    @classmethod
-    def from_string(self, string):
-        return Include(*string.split('-', 1))
-
-    def __cmp__(self, other):
-        if not isinstance(other, Include):
-            return cmp(self, other)
-        namecmp = cmp(self.name, other.name)
-        if namecmp != 0:
-            return namecmp
-        return cmp(self.version, other.version)
-
-    def __hash__(self):
-        return hash((self.name, self.version))
-
-    def __str__(self):
-        return '%s-%s' % (self.name, self.version)
 
 class Callable(Node):
 
@@ -252,20 +326,24 @@ class Callable(Node):
         self.retval = retval
         self.parameters = parameters
         self.throws = not not throws
-        self.doc = None
 
-    def __repr__(self):
-        return '%s(%r, %r, %r)' % (self.__class__.__name__,
-                                   self.name, self.retval,
-                                   self.parameters)
+    def get_parameter_index(self, name):
+        for i, parameter in enumerate(self.parameters):
+            if parameter.name == name:
+                return i
+
+    def get_parameter(self, name):
+        for parameter in self.parameters:
+            if parameter.name == name:
+                return parameter
+
 
 class Function(Callable):
 
-    def __init__(self, name, retval, parameters, symbol, throws=None):
+    def __init__(self, name, retval, parameters, throws, symbol):
         Callable.__init__(self, name, retval, parameters, throws)
         self.symbol = symbol
         self.is_method = False
-        self.doc = None
 
     def get_parameter_index(self, name):
         for i, parameter in enumerate(self.parameters):
@@ -291,59 +369,78 @@ class VFunction(Callable):
         return obj
 
 
-class Type(Node):
-
-    def __init__(self, name, ctype=None):
-        Node.__init__(self, name)
+class Type(object):
+    """A Type can be either:
+* A reference to a node (target_giname)
+* A reference to a "fundamental" type like 'utf8'
+* A "foreign" type - this can be any string."
+If none are specified, then it's in an "unresolved" state.
+In this case, the ctype must be specified.
+"""
+    def __init__(self, 
+                 ctype=None, 
+                 target_fundamental=None,
+                 target_giname=None,
+                 target_foreign=None,
+                 is_const=False):
+        if target_fundamental:
+            assert target_giname is None
+            assert target_foreign is None
+            self.resolved = True
+        elif target_giname:
+            assert target_fundamental is None
+            assert target_foreign is None
+            self.resolved = True
+        elif target_foreign:
+            assert ctype is not None
+            assert target_giname is None
+            assert target_fundamental is None
+            self.resolved = True
+        else:
+            assert ctype is not None
+            self.resolved = False
         self.ctype = ctype
-        self.resolved = False
-        self.is_const = False
-        self.canonical = None
-        self.derefed_canonical = None
+        self.target_fundamental = target_fundamental
+        self.target_giname = target_giname
+        self.target_foreign = target_foreign
+        self.is_const = is_const
 
 
 class Varargs(Type):
 
     def __init__(self):
-        Type.__init__(self, '<varargs>')
+        Type.__init__(self, '<varargs>', target_fundamental='<varargs>')
 
 
 class Array(Type):
 
-    def __init__(self, name, ctype, element_type):
-        if name is None:
-            name = '<carray>'
-        Type.__init__(self, name, ctype)
+    def __init__(self, name, element_type, **kwargs):
+        Type.__init__(self, target_fundamental='<array>',
+                      **kwargs)
+        self.name = name
         self.element_type = element_type
         self.zeroterminated = True
         self.length_param_index = -1
         self.length_param_name = None
         self.size = None
 
-    def __repr__(self):
-        return 'Array(%r, %r)' % (self.name, self.element_type, )
-
 
 class List(Type):
 
-    def __init__(self, name, ctype, element_type):
-        Type.__init__(self, name, ctype)
+    def __init__(self, name, element_type, **kwargs):
+        Type.__init__(self, target_fundamental='<list>',
+                      **kwargs)
+        self.name = name
         self.element_type = element_type
 
-    def __repr__(self):
-        return 'List(%r of %r)' % (self.name, self.element_type, )
-
 
 class Map(Type):
 
-    def __init__(self, name, ctype, key_type, value_type):
-        Type.__init__(self, name, ctype)
+    def __init__(self, ctype, key_type, value_type, **kwargs):
+        Type.__init__(self, ctype=ctype, target_fundamental='<map>')
         self.key_type = key_type
         self.value_type = value_type
 
-    def __repr__(self):
-        return 'Map(%r <%r,%r>)' % (self.name, self.key_type, self.value_type)
-
 
 class Alias(Node):
 
@@ -352,14 +449,12 @@ class Alias(Node):
         self.target = target
         self.ctype = ctype
 
-    def __repr__(self):
-        return 'Alias(%r, %r)' % (self.name, self.target)
 
+class TypeContainer(Annotated):
+    """A fundamental base class for Return and Parameter."""
 
-class TypeContainer(Node):
-
-    def __init__(self, name, typenode, transfer):
-        Node.__init__(self, name)
+    def __init__(self, typenode, transfer):
+        Annotated.__init__(self)
         self.type = typenode
         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
                         PARAM_TRANSFER_FULL]:
@@ -369,25 +464,32 @@ class TypeContainer(Node):
 
 
 class Parameter(TypeContainer):
+    """An argument to a function."""
 
-    def __init__(self, name, typenode, direction=None,
-                 transfer=None, allow_none=False, scope=None):
-        TypeContainer.__init__(self, name, typenode, transfer)
+    def __init__(self, argname, typenode, direction=None,
+                 transfer=None, allow_none=False, scope=None,
+                 caller_allocates=False):
+        TypeContainer.__init__(self, typenode, transfer)
+        self.argname = argname
         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
                          PARAM_DIRECTION_INOUT, None]:
             self.direction = direction
         else:
             self.direction = PARAM_DIRECTION_IN
 
-        self.caller_allocates = False
+        self.caller_allocates = caller_allocates
         self.allow_none = allow_none
         self.scope = scope
         self.closure_index = -1
         self.destroy_index = -1
-        self.doc = None
 
-    def __repr__(self):
-        return 'Parameter(%r, %r)' % (self.name, self.type)
+
+class Return(TypeContainer):
+    """A return value from a function."""
+
+    def __init__(self, rtype, transfer=None):
+        TypeContainer.__init__(self, rtype, transfer)
+        self.direction = PARAM_DIRECTION_OUT
 
 
 class Enum(Node):
@@ -396,10 +498,6 @@ class Enum(Node):
         Node.__init__(self, name)
         self.symbol = symbol
         self.members = members
-        self.doc = None
-
-    def __repr__(self):
-        return 'Enum(%r, %r)' % (self.name, self.members)
 
 
 class Bitfield(Node):
@@ -408,22 +506,15 @@ class Bitfield(Node):
         Node.__init__(self, name)
         self.symbol = symbol
         self.members = members
-        self.doc = None
-
-    def __repr__(self):
-        return 'Bitfield(%r, %r)' % (self.name, self.members)
 
 
-class Member(Node):
+class Member(object):
 
     def __init__(self, name, value, symbol):
-        Node.__init__(self, name)
+        self.name = name
         self.value = value
         self.symbol = symbol
 
-    def __repr__(self):
-        return 'Member(%r, %r)' % (self.name, self.value)
-
 
 class Record(Node):
 
@@ -433,7 +524,6 @@ class Record(Node):
         self.constructors = []
         self.symbol = symbol
         self.disguised = disguised
-        self.doc = None
         self.methods = []
 
     def remove_matching_children(self, pred):
@@ -441,36 +531,18 @@ class Record(Node):
         self.constructors = filter(pred, self.constructors)
         self.methods = filter(pred, self.methods)
 
-# BW compat, remove
-Struct = Record
 
+class Field(Annotated):
 
-class Field(Node):
-
-    def __init__(self, name, typenode, symbol, readable, writable, bits=None):
-        Node.__init__(self, name)
+    def __init__(self, name, typenode, readable, writable, bits=None,
+                 anonymous_node=None):
+        Annotated.__init__(self)
+        self.name = name
         self.type = typenode
-        self.symbol = symbol
         self.readable = readable
         self.writable = writable
         self.bits = bits
-
-    def __repr__(self):
-        if self.bits:
-            return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
-        else:
-            return 'Field(%r, %r)' % (self.name, self.type)
-
-
-class Return(TypeContainer):
-
-    def __init__(self, rtype, transfer=None):
-        TypeContainer.__init__(self, None, rtype, transfer)
-        self.direction = PARAM_DIRECTION_OUT
-        self.doc = None
-
-    def __repr__(self):
-        return 'Return(%r)' % (self.type, )
+        self.anonymous_node = anonymous_node
 
 
 class Class(Node):
@@ -488,7 +560,6 @@ class Class(Node):
         self.constructors = []
         self.properties = []
         self.fields = []
-        self.doc = None
 
     def remove_matching_children(self, pred):
         self.methods = filter(pred, self.methods)
@@ -496,10 +567,6 @@ class Class(Node):
         self.properties = filter(pred, self.properties)
         self.fields = filter(pred, self.fields)
 
-    def __repr__(self):
-        return '%s(%r, %r, %r)' % (
-            self.__class__.__name__,
-            self.name, self.parent, self.methods)
 
 
 class Interface(Node):
@@ -513,70 +580,34 @@ class Interface(Node):
         self.properties = []
         self.fields = []
         self.prerequisites = []
-        self.doc = None
-
-    def __repr__(self):
-        return '%s(%r, %r)' % (
-            self.__class__.__name__,
-            self.name, self.methods)
 
 
 class Constant(Node):
 
-    def __init__(self, name, type_name, value):
+    def __init__(self, name, value_type, value):
         Node.__init__(self, name)
-        self.type = Type(type_name)
+        self.value_type = value_type
         self.value = value
 
-    def __repr__(self):
-        return 'Constant(%r, %r, %r)' % (
-            self.name, self.type, self.value)
 
+class Property(Node):
 
-class Property(TypeContainer):
-
-    def __init__(self, name, type_name, readable, writable,
-                 construct, construct_only, ctype=None, transfer=None):
-        self.type = Type(type_name, ctype)
-        TypeContainer.__init__(self, name, self.type, transfer)
+    def __init__(self, name, typeobj, readable, writable,
+                 construct, construct_only, transfer=None):
+        Node.__init__(self, name)
+        self.type = typeobj
         self.readable = readable
         self.writable = writable
         self.construct = construct
         self.construct_only = construct_only
-        self.doc = None
-
-    def __repr__(self):
-        return '%s(%r, %r)' % (
-            self.__class__.__name__,
-            self.name, self.type)
-
-
-# FIXME: Inherit from Function
+        self.transfer = PARAM_TRANSFER_NONE
 
 
-class Callback(Node):
+class Callback(Callable):
 
-    def __init__(self, name, retval, parameters, ctype=None):
-        Node.__init__(self, name)
-        self.retval = retval
-        self.parameters = parameters
+    def __init__(self, name, retval, parameters, throws, ctype=None):
+        Callable.__init__(self, name, retval, parameters, throws)
         self.ctype = ctype
-        self.throws = False
-        self.doc = None
-
-    def get_parameter_index(self, name):
-        for i, parameter in enumerate(self.parameters):
-            if parameter.name == name:
-                return i
-
-    def get_parameter(self, name):
-        for parameter in self.parameters:
-            if parameter.name == name:
-                return parameter
-
-    def __repr__(self):
-        return 'Callback(%r, %r, %r)' % (
-            self.name, self.retval, self.parameters)
 
 
 class Union(Node):
@@ -587,7 +618,3 @@ class Union(Node):
         self.constructors = []
         self.methods = []
         self.symbol = symbol
-        self.doc = None
-
-    def __repr__(self):
-        return 'Union(%r, %r)' % (self.name, self.fields, )
diff --git a/giscanner/girparser.py b/giscanner/girparser.py
index 17cf630..1d87b0e 100644
--- a/giscanner/girparser.py
+++ b/giscanner/girparser.py
@@ -23,11 +23,11 @@ import os
 from xml.etree.cElementTree import parse
 
 from .ast import (Alias, Array, Callback, Constant, Enum, Function, Field,
-                  Namespace, Parameter, Property, Return, Union, Struct, Type,
-                  Varargs, Include)
+                  Namespace, Parameter, Property, Return, Union, Type, List,
+                  VFunction, Record, Varargs, Include, PARAM_DIRECTION_IN)
 from .glibast import (GLibEnum, GLibEnumMember, GLibFlags,
                       GLibInterface, GLibObject, GLibBoxedStruct,
-                      GLibBoxedUnion, GLibBoxedOther)
+                      GLibBoxedUnion, GLibBoxedOther, GLibRecord)
 
 from .girwriter import COMPATIBLE_GIR_VERSION
 
@@ -51,7 +51,6 @@ def _cns(tag):
 class GIRParser(object):
 
     def __init__(self):
-        self._include_parsing = False
         self._shared_libraries = []
         self._includes = set()
         self._pkgconfig_packages = set()
@@ -72,6 +71,8 @@ class GIRParser(object):
         self._namespace = None
         self._shared_libraries = []
         self._pkgconfig_packages = set()
+        self._c_includes = set()
+        self._c_prefix = None
         self._parse_api(tree.getroot())
 
     def get_namespace(self):
@@ -83,6 +84,12 @@ class GIRParser(object):
     def get_includes(self):
         return self._includes
 
+    def get_c_includes(self):
+        return self._c_includes
+
+    def get_c_prefix(self):
+        return self._c_prefix
+
     def get_pkgconfig_packages(self):
         if not hasattr(self, '_pkgconfig_packages'):
             self._pkgconfig_packages = []
@@ -91,11 +98,21 @@ class GIRParser(object):
     def get_doc(self):
         return parse(self._filename)
 
-    def set_include_parsing(self, include_parsing):
-        self._include_parsing = include_parsing
-
     # Private
 
+    def _find_first_child(self, node, name):
+        for child in node.getchildren():
+            if child.tag == name:
+                return child
+        return None
+
+    def _find_children(self, node, name):
+        result = []
+        for child in node.getchildren():
+            if child.tag == name:
+                result.append(child)
+        return result
+
     def _get_current_file(self):
         if not self._filename_stack:
             return None
@@ -105,9 +122,6 @@ class GIRParser(object):
             return curfile[len(cwd):]
         return curfile
 
-    def _add_node(self, node):
-        self._namespace.nodes.append(node)
-
     def _parse_api(self, root):
         assert root.tag == _corens('repository')
         version = root.attrib['version']
@@ -121,11 +135,14 @@ class GIRParser(object):
                 self._parse_include(node)
             elif node.tag == _corens('package'):
                 self._parse_pkgconfig_package(node)
+            elif node.tag == _cns('include'):
+                self._parse_c_include(node)
 
         ns = root.find(_corens('namespace'))
         assert ns is not None
         self._namespace = Namespace(ns.attrib['name'],
-                                    ns.attrib['version'])
+                                    ns.attrib['version'],
+                                    ns.attrib.get(_cns('prefix')))
         if 'shared-library' in ns.attrib:
             self._shared_libraries.extend(
                 ns.attrib['shared-library'].split(','))
@@ -155,19 +172,40 @@ class GIRParser(object):
         self._includes.add(include)
 
     def _parse_pkgconfig_package(self, node):
-        if not hasattr(self, '_pkgconfig_packages'):
-            self._pkgconfig_packages = []
         self._pkgconfig_packages.add(node.attrib['name'])
 
+    def _parse_c_include(self, node):
+        self._c_includes.add(node.attrib['name'])
+
     def _parse_alias(self, node):
         alias = Alias(node.attrib['name'],
                       node.attrib['target'],
                       node.attrib.get(_cns('type')))
-        self._add_node(alias)
+        self._namespace.append(alias)
+
+    def _parse_generic_attribs(self, node, obj):
+        doc = node.attrib.get('doc')
+        if doc:
+            obj.doc = doc
+        version = node.attrib.get('version')
+        if version:
+            obj.version = version
+        deprecated = node.attrib.get('deprecated')
+        if deprecated:
+            obj.deprecated = deprecated
+        introspectable = node.attrib.get('introspectable')
+        if introspectable:
+            obj.introspectable = int(introspectable) > 0
 
     def _parse_object_interface(self, node):
+        parent = node.attrib.get('parent')
+        if parent:
+            parent_type = Type(target_giname=parent)
+        else:
+            parent_type = None
+        
         ctor_args = [node.attrib['name'],
-                     node.attrib.get('parent'),
+                     parent_type,
                      node.attrib[_glibns('type-name')],
                      node.attrib[_glibns('get-type')]]
         if node.tag == _corens('interface'):
@@ -181,38 +219,49 @@ class GIRParser(object):
             raise AssertionError(node)
 
         obj = klass(*ctor_args)
-        self._add_node(obj)
+        self._parse_generic_attribs(node, obj)
+        type_struct = node.attrib.get(_glibns('type-struct'))
+        if type_struct:
+            obj.glib_type_struct = Type(target_giname=type_struct)
+        self._namespace.append(obj)
 
-        if self._include_parsing:
-            return
         ctor_args.append(node.attrib.get(_cns('type')))
-        for iface in node.findall(_corens('implements')):
-            obj.interfaces.append(iface.attrib['name'])
-        for iface in node.findall(_corens('prerequisites')):
-            obj.prerequisities.append(iface.attrib['name'])
-        for method in node.findall(_corens('method')):
+        for iface in self._find_children(node, _corens('implements')):
+            obj.interfaces.append(Type(target_giname=iface.attrib['name']))
+        for iface in self._find_children(node, _corens('prerequisites')):
+            obj.prerequisities.append(Type(target_giname=iface.attrib['name']))
+        for func_node in self._find_children(node, _corens('function')):
+            func = self._parse_function_common(func_node, Function)
+            obj.static_methods.append(func)
+        for method in self._find_children(node, _corens('method')):
             func = self._parse_function_common(method, Function)
             func.is_method = True
             obj.methods.append(func)
-        for ctor in node.findall(_corens('constructor')):
+        for method in self._find_children(node, _corens('virtual-method')):
+            func = self._parse_function_common(method, VFunction)
+            self._parse_generic_attribs(method, func)
+            func.is_method = True
+            func.invoker = method.get('invoker')
+            obj.virtual_methods.append(func)
+        for ctor in self._find_children(node, _corens('constructor')):
             obj.constructors.append(
                 self._parse_function_common(ctor, Function))
-        for callback in node.findall(_corens('callback')):
+        for callback in self._find_children(node, _corens('callback')):
             obj.fields.append(self._parse_function_common(callback, Callback))
-        for field in node.findall(_corens('field')):
+        for field in self._find_children(node, _corens('field')):
             obj.fields.append(self._parse_field(field))
-        for prop in node.findall(_corens('property')):
+        for prop in self._find_children(node, _corens('property')):
             obj.properties.append(self._parse_property(prop))
-        for signal in node.findall(_glibns('signal')):
+        for signal in self._find_children(node, _glibns('signal')):
             obj.signals.append(self._parse_function_common(signal, Function))
 
     def _parse_callback(self, node):
         callback = self._parse_function_common(node, Callback)
-        self._add_node(callback)
+        self._namespace.append(callback)
 
     def _parse_function(self, node):
         function = self._parse_function_common(node, Function)
-        self._add_node(function)
+        self._namespace.append(function)
 
     def _parse_function_common(self, node, klass):
         name = node.attrib['name']
@@ -221,29 +270,43 @@ class GIRParser(object):
             raise ValueError('node %r has no return-value' % (name, ))
         transfer = returnnode.attrib.get('transfer-ownership')
         retval = Return(self._parse_type(returnnode), transfer)
+        self._parse_generic_attribs(returnnode, retval)
         parameters = []
 
+        throws = (node.attrib.get('throws') == '1')
+
         if klass is Callback:
-            func = klass(name, retval, parameters,
+            func = klass(name, retval, parameters, throws,
                          node.attrib.get(_cns('type')))
-        else:
+        elif klass is Function:
             identifier = node.attrib.get(_cns('identifier'))
-            throws = (node.attrib.get('throws') == '1')
-            func = klass(name, retval, parameters, identifier, throws)
-
-        if self._include_parsing:
-            return func
+            func = klass (name, retval, parameters, throws, identifier)
+        elif klass is VFunction:
+            func = klass(name, retval, parameters, throws)
+        else:
+            assert False
 
         parameters_node = node.find(_corens('parameters'))
         if (parameters_node is not None):
-            for paramnode in parameters_node.findall(_corens('parameter')):
+            for paramnode in self._find_children(parameters_node, _corens('parameter')):
                 param = Parameter(paramnode.attrib.get('name'),
                                   self._parse_type(paramnode),
-                                  paramnode.attrib.get('direction'),
+                                  paramnode.attrib.get('direction') or PARAM_DIRECTION_IN,
                                   paramnode.attrib.get('transfer-ownership'),
-                                  paramnode.attrib.get('allow-none') == '1')
+                                  paramnode.attrib.get('allow-none') == '1',
+                                  paramnode.attrib.get('scope'),
+                                  paramnode.attrib.get('caller-allocates') == '1')
+                closure = paramnode.attrib.get('closure')
+                if closure:
+                    param.closure_index = int(closure)
+                destroy = paramnode.attrib.get('destroy')
+                if destroy:
+                    param.destroy_index = int(destroy)
+                self._parse_generic_attribs(paramnode, param)
                 parameters.append(param)
 
+        self._parse_generic_attribs(node, func)
+
         return func
 
     def _parse_record(self, node):
@@ -252,24 +315,26 @@ class GIRParser(object):
                                      node.attrib[_glibns('type-name')],
                                      node.attrib[_glibns('get-type')],
                                      node.attrib.get(_cns('type')))
+        elif _glibns('is-gtype-struct-for') in node.attrib:
+            struct = GLibRecord(node.attrib['name'],
+                                node.attrib.get(_cns('type')),
+                                disguised=node.attrib.get('disguised') == '1')
+            is_gtype_struct_for = node.attrib[_glibns('is-gtype-struct-for')]
+            struct.is_gtype_struct_for = Type(target_giname=is_gtype_struct_for)
         else:
-            disguised = node.attrib.get('disguised') == '1'
-            struct = Struct(node.attrib['name'],
+            struct = Record(node.attrib['name'],
                             node.attrib.get(_cns('type')),
-                            disguised=disguised)
-        self._add_node(struct)
-
-        if self._include_parsing:
-            return
-        for field in node.findall(_corens('field')):
-            struct.fields.append(self._parse_field(field))
-        for callback in node.findall(_corens('callback')):
-            struct.fields.append(
-                self._parse_function_common(callback, Callback))
-        for method in node.findall(_corens('method')):
-            struct.fields.append(
+                            disguised=node.attrib.get('disguised') == '1')
+        self._parse_generic_attribs(node, struct)
+        self._namespace.append(struct)
+
+        for field in self._find_children(node, _corens('field')):
+            fieldobj = self._parse_field(field) 
+            struct.fields.append(fieldobj)
+        for method in self._find_children(node, _corens('method')):
+            struct.methods.append(
                 self._parse_function_common(method, Function))
-        for ctor in node.findall(_corens('constructor')):
+        for ctor in self._find_children(node, _corens('constructor')):
             struct.constructors.append(
                 self._parse_function_common(ctor, Function))
 
@@ -282,50 +347,71 @@ class GIRParser(object):
         else:
             union = Union(node.attrib['name'],
                           node.attrib.get(_cns('type')))
-        self._add_node(union)
+        self._namespace.append(union)
 
-        if self._include_parsing:
-            return
-        for callback in node.findall(_corens('callback')):
+        for callback in self._find_children(node, _corens('callback')):
             union.fields.append(
                 self._parse_function_common(callback, Callback))
-        for field in node.findall(_corens('field')):
+        for field in self._find_children(node, _corens('field')):
             union.fields.append(self._parse_field(field))
-        for method in node.findall(_corens('method')):
+        for method in self._find_children(node, _corens('method')):
             union.fields.append(
                 self._parse_function_common(method, Function))
-        for ctor in node.findall(_corens('constructor')):
+        for ctor in self._find_children(node, _corens('constructor')):
             union.constructors.append(
                 self._parse_function_common(ctor, Function))
 
     def _parse_type(self, node):
-        typenode = node.find(_corens('type'))
+        # Fields can contain inline callbacks
+        typenode = node.find(_corens('callback'))
         if typenode is not None:
-            return Type(typenode.attrib['name'],
-                        typenode.attrib.get(_cns('type')))
+            return Type(target_giname=typenode.attrib['name'],
+                        ctype=typenode.attrib.get(_cns('type')))
 
+        # Arrays have their own toplevel XML
         typenode = node.find(_corens('array'))
         if typenode is not None:
-
-            array_type = typenode.attrib.get(_cns('type'))
-            if array_type.startswith('GArray*') or \
-               array_type.startswith('GPtrArray*') or \
-               array_type.startswith('GByteArray*'):
-                element_type = None
+            array_name = typenode.attrib.get('name')
+            if array_name in ('GLib.PtrArray', 'GLib.Array',
+                              'GLib.ByteArray'):
+                element_type = Type(target_fundamental='any', ctype='gpointer')
             else:
                 element_type = self._parse_type(typenode)
-
-            ret = Array(None, array_type, element_type)
+            array_ctype = typenode.attrib.get(_cns('type'))
+            ret = Array(array_name, element_type, ctype=array_ctype)
+            # zero-terminated defaults to true...
+            zero = typenode.attrib.get('zero-terminated')
+            if zero and zero == '0':
+                ret.zeroterminated = False
+            fixed_size = typenode.attrib.get('fixed-size') 
+            if fixed_size:
+                ret.size = int(fixed_size)
 
             lenidx = typenode.attrib.get('length')
             if lenidx:
                 ret.length_param_index = int(lenidx)
             return ret
 
+        # Dispsense with varargs
         typenode = node.find(_corens('varargs'))
         if typenode is not None:
             return Varargs()
 
+        # Okay now...could be a list, let's see.
+        typenode = self._find_first_child(node, _corens('type'))
+        if typenode is not None:
+            name = typenode.attrib['name']
+            ctype = typenode.attrib.get(_cns('type'))
+            if name in ['GLib.List', 'GLib.SList']:
+                subchild = self._find_first_child(typenode, _corens('type'))
+                if subchild is not None:
+                    element_type = self._parse_type(typenode)
+                else:
+                    element_type = Type(target_fundamental='any')
+                return List(name, element_type, ctype=ctype)
+            else:
+                return self._namespace.type_from_name(name, ctype)
+
         raise ValueError("Couldn't parse type of node %r; children=%r",
                          node, list(node))
 
@@ -333,51 +419,62 @@ class GIRParser(object):
         obj = GLibBoxedOther(node.attrib[_glibns('name')],
                              node.attrib[_glibns('type-name')],
                              node.attrib[_glibns('get-type')])
-        self._add_node(obj)
-        if self._include_parsing:
-            return
-        for method in node.findall(_corens('method')):
+        self._parse_generic_attribs(node, obj)
+        self._namespace.append(obj)
+        for method in self._find_children(node, _corens('method')):
             func = self._parse_function_common(method, Function)
             func.is_method = True
             obj.methods.append(func)
-        for ctor in node.findall(_corens('constructor')):
+        for ctor in self._find_children(node, _corens('constructor')):
             obj.constructors.append(
                 self._parse_function_common(ctor, Function))
-        for callback in node.findall(_corens('callback')):
+        for callback in self._find_children(node, _corens('callback')):
             obj.fields.append(
                 self._parse_function_common(callback, Callback))
 
     def _parse_field(self, node):
-        type_node = self._parse_type(node)
-        return Field(node.attrib['name'],
-                     type_node,
-                     type_node.ctype,
-                     node.attrib.get('readable') != '0',
-                     node.attrib.get('writable') == '1',
-                     node.attrib.get('bits'))
+        callback_node = self._find_first_child(node, _corens('callback'))
+        if callback_node:
+            anonymous_node = self._parse_function_common(callback_node, Callback)
+            type_node = None
+        else:
+            anonymous_node = None
+            type_node = self._parse_type(node)
+        field = Field(node.attrib['name'],
+                      type_node,
+                      node.attrib.get('readable') != '0',
+                      node.attrib.get('writable') == '1',
+                      node.attrib.get('bits'),
+                      anonymous_node=anonymous_node)
+        self._parse_generic_attribs(node, field)
+        return field
 
     def _parse_property(self, node):
-        type_node = self._parse_type(node)
-        return Property(node.attrib['name'],
-                        type_node.name,
+        prop = Property(node.attrib['name'],
+                        self._parse_type(node),
                         node.attrib.get('readable') != '0',
                         node.attrib.get('writable') == '1',
                         node.attrib.get('construct') == '1',
-                        node.attrib.get('construct-only') == '1',
-                        type_node.ctype)
+                        node.attrib.get('construct-only') == '1')
+        self._parse_generic_attribs(node, prop)
+        return prop
 
     def _parse_member(self, node):
-        return GLibEnumMember(node.attrib['name'],
-                              node.attrib['value'],
-                              node.attrib.get(_cns('identifier')),
-                              node.attrib.get(_glibns('nick')))
+        member = GLibEnumMember(node.attrib['name'],
+                                node.attrib['value'],
+                                node.attrib.get(_cns('identifier')),
+                                node.attrib.get(_glibns('nick')))
+        self._parse_generic_attribs(node, member)
+        return member
+        
 
     def _parse_constant(self, node):
         type_node = self._parse_type(node)
         constant = Constant(node.attrib['name'],
-                            type_node.name,
+                            type_node,
                             node.attrib['value'])
-        self._add_node(constant)
+        self._parse_generic_attribs(node, constant)
+        self._namespace.append(constant)
 
     def _parse_enumeration_bitfield(self, node):
         name = node.attrib.get('name')
@@ -398,9 +495,8 @@ class GIRParser(object):
         else:
             obj = klass(name, type_name, members, get_type)
             obj.ctype = ctype
-        self._add_node(obj)
+        self._parse_generic_attribs(node, obj)
+        self._namespace.append(obj)
 
-        if self._include_parsing:
-            return
-        for member in node.findall(_corens('member')):
+        for member in self._find_children(node, _corens('member')):
             members.append(self._parse_member(member))
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 59b4b49..ed836eb 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -22,8 +22,8 @@
 from __future__ import with_statement
 
 from .ast import (Alias, Array, Bitfield, Callback, Class, Constant, Enum,
-                  Function, Interface, List, Map, Member, Struct, Union,
-                  Varargs)
+                  Function, Interface, List, Map, Member, Union, Record,
+                  Varargs, Type)
 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
                       GLibFlags, GLibObject, GLibInterface,
                       GLibRecord)
@@ -42,10 +42,10 @@ class GIRWriter(XMLWriter):
 To affect the contents of this file, edit the original C definitions,
 and/or use gtk-doc annotations. ''')
         self._write_repository(namespace, shlibs, includes, pkgs,
-                               c_includes, cprefix)
+                               c_includes)
 
     def _write_repository(self, namespace, shlibs, includes=None,
-                          packages=None, c_includes=None, cprefix=None):
+                          packages=None, c_includes=None):
         if includes is None:
             includes = frozenset()
         if packages is None:
@@ -65,7 +65,9 @@ and/or use gtk-doc annotations. ''')
                 self._write_pkgconfig_pkg(pkg)
             for c_include in sorted(set(c_includes)):
                 self._write_c_include(c_include)
-            self._write_namespace(namespace, shlibs, cprefix)
+            self._namespace = namespace
+            self._write_namespace(namespace, shlibs)
+            self._namespace = None
 
     def _write_include(self, include):
         attrs = [('name', include.name), ('version', include.version)]
@@ -79,11 +81,11 @@ and/or use gtk-doc annotations. ''')
         attrs = [('name', c_include)]
         self.write_tag('c:include', attrs)
 
-    def _write_namespace(self, namespace, shlibs, cprefix):
+    def _write_namespace(self, namespace, shlibs):
         attrs = [('name', namespace.name),
                  ('version', namespace.version),
                  ('shared-library', ','.join(shlibs)),
-                 ('c:prefix', cprefix)]
+                 ('c:prefix', namespace.c_prefix)]
         with self.tagcontext('namespace', attrs):
             # We define a custom sorting function here because
             # we want aliases to be first.  They're a bit
@@ -98,7 +100,7 @@ and/or use gtk-doc annotations. ''')
                     return 1
                 else:
                     return cmp(a, b)
-            for node in sorted(namespace.nodes, cmp=nscmp):
+            for node in sorted(namespace.itervalues(), cmp=nscmp):
                 self._write_node(node)
 
     def _write_node(self, node):
@@ -112,7 +114,7 @@ and/or use gtk-doc annotations. ''')
             self._write_class(node)
         elif isinstance(node, Callback):
             self._write_callback(node)
-        elif isinstance(node, Struct):
+        elif isinstance(node, Record):
             self._write_record(node)
         elif isinstance(node, Union):
             self._write_union(node)
@@ -169,7 +171,9 @@ and/or use gtk-doc annotations. ''')
             self._write_parameters(callable.parameters)
 
     def _write_function(self, func, tag_name='function'):
-        attrs = [('c:identifier', func.symbol)]
+        attrs = []
+        if hasattr(func, 'symbol'):
+            attrs.append(('c:identifier', func.symbol))
         self._write_callable(func, tag_name, attrs)
 
     def _write_method(self, method):
@@ -206,8 +210,8 @@ and/or use gtk-doc annotations. ''')
         assert parameter.transfer is not None, parameter
 
         attrs = []
-        if parameter.name is not None:
-            attrs.append(('name', parameter.name))
+        if parameter.argname is not None:
+            attrs.append(('name', parameter.argname))
         if parameter.direction != 'in':
             attrs.append(('direction', parameter.direction))
             attrs.append(('caller-allocates',
@@ -228,55 +232,54 @@ and/or use gtk-doc annotations. ''')
             self._write_attributes(parameter)
             self._write_type(parameter.type)
 
-    def _type_to_string(self, ntype):
-        if isinstance(ntype, basestring):
-            return ntype
-        return ntype.name
-
     def _write_type(self, ntype, relation=None):
-        if isinstance(ntype, basestring):
-            typename = ntype
-            type_cname = None
-        else:
-            typename = ntype.name
-            type_cname = ntype.ctype
+        assert isinstance(ntype, Type)
+        attrs = []
+        if ntype.ctype:
+            attrs.append(('c:type', ntype.ctype))
         if isinstance(ntype, Varargs):
             with self.tagcontext('varargs', []):
                 pass
-            return
-        if isinstance(ntype, Array):
-            attrs = []
+        elif isinstance(ntype, Array):
             if not ntype.zeroterminated:
                 attrs.append(('zero-terminated', '0'))
             if ntype.length_param_index >= 0:
                 attrs.append(('length', '%d' % (ntype.length_param_index, )))
-            if ntype.name in ['GLib.Array', 'GLib.PtrArray', 'GLib.ByteArray']:
-                attrs.append(('name', ntype.name))
-            attrs.append(('c:type', ntype.ctype))
             if ntype.size is not None:
-                attrs.append(('fixed-size', ntype.size))
+                attrs.append(('fixed-size', '%d' % (ntype.size, )))
 
             with self.tagcontext('array', attrs):
                 if ntype.element_type is not None:
                     self._write_type(ntype.element_type)
-            return
-        attrs = [('name', self._type_to_string(ntype))]
-        # FIXME: figure out if type references a basic type
-        #        or a boxed/class/interface etc. and skip
-        #        writing the ctype if the latter.
-        if type_cname is not None:
-            attrs.append(('c:type', type_cname))
-        if isinstance(ntype, List) and ntype.element_type:
+        elif isinstance(ntype, List):
+            if ntype.name:
+                attrs.insert(0, ('name', ntype.name))
             with self.tagcontext('type', attrs):
                 self._write_type(ntype.element_type)
-            return
-        if isinstance(ntype, Map) and ntype.key_type:
+        elif isinstance(ntype, Map):
+            if ntype.name:
+                attrs.insert(0, ('name', name))
             with self.tagcontext('type', attrs):
                 self._write_type(ntype.key_type)
                 self._write_type(ntype.value_type)
-            return
-        # Not a special type, just write it out
-        self.write_tag('type', attrs)
+        else:
+            # REWRITEFIXME - enable this for 1.2
+            if ntype.target_giname:
+                # attrs.insert(0, ('ref', ntype.target_giname))
+                prefix = self._namespace.name + '.'
+                if ntype.target_giname.startswith(prefix):
+                    attrs.insert(0, ('name', ntype.target_giname[len(prefix):]))
+                else:
+                    attrs.insert(0, ('name', ntype.target_giname))
+            elif ntype.target_fundamental:
+                # attrs = [('fundamental', ntype.target_fundamental)]
+                attrs.insert(0, ('name', ntype.target_fundamental))
+            elif ntype.target_foreign:
+                attrs.insert(0, ('foreign', '1'))
+            else:
+                raise AssertionError("Caught unresolved type %r" % (ntype, ))
+            # Not a special type, just write it out
+            self.write_tag('type', attrs)
 
     def _write_enum(self, enum):
         attrs = [('name', enum.name)]
@@ -324,10 +327,9 @@ and/or use gtk-doc annotations. ''')
         self.write_tag('member', attrs)
 
     def _write_constant(self, constant):
-        attrs = [('name', constant.name),
-                 ('value', str(constant.value))]
+        attrs = [('name', constant.name), ('value', constant.value)]
         with self.tagcontext('constant', attrs):
-            self._write_type(constant.type)
+            self._write_type(constant.value_type)
 
     def _write_class(self, node):
         attrs = [('name', node.name),
@@ -339,7 +341,7 @@ and/or use gtk-doc annotations. ''')
         if isinstance(node, Class):
             tag_name = 'class'
             if node.parent is not None:
-                attrs.append(('parent', node.parent))
+                attrs.append(('parent', node.parent.target_giname))
             if node.is_abstract:
                 attrs.append(('abstract', '1'))
         else:
@@ -349,15 +351,15 @@ and/or use gtk-doc annotations. ''')
             if node.get_type:
                 attrs.append(('glib:get-type', node.get_type))
             if node.glib_type_struct:
-                attrs.append(('glib:type-struct', node.glib_type_struct.name))
+                attrs.append(('glib:type-struct', node.glib_type_struct.target_giname))
         with self.tagcontext(tag_name, attrs):
             self._write_attributes(node)
             if isinstance(node, GLibObject):
                 for iface in node.interfaces:
-                    self.write_tag('implements', [('name', iface)])
+                    self.write_tag('implements', [('name', iface.target_giname)])
             if isinstance(node, Interface):
                 for iface in node.prerequisites:
-                    self.write_tag('prerequisite', [('name', iface)])
+                    self.write_tag('prerequisite', [('name', iface.target_giname)])
             if isinstance(node, Class):
                 for method in node.constructors:
                     self._write_constructor(method)
@@ -410,7 +412,7 @@ and/or use gtk-doc annotations. ''')
     def _write_vfunc(self, vf):
         attrs = []
         if vf.invoker:
-            attrs.append(('invoker', vf.invoker.name))
+            attrs.append(('invoker', vf.invoker))
         self._write_callable(vf, 'virtual-method', attrs)
 
     def _write_callback(self, callback):
@@ -436,7 +438,7 @@ and/or use gtk-doc annotations. ''')
             if record.is_gtype_struct_for:
                 is_gtype_struct = True
                 attrs.append(('glib:is-gtype-struct-for',
-                              record.is_gtype_struct_for))
+                              record.is_gtype_struct_for.target_giname))
         if record.doc:
             attrs.append(('doc', record.doc))
         self._append_version(record, attrs)
@@ -476,20 +478,16 @@ and/or use gtk-doc annotations. ''')
                 self._write_method(method)
 
     def _write_field(self, field, is_gtype_struct=False):
-        if isinstance(field, Function):
-            self._write_method(field)
-            return
-
-        if isinstance(field, Callback):
+        if field.anonymous_node:
             attrs = [('name', field.name)]
             with self.tagcontext('field', attrs):
                 self._write_attributes(field)
-                if is_gtype_struct:
-                    self._write_callback(field)
+                if isinstance(field.anonymous_node, Callback):
+                    self._write_callback(field.anonymous_node)
                 else:
-                    attrs = [('name', 'any'), ('c:type', 'pointer')]
-                    self.write_tag('type', attrs)
-        elif isinstance(field, Struct):
+                    raise AssertionError("Unknown field anonymous: %r" \
+                                             % (field.anonymous_node, ))
+        elif isinstance(field, Record):
             self._write_record(field)
         elif isinstance(field, Union):
             self._write_union(field)
@@ -504,7 +502,6 @@ and/or use gtk-doc annotations. ''')
             if field.bits:
                 attrs.append(('bits', str(field.bits)))
             with self.tagcontext('field', attrs):
-                self._write_attributes(field)
                 self._write_type(field.type)
 
     def _write_signal(self, signal):
diff --git a/giscanner/glibast.py b/giscanner/glibast.py
index fb1ef20..e2457d6 100644
--- a/giscanner/glibast.py
+++ b/giscanner/glibast.py
@@ -19,7 +19,7 @@
 #
 
 from .ast import (Bitfield, Class, Enum, Interface, Member, Node,
-                  Property, Struct, Union, Record)
+                  Property, Union, Record)
 from .ast import (
     type_names, default_array_types,
     TYPE_STRING, TYPE_INT8, TYPE_UINT8, TYPE_SHORT, TYPE_USHORT,
@@ -68,7 +68,7 @@ class GLibRecord(Record):
 
     @classmethod
     def from_record(cls, record):
-        obj = cls(record.name, record.symbol)
+        obj = cls(record.namespace, record.name, record.symbol)
         obj.fields = record.fields
         obj.constructors = record.constructors
         obj.disguised = record.disguised
@@ -122,6 +122,8 @@ class GLibObject(Class):
         self.get_type = get_type
         self.signals = []
         self.ctype = ctype or type_name
+        # Unresolved state
+        self.parent_gtype_names = []
 
 
 class GLibBoxed:
@@ -131,10 +133,10 @@ class GLibBoxed:
         self.get_type = get_type
 
 
-class GLibBoxedStruct(Struct, GLibBoxed):
+class GLibBoxedStruct(Record, GLibBoxed):
 
     def __init__(self, name, type_name, get_type, ctype=None):
-        Struct.__init__(self, name, ctype or type_name)
+        Record.__init__(self, name, ctype or type_name)
         GLibBoxed.__init__(self, type_name, get_type)
 
 
@@ -170,10 +172,10 @@ class GLibProperty(Property):
     pass
 
 
-class GLibSignal(Node):
+class GLibSignal(object):
 
     def __init__(self, name, retval):
-        Node.__init__(self, name)
+        self.name = name
         self.retval = retval
         self.parameters = []
         self.doc = None
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 3b088bc..d42480f 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -31,7 +31,6 @@ from .ast import (Alias, Bitfield, Callable, Callback, Class, Constant, Enum,
                   Field, VFunction, type_name_from_ctype, default_array_types,
                   TYPE_UINT8, PARAM_TRANSFER_FULL, Array, List,
                   Map, Varargs)
-from .transformer import Names
 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
                       GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
                       GLibBoxedUnion, GLibBoxedOther, GLibRecord,
@@ -50,18 +49,6 @@ G_PARAM_STATIC_NAME = 1 << 5
 G_PARAM_STATIC_NICK = 1 << 6
 G_PARAM_STATIC_BLURB = 1 << 7
 
-SYMBOL_BLACKLIST = [
-    # These ones break GError conventions
-    'g_simple_async_result_new_from_error',
-    'g_simple_async_result_set_from_error',
-    'g_simple_async_result_propagate_error',
-    'g_simple_async_result_report_error_in_idle',
-    'gtk_print_operation_get_error',
-]
-
-SYMBOL_BLACKLIST_RE = [re.compile(x) for x in \
-                           [r'\w+_marshal_[A-Z]+__', ]]
-
 GET_TYPE_OVERRIDES = {
     # this is a special case, from glibtransforer.py:create_gobject
     'intern': 'g_object_get_type',
@@ -97,11 +84,9 @@ class UnknownTypeError(Exception):
 
 class GLibTransformer(object):
 
-    def __init__(self, transformer, noclosure=False):
+    def __init__(self, transformer):
         self._transformer = transformer
-        self._noclosure = noclosure
-        self._namespace_name = None
-        self._names = Names()
+        self._namespace = transformer.namespace
         self._uscore_type_names = {}
         self._binary = None
         self._get_type_functions = []
@@ -110,7 +95,6 @@ class GLibTransformer(object):
         self._failed_types = {}
         self._boxed_types = {}
         self._private_internal_types = {}
-        self._validating = False
 
     # Public API
 
@@ -121,18 +105,22 @@ class GLibTransformer(object):
 
         """
 
-        namespace = self._transformer.parse()
-        self._namespace_name = namespace.name
-        self._namespace_version = namespace.version
+        self._transformer.parse()
 
         # First pass: parsing
-        for node in namespace.nodes:
-            self._parse_node(node)
+        for node in self._namespace.itervalues():
+            if isinstance(node, Function):
+                print "doing initparse of %r" % (node, )
+                self._initparse_function(node)
+        if self._namespace.name == 'GObject':
+            for node in self._namespace.itervalues():
+                if isinstance(node, Record):
+                    self._initparse_gobject_record(node)
 
         # We don't want an alias for this - it's handled specially in
         # the typelib compiler.
-        if namespace.name == 'GObject':
-            del self._names.aliases['Type']
+        if self._namespace.name == 'GObject':
+            del self._namespace.aliases['Type']
 
     def get_get_type_functions(self):
         return self._get_type_functions
@@ -144,74 +132,41 @@ class GLibTransformer(object):
         """Do remaining parsing steps requiring introspection binary"""
 
         # Get all the GObject data by passing our list of get_type
-        # functions to the compiled binary
-
-        self._execute_binary()
-
-        # Introspection is done from within parsing
+        # functions to the compiled binary, returning an XML blob.
+        tree = self._execute_binary_get_tree()
+        root = tree.getroot()
+        for child in root:
+            self._gtype_data[child.attrib['name']] = child
+        for child in root:
+            self._introspect_type(child)
 
-        # Second pass: pair boxed structures
+        # Pair boxed structures; doesn't depend on anything else.
         for boxed in self._boxed_types.itervalues():
             self._pair_boxed_type(boxed)
-        # Third pass: delete class structures, resolve
-        # all types we now know about
-        nodes = list(self._names.names.itervalues())
-        for (ns, node) in nodes:
-            try:
-                self._resolve_node(node)
-            except KeyError, e:
-                self._transformer.log_node_warning(node,
-"""Unresolvable entry %r""" % (e, ))
-                self._remove_attribute(node.name)
-        # Another pass, since we need to have the methods parsed
-        # in order to correctly modify them after class/record
-        # pairing
-        for (ns, node) in nodes:
-            # associate GtkButtonClass with GtkButton
+
+        # In this first pass, we're just looking at functions and
+        # objects; try to match those up.
+        for node in self._namespace:
+            if isinstance(node, Function):
+                self._resolve_function_toplevel(node)
+            elif isinstance(node, GLibObject):
+                self._resolve_glib_object(node)
+            elif isinstance(node, GLibInterface):
+                self._resolve_glib_interface(node)
+
+        # Second pass; a variety of things happen here
+        for node in self._namespace:
             if isinstance(node, Record):
-                self._pair_class_record(node)
-        for (ns, alias) in self._names.aliases.itervalues():
-            self._resolve_alias(alias)
+                self._pass2_pair_class_record(node)
+            elif isinstance(node, Callable):
+                self._pass2_callable(node)
 
         self._resolve_quarks()
 
-        # Our final pass replacing types
-        self._resolve_types(nodes)
-
-        # Create a new namespace with what we found
-        namespace = Namespace(self._namespace_name, self._namespace_version)
-        namespace.nodes = map(lambda x: x[1], self._names.aliases.itervalues())
-        for (ns, x) in self._names.names.itervalues():
-            namespace.nodes.append(x)
-        return namespace
+        return self._namespace
 
     # Private
 
-    def _add_attribute(self, node, replace=False):
-        node_name = node.name
-        if (not replace) and node_name in self._names.names:
-            return
-        self._names.names[node_name] = (None, node)
-
-    def _remove_attribute(self, name):
-        del self._names.names[name]
-
-    def _get_attribute(self, name):
-        node = self._names.names.get(name)
-        if node:
-            return node[1]
-        return None
-
-    def _lookup_node(self, name):
-        if name in type_names:
-            return None
-        node = self._get_attribute(name)
-        if node is None:
-            node = self._transformer.get_names().names.get(name)
-            if node:
-                return node[1]
-        return node
-
     def _get_no_uscore_prefixed_name(self, type_name):
         # Besides the straight underscore conversion, we also try
         # removing the underscores from the namespace as a possible C
@@ -240,7 +195,9 @@ class GLibTransformer(object):
         # but only covers enums that are registered as GObject enums.
         # Create a fallback mapping based on all known enums in this module.
         uscore_enums = {}
-        for enum in self._transformer.iter_enums():
+        for enum in self._namespace.itervalues():
+            if not isinstance(enum, Enum):
+                continue
             type_name = enum.symbol
             uscored = to_underscores(type_name).lower()
 
@@ -285,7 +242,11 @@ class GLibTransformer(object):
                 continue
         return Unresolved(gtype_names[0])
 
-    def _execute_binary(self):
+    def _execute_binary_get_tree(self):
+        """Load the library (or executable), returning an XML
+blob containing data gleaned from GObject's primitive introspection."""
+        from xml.etree.cElementTree import parse
+
         in_path = os.path.join(self._binary.tmpdir, 'types.txt')
         f = open(in_path, 'w')
         # TODO: Introspect GQuark functions
@@ -301,22 +262,14 @@ class GLibTransformer(object):
 
         # Invoke the binary, having written our get_type functions to types.txt
         try:
-            subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
-        except subprocess.CalledProcessError, e:
-            raise SystemExit(e)
-        self._read_introspect_dump(out_path)
-
-        # Clean up temporaries
-        shutil.rmtree(self._binary.tmpdir)
-
-    def _read_introspect_dump(self, xmlpath):
-        from xml.etree.cElementTree import parse
-        tree = parse(xmlpath)
-        root = tree.getroot()
-        for child in root:
-            self._gtype_data[child.attrib['name']] = child
-        for child in root:
-            self._introspect_type(child)
+            try:
+                subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
+            except subprocess.CalledProcessError, e:
+                # Clean up temporaries
+                raise SystemExit(e)
+            return parse(out_path)
+        finally:
+            shutil.rmtree(self._binary.tmpdir)
 
     def _create_gobject(self, node):
         type_name = 'G' + node.name
@@ -324,8 +277,7 @@ class GLibTransformer(object):
             parent_gitype = None
             symbol = 'intern'
         elif type_name == 'GInitiallyUnowned':
-            parent_type_name = 'GObject'
-            parent_gitype = self._resolve_gtypename(parent_type_name)
+            parent_gitype = 'GLib.Object'
             symbol = 'g_initially_unowned_get_type'
         else:
             assert False
@@ -341,69 +293,25 @@ class GLibTransformer(object):
             # GInitiallyUnowned so that struct offset computation
             # works correctly.
             gnode.fields = self._names.names['Object'][1].fields
-        self._add_attribute(gnode)
+        self._namespace.append(gnode, replace=True)
         self._register_internal_type(type_name, gnode)
 
     # Parser
 
-    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, Record):
-            self._parse_record(node)
-        elif isinstance(node, Callback):
-            self._parse_callback(node)
-        elif isinstance(node, Alias):
-            self._parse_alias(node)
-        elif isinstance(node, Member):
-            # FIXME: atk_misc_instance singletons
-            pass
-        elif isinstance(node, Union):
-            self._parse_union(node)
-        elif isinstance(node, Constant):
-            self._parse_constant(node)
-        else:
-            print 'GLIB Transformer: Unhandled node:', node
-
-    def _parse_alias(self, alias):
-        self._names.aliases[alias.name] = (None, alias)
-
-    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)
-
-    def _parse_function(self, func):
-        if func.symbol in SYMBOL_BLACKLIST:
-            return
-        if func.symbol.startswith('_'):
-            return
-        for regexp in SYMBOL_BLACKLIST_RE:
-            if regexp.match(func.symbol):
-                return
-        if self._parse_get_type_function(func):
-            return
-        if self._parse_error_quark_function(func):
+    def _initparse_function(self, func):
+        symbol = func.symbol
+        if symbol.startswith('_'):
             return
+        elif symbol.endswith('_get_type'):
+            self._initparse_get_type_function(func)
+        elif symbol.endswith('_error_quark'):
+            self._initparse_error_quark_function(func)
 
-        self._add_attribute(func)
-
-    def _parse_get_type_function(self, func):
-        symbol = func.symbol
-        if not symbol.endswith('_get_type'):
-            return False
-        if self._namespace_name == 'GLib':
+    def _initparse_get_type_function(self, func):
+        if self._namespace.name == 'GLib':
             # No GObjects in GLib
             return False
-        if (self._namespace_name == 'GObject' and
+        if (self._namespace.name == 'GObject' and
             symbol in ('g_object_get_type', 'g_initially_unowned_get_type')):
             # We handle these internally, see _create_gobject
             return True
@@ -421,13 +329,10 @@ class GLibTransformer(object):
         self._get_type_functions.append(symbol)
         return True
 
-    def _parse_error_quark_function(self, func):
-        if not func.symbol.endswith('_error_quark'):
-            return False
+    def _initparse_error_quark_function(self, func):
         if func.parameters:
             return False
-        if (func.retval.type.name != 'GLib.Quark' and
-            func.retval.type.ctype != 'GQuark'):
+        if func.retval.type.target_giname != 'GLib.Quark':
             return False
 
         self._error_quark_functions.append(func)
@@ -457,7 +362,7 @@ class GLibTransformer(object):
             target_klass = None
         if not target_klass:
             return None
-        self._remove_attribute(func.name)
+        self._namespace.remove(func)
         func.name = methname
         target_klass.static_methods.append(func)
         func.is_method = True
@@ -491,7 +396,7 @@ class GLibTransformer(object):
             name = self._transformer.remove_prefix(argtype)
             name_uscore = to_underscores_noprefix(name).lower()
             # prefer the prefix of the _get_type method, if there is one
-            if argtype in self._names.type_names:
+            if argtype in self._namespace.type_names:
                 node = self._names.type_names[argtype][1]
                 if hasattr(node, 'get_type'):
                     name_uscore = GET_TYPE_OVERRIDES.get(node.get_type,
@@ -550,7 +455,7 @@ class GLibTransformer(object):
             name = self._transformer.remove_prefix(remove_prefix)
             func.retval.type = Type(name, func.retval.type.ctype)
 
-        self._remove_attribute(func.name)
+        self._namespace.remove(func)
         # Strip namespace and object prefix: gtk_window_new -> new
         func.name = func.symbol[len(prefix)+1:]
         if is_method:
@@ -562,38 +467,15 @@ class GLibTransformer(object):
             klass.constructors.append(func)
         return func
 
-    def _parse_record(self, record):
-        # This is a hack, but GObject is a rather fundamental piece so.
-        internal_names = ["Object", 'InitiallyUnowned']
-        g_internal_names = ["G" + x for x in internal_names]
-        if (self._namespace_name == 'GObject' and
-            record.name in internal_names):
+    def _initparse_gobject_record(self, record):
+        # Special handling for when we're parsing GObject
+        internal_names = ("Object", 'InitiallyUnowned')
+        if record.name in internal_names:
             self._create_gobject(record)
             return
-        elif record.name in g_internal_names:
-            # Avoid duplicates
-            return
         if record.name == 'InitiallyUnownedClass':
             record.fields = self._names.names['ObjectClass'][1].fields
-        node = self._names.names.get(record.name)
-        if node is None:
-            self._add_attribute(record, replace=True)
-            self._register_internal_type(record.symbol, record)
-            return
-        (ns, node) = node
-        node.fields = record.fields[:]
-
-    def _parse_union(self, union):
-        node = self._names.names.get(union.name)
-        if node is None:
-            self._add_attribute(union, replace=True)
-            self._register_internal_type(union.symbol, union)
-            return
-        (ns, node) = node
-        node.fields = union.fields[:]
-
-    def _parse_callback(self, callback):
-        self._add_attribute(callback)
+        self._namespace.append(record, replace=True)
 
     def _strip_class_suffix(self, name):
         if (name.endswith('Class') or
@@ -612,7 +494,7 @@ class GLibTransformer(object):
             return True
         return False
 
-    def _pair_class_record(self, maybe_class):
+    def _pass2_pair_class_record(self, maybe_class):
         name = self._strip_class_suffix(maybe_class.name)
         if name == maybe_class.name:
             return
@@ -672,13 +554,13 @@ class GLibTransformer(object):
                 vfunc.invoker = method
 
         gclass_struct = GLibRecord.from_record(class_struct)
-        self._remove_attribute(class_struct.name)
-        self._add_attribute(gclass_struct, True)
+        self._namespace.append(gclass_struct, replace=True)
         pair_class.glib_type_struct = gclass_struct
         pair_class.inherit_file_positions(class_struct)
         gclass_struct.is_gtype_struct_for = name
 
-    # Introspection
+    # Introspection over the data we get from the dynamic
+    # GObject/GType system out of the binary
 
     def _introspect_type(self, xmlnode):
         if xmlnode.tag in ('enum', 'flags'):
@@ -707,8 +589,7 @@ class GLibTransformer(object):
         type_name = node.attrib['name']
         enum_name = self._transformer.remove_prefix(type_name)
         node = klass(enum_name, type_name, members, node.attrib['get-type'])
-        self._add_attribute(node, replace=True)
-        self._register_internal_type(type_name, node)
+        self._namespace.append(node, replace=True)
 
     def _introspect_object(self, xmlnode):
         type_name = xmlnode.attrib['name']
@@ -720,28 +601,24 @@ class GLibTransformer(object):
         # Get a list of parents here; some of them may be hidden, and what
         # we really want to do is use the most-derived one that we know of.
         #
-        parent_type_names = xmlnode.attrib['parents'].split(',')
-        parent_gitype = self._resolve_gtypename_chain(parent_type_names)
         is_abstract = bool(xmlnode.attrib.get('abstract', False))
-        node = GLibObject(
-            self._transformer.remove_prefix(type_name),
-            parent_gitype,
-            type_name,
-            xmlnode.attrib['get-type'], is_abstract)
+        node = GLibObject(self._transformer.remove_prefix(type_name),
+                          None,
+                          type_name,
+                          xmlnode.attrib['get-type'], is_abstract)
+        node.parent_gtype_names = xmlnode.attrib['parents'].split(',')
         self._introspect_properties(node, xmlnode)
         self._introspect_signals(node, xmlnode)
         self._introspect_implemented_interfaces(node, xmlnode)
 
         self._add_record_fields(node)
-        self._add_attribute(node, replace=True)
-        self._register_internal_type(type_name, node)
+        self._namespace.append(node, replace=True)
 
     def _introspect_interface(self, xmlnode):
         type_name = xmlnode.attrib['name']
-        node = GLibInterface(
-            self._transformer.remove_prefix(type_name),
-            None,
-            type_name, xmlnode.attrib['get-type'])
+        node = GLibInterface(self._transformer.remove_prefix(type_name),
+                             None,
+                             type_name, xmlnode.attrib['get-type'])
         self._introspect_properties(node, xmlnode)
         self._introspect_signals(node, xmlnode)
         for child in xmlnode.findall('prerequisite'):
@@ -751,11 +628,9 @@ class GLibTransformer(object):
         # GtkFileChooserEmbed is an example of a private interface, we
         # just filter them out
         if xmlnode.attrib['get-type'].startswith('_'):
-            print "NOTICE: Marking %s as internal type" % (type_name, )
             self._private_internal_types[type_name] = node
         else:
-            self._add_attribute(node, replace=True)
-            self._register_internal_type(type_name, node)
+            self._namespace.append(node, replace=True)
 
     def _introspect_boxed(self, xmlnode):
         type_name = xmlnode.attrib['name']
@@ -782,7 +657,7 @@ class GLibTransformer(object):
             construct_only = (flags & G_PARAM_CONSTRUCT_ONLY) != 0
             node.properties.append(Property(
                 pspec.attrib['name'],
-                type_name_from_ctype(ctype),
+                self._transformer._create_type(ctype),
                 readable, writable, construct, construct_only,
                 ctype,
                 ))
@@ -791,9 +666,8 @@ class GLibTransformer(object):
     def _introspect_signals(self, node, xmlnode):
         for signal_info in xmlnode.findall('signal'):
             rctype = signal_info.attrib['return']
-            rtype = Type(self._transformer.parse_ctype(rctype), rctype)
-            return_ = Return(rtype, signal_info.attrib['return'])
-            return_.transfer = PARAM_TRANSFER_FULL
+            rtype = self._transformer.create_type(rctype)
+            return_ = Return(rtype, PARAM_TRANSFER_FULL)
             signal = GLibSignal(signal_info.attrib['name'], return_)
             for i, parameter in enumerate(signal_info.findall('param')):
                 if i == 0:
@@ -801,8 +675,8 @@ class GLibTransformer(object):
                 else:
                     name = 'p%s' % (i-1, )
                 pctype = parameter.attrib['type']
-                ptype = Type(self._transformer.parse_ctype(pctype), pctype)
-                param = Parameter(name, ptype)
+                ptype = self._transformer.create_type(pctype)
+                param = Parameter(name, ptype, PARAM_TRANSFER_NONE)
                 param.transfer = 'none'
                 signal.parameters.append(param)
             node.signals.append(signal)
@@ -838,30 +712,18 @@ class GLibTransformer(object):
             boxed_item.fields = pair_node.fields
         else:
             return False
-        self._add_attribute(boxed_item, replace=True)
+        self._namespace.append(boxed_item, replace=True)
 
     # Node walking
 
-    def _walk(self, node, callback, chain):
-        if not isinstance(node, Node):
-            return
+    def walk_node(self, node, callback, chain):
+        assert isinstance(node, Node)
         if not callback(node, chain):
             return
         chain.append(node)
         def _subwalk(subnode):
             self._walk(subnode, callback, chain)
-        if isinstance(node, (Callback, Callable)):
-            _subwalk(node.retval)
-            for parameter in node.parameters:
-                _subwalk(parameter)
-        elif isinstance(node, (Array, List)):
-            _subwalk(node.element_type)
-        elif isinstance(node, Map):
-            _subwalk(node.key_type)
-            _subwalk(node.value_type)
-        elif isinstance(node, Bitfield):
-            pass
-        elif isinstance(node, Record):
+        if isinstance(node, Record):
             for ctor in node.constructors:
                 _subwalk(ctor)
             for func in node.methods:
@@ -877,21 +739,11 @@ class GLibTransformer(object):
                 _subwalk(meth)
             for ctor in node.constructors:
                 _subwalk(ctor)
-            for prop in node.properties:
-                _subwalk(prop)
-            for field in node.fields:
-                _subwalk(field)
         elif isinstance(node, Interface):
             for meth in node.methods:
                 _subwalk(meth)
             for meth in node.virtual_methods:
                 _subwalk(meth)
-            for prop in node.properties:
-                _subwalk(prop)
-            for field in node.fields:
-                _subwalk(field)
-        elif isinstance(node, Constant):
-            _subwalk(node.type)
         elif isinstance(node, Union):
             for ctor in node.constructors:
                 _subwalk(ctor)
@@ -903,52 +755,8 @@ class GLibTransformer(object):
             for meth in node.methods:
                 _subwalk(meth)
 
-        if isinstance(node, (GLibObject, GLibInterface)):
-            for sig in node.signals:
-                _subwalk(sig)
-
         chain.pop()
 
-    # Resolver
-
-    def _resolve_type_name(self, type_name, ctype=None):
-        # Workaround glib bug #548689, to be included in 2.18.0
-        if type_name == "GParam":
-            type_name = "GObject.ParamSpec"
-        res = self._transformer.resolve_type_name_full
-        try:
-            return res(type_name, ctype, self._names)
-        except KeyError, e:
-            return self._transformer.resolve_type_name(type_name, ctype)
-
-    def _resolve_param_type(self, ptype, **kwargs):
-        # Workaround glib bug #548689, to be included in 2.18.0
-        if ptype.name == "GParam":
-            ptype.name = "GObject.ParamSpec"
-        elif ptype.name == "GObject.Strv":
-            return Array(None, ptype.ctype, Type('utf8'))
-
-        return self._transformer.resolve_param_type_full(ptype,
-                                                         self._names,
-                                                         **kwargs)
-
-    def _resolve_node(self, node):
-        if isinstance(node, Function):
-            self._resolve_function_toplevel(node)
-
-        elif isinstance(node, Callback):
-            self._resolve_function(node)
-        elif isinstance(node, GLibObject):
-            self._resolve_glib_object(node)
-        elif isinstance(node, GLibInterface):
-            self._resolve_glib_interface(node)
-        elif isinstance(node, Record):
-            self._resolve_record(node)
-        elif isinstance(node, Union):
-            self._resolve_union(node)
-        elif isinstance(node, Alias):
-            self._resolve_alias(node)
-
     def _resolve_function_toplevel(self, func):
         for parser in [self._parse_constructor,
                        self._parse_method,
@@ -987,9 +795,6 @@ class GLibTransformer(object):
 
     def _resolve_glib_interface(self, node):
         node.parent = self._force_resolve(node.parent)
-        self._resolve_methods(node.methods)
-        self._resolve_properties(node.properties, node)
-        self._resolve_signals(node.signals)
         node.prerequisites = filter(None,
             [self._force_resolve(x, allow_unknown=True)
              for x in node.prerequisites])
@@ -1009,13 +814,6 @@ class GLibTransformer(object):
         node.interfaces = filter(None,
             [self._force_resolve(x, allow_unknown=True)
                                     for x in node.interfaces])
-        self._resolve_constructors(node.constructors)
-        self._resolve_methods(node.methods)
-        self._resolve_methods(node.static_methods)
-        self._resolve_properties(node.properties, node)
-        self._resolve_signals(node.signals)
-        for field in node.fields:
-            self._resolve_field(field)
 
     def _resolve_glib_boxed(self, node):
         self._resolve_constructors(node.constructors)
@@ -1048,12 +846,58 @@ class GLibTransformer(object):
     def _resolve_property(self, prop):
         prop.type = self._resolve_param_type(prop.type, allow_invalid=False)
 
-    def _adjust_throws(self, func):
-        if func.parameters == []:
-            return
 
-        last_param = func.parameters.pop()
+    def _handle_closure(self, param, closure_idx, closure_param):
+        if (closure_param.type.name == 'any' and
+            closure_param.name.endswith('data')):
+            param.closure_name = closure_param.name
+            param.closure_index = closure_idx
+            return True
+        return False
+
+    def _handle_destroy(self, param, destroy_idx, destroy_param):
+        if (destroy_param.type.name == 'GLib.DestroyNotify' or
+            destroy_param.type.ctype == 'GDestroyNotify'):
+            param.destroy_name = destroy_param.name
+            param.destroy_index = destroy_idx
+            return True
+        return False
+
+    def _pass2_callable(self, node):
+        """Some analysis of a callable type.  
+* Check to see if we have anything that looks like a callback+user_data+GDestroyNotify set.
+* Look for GError **.
+"""
+        for i, param in enumerate(node.params):
+            node = self._transformer.lookup_typenode(param.type)
+            if not isinstance(node, Callback):
+                continue
+
+            # set a default scope
+            if param.scope is None:
+                param.scope = 'call'
+
+            # j is the index where we look for closure/destroy to
+            # group with the callback param
+            j = i + 1
+            if j == len(params):
+                continue # no more args -> nothing to group
+            # look at the param directly following for either a
+            # closure or a destroy; only one of these will fire
+            had_closure = self._handle_closure(param, j, params[j])
+            had_destroy = self._handle_destroy(param, j, params[j])
+            j += 1
+            # are we out of params, or did we find neither?
+            if j == len(params) or (not had_closure and not had_destroy):
+                continue
+            # we found either a closure or a destroy; check the
+            # parameter following for the other
+            if not had_closure:
+                self._handle_closure(param, j, params[j])
+            if not had_destroy:
+                self._handle_destroy(param, j, params[j])
 
+        last_param = func.parameters.pop()
         # Checking type.name=='GLib.Error' generates false positives
         # on methods that take a 'GError *'
         if last_param.type.ctype == 'GError**':
@@ -1061,47 +905,6 @@ class GLibTransformer(object):
         else:
             func.parameters.append(last_param)
 
-    def _resolve_function(self, func):
-        self._resolve_parameters(func.parameters)
-        func.retval.type = self._resolve_param_type(func.retval.type)
-        self._adjust_throws(func)
-
-    def _resolve_parameters(self, parameters):
-        for parameter in parameters:
-            parameter.type = self._resolve_param_type(parameter.type)
-
-    def _resolve_field(self, field):
-        if isinstance(field, Callback):
-            self._resolve_function(field)
-        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)
-
-    def _resolve_types(self, nodes):
-        nodes = list(self._names.names.itervalues())
-        i = 0
-        self._validating = True
-        while True:
-            initlen = len(nodes)
-
-            nodes = list(self._names.names.itervalues())
-            for node in nodes:
-                try:
-                    self._resolve_node(node)
-                except UnknownTypeError, e:
-                    print "WARNING: %s: Deleting %r" % (e, node)
-                    self._remove_attribute(node.name)
-            if len(nodes) == initlen:
-                break
-            i += 1
-        self._validating = False
-
     # Validation
 
     def _interface_vfunc_check(self, node, stack):
@@ -1118,9 +921,7 @@ class GLibTransformer(object):
             if isinstance(node.type, Varargs):
                 parent.introspectable = False
             elif not isinstance(node.type, List) and \
-                 (node.type.name == 'GLib.List' or
-                  (self._transformer._namespace.name == 'GLib'
-                   and node.type.name == 'List')):
+                 (node.type.target_giname == 'GLib.List'):
                 if isinstance(node, Parameter):
                     self._transformer.log_node_warning(parent,
 """Missing (element-type) annotation on argument %r""" % (node.name, ),
@@ -1130,24 +931,24 @@ class GLibTransformer(object):
 """Missing (element-type) annotation on return value""", context=parent)
                 parent.introspectable = False
 
-    def _analyze_node(self, node, stack):
-        if node.skip:
+    def _analyze_node(self, obj, stack):
+        if isinstance(obj, Node) and obj.skip:
             return False
         # Combine one-pass checks here
-        self._interface_vfunc_check(node, stack)
+        self._interface_vfunc_check(obj, stack)
         # Our first pass for scriptability
-        self._introspectable_analysis(node, stack)
+        self._introspectable_analysis(obj, stack)
         return True
 
-    def _introspectable_pass2(self, node, stack):
-        if node.skip:
+    def _introspectable_pass2(self, obj, stack):
+        if isinstance(obj, Node) and obj.skip:
             return False
         # In the second introspectable pass, we propagate introspectablity;
         # for example, a varargs callback as an argument to a function
         # makes the whole function unintrospectable
-        if isinstance(node, TypeContainer):
+        if isinstance(obj, TypeContainer):
             parent = stack[-1]
-            target = self._lookup_node(node.type.name)
+            target = self._transformer.lookup_typenode(obj.type)
             if target and not target.introspectable:
                 parent.introspectable = False
         return True
@@ -1155,7 +956,7 @@ class GLibTransformer(object):
     # This function is called at the very end, before we hand back the
     # completed namespace to the writer.  Add static analysis checks here.
     def final_analyze(self):
-        for (ns, node) in self._names.names.itervalues():
-            self._walk(node, self._analyze_node, [])
-        for (ns, node) in self._names.names.itervalues():
-            self._walk(node, self._introspectable_pass2, [])
+        for node in self._namespace.itervalues():
+            self.walk_node(node, self._analyze_node, [])
+        for node in self._namespace.itervalues():
+            self.walk_node(node, self._introspectable_pass2, [])
diff --git a/giscanner/scannermain.py b/giscanner/scannermain.py
index 363f6f6..d543451 100644
--- a/giscanner/scannermain.py
+++ b/giscanner/scannermain.py
@@ -34,6 +34,8 @@ from giscanner.minixpath import myxpath, xpath_assert
 from giscanner.sourcescanner import SourceScanner
 from giscanner.shlibs import resolve_shlibs
 from giscanner.transformer import Transformer
+from giscanner.girparser import GIRParser
+from giscanner.girwriter import GIRWriter
 
 def _get_option_parser():
     parser = optparse.OptionParser('%prog [options] sources')
@@ -49,6 +51,9 @@ def _get_option_parser():
     parser.add_option("-i", "--include",
                       action="append", dest="includes", default=[],
                       help="include types for other gidls")
+    parser.add_option('', "--passthrough-gir",
+                      action="store", dest="passthrough_gir", default=None,
+                      help="Parse and re-output the specified GIR")
     parser.add_option("", "--add-include-path",
                       action="append", dest="include_paths", default=[],
                       help="include paths for other GIR files")
@@ -101,15 +106,9 @@ def _get_option_parser():
     parser.add_option("-v", "--verbose",
                       action="store_true", dest="verbose",
                       help="be verbose")
-    parser.add_option("", "--noclosure",
-                      action="store_true", dest="noclosure",
-                      help="do not delete unknown types")
     parser.add_option("", "--typelib-xml",
                       action="store_true", dest="typelib_xml",
                       help="Just convert GIR to typelib XML")
-    parser.add_option("", "--inject",
-                      action="store_true", dest="inject",
-                      help="Inject additional components into GIR XML")
     parser.add_option("", "--xpath-assertions",
                       action="store", dest="xpath_assertions",
             help="Use given file to create assertions on GIR content")
@@ -136,54 +135,18 @@ def _get_option_parser():
 def _error(msg):
     raise SystemExit('ERROR: %s' % (msg, ))
 
-def typelib_xml_strip(path):
-    from giscanner.girparser import GIRParser
-    from giscanner.girwriter import GIRWriter
-    from giscanner.girparser import C_NS
-    from xml.etree.cElementTree import parse
-
-    c_ns_key = '{%s}' % (C_NS, )
-
-    tree = parse(path)
-    root = tree.getroot()
-    for node in root.getiterator():
-        for attrib in list(node.attrib):
-            if attrib.startswith(c_ns_key):
-                del node.attrib[attrib]
+def passthrough_gir(path):
     parser = GIRParser()
-    parser.parse_tree(tree)
+    parser.parse(path)
 
     writer = GIRWriter(parser.get_namespace(),
                        parser.get_shared_libraries(),
-                       parser.get_includes())
+                       parser.get_includes(),
+                       parser.get_pkgconfig_packages(),
+                       parser.get_c_includes(),
+                       parser.get_c_prefix())
     sys.stdout.write(writer.get_xml())
-    return 0
-
-def inject(path, additions, outpath):
-    from giscanner.girparser import GIRParser
-    from giscanner.girwriter import GIRWriter
-    from xml.etree.cElementTree import parse
-
-    tree = parse(path)
-    root = tree.getroot()
-    injectDoc = parse(open(additions))
-    for node in injectDoc.getroot():
-        injectPath = node.attrib['path']
-        target = myxpath(root, injectPath)
-        if not target:
-            raise ValueError("Couldn't find path %r" % (injectPath, ))
-        for child in node:
-            target.append(child)
-
-    parser = GIRParser()
-    parser.parse_tree(tree)
-    writer = GIRWriter(parser.get_namespace(),
-                       parser.get_shared_libraries(),
-                       parser.get_includes())
-    outf = open(outpath, 'w')
-    outf.write(writer.get_xml())
-    outf.close()
-    return 0
+    sys.exit(0)
 
 def validate(assertions, path):
     from xml.etree.cElementTree import parse
@@ -237,18 +200,12 @@ def scanner_main(args):
     parser = _get_option_parser()
     (options, args) = parser.parse_args(args)
 
+    if options.passthrough_gir:
+        return passthrough_gir(options.passthrough_gir)
+
     if len(args) <= 1:
         _error('Need at least one filename')
 
-    if options.typelib_xml:
-        return typelib_xml_strip(args[1])
-
-    if options.inject:
-        if len(args) != 4:
-            _error('Need three filenames; e.g. g-ir-scanner '
-                   '--inject Source.gir Additions.xml SourceOut.gir')
-        return inject(*args[1:4])
-
     if options.xpath_assertions:
         return validate(options.xpath_assertions, args[1])
 
@@ -314,8 +271,7 @@ def scanner_main(args):
 
     # Transform the C AST nodes into higher level
     # GLib/GObject nodes
-    glibtransformer = GLibTransformer(transformer,
-                                      noclosure=options.noclosure)
+    glibtransformer = GLibTransformer(transformer)
 
     # Do enough parsing that we have the get_type() functions to reference
     # when creating the introspection binary
diff --git a/giscanner/sourcescanner.py b/giscanner/sourcescanner.py
index acfc048..b024baf 100644
--- a/giscanner/sourcescanner.py
+++ b/giscanner/sourcescanner.py
@@ -154,10 +154,16 @@ class SourceSymbol(object):
         self._symbol = symbol
 
     def __repr__(self):
-        return '<%s type=%r ident=%r>' % (
+        src = self.source_filename
+        if src:
+            line = self.line
+            if line:
+                src += ':%r' % (line,)
+        return '<%s type=%r ident=%r src=%r>' % (
             self.__class__.__name__,
             symbol_type_name(self.type),
-            self.ident)
+            self.ident,
+            src)
 
     @property
     def const_int(self):
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index 319e43c..85ea657 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -22,12 +22,11 @@ import os
 import sys
 
 from .ast import (Bitfield, Callback, Enum, Function, Namespace, Member,
-                  Parameter, Return, Struct, Field,
+                  Parameter, Return, Record, Field,
                   Type, Array, Alias, Interface, Class, Node, Union,
                   Varargs, Constant, type_name_from_ctype,
-                  type_names, TYPE_STRING, BASIC_GIR_TYPES)
+                  type_names, default_array_types, TYPE_STRING, BASIC_GIR_TYPES)
 from .config import DATADIR, GIR_DIR, GIR_SUFFIX
-from .glibast import GLibBoxed
 from .girparser import GIRParser
 from .odict import odict
 from .sourcescanner import (
@@ -43,46 +42,25 @@ from .utils import to_underscores
 _xdg_data_dirs = [x for x in os.environ.get('XDG_DATA_DIRS', '').split(':') \
                       + [DATADIR, '/usr/share'] if x]
 
-
-class SkipError(Exception):
-    pass
-
-
-class Names(object):
-    names = property(lambda self: self._names)
-    aliases = property(lambda self: self._aliases)
-    type_names = property(lambda self: self._type_names)
-    ctypes = property(lambda self: self._ctypes)
-
-    def __init__(self):
-        super(Names, self).__init__()
-        self._names = odict() # Maps from GIName -> (namespace, node)
-        self._aliases = {} # Maps from GIName -> GIName
-        self._type_names = {} # Maps from GTName -> (namespace, node)
-        self._ctypes = {} # Maps from CType -> (namespace, node)
-
-
 class Transformer(object):
+    namespace = property(lambda self: self._namespace)
 
     def __init__(self, cachestore, namespace_name, namespace_version):
         self._cwd = os.getcwd() + os.sep
         self._cachestore = cachestore
         self.generator = None
         self._namespace = Namespace(namespace_name, namespace_version)
-        self._names = Names()
         self._pkg_config_packages = set()
         self._typedefs_ns = {}
         self._strip_prefix = ''
         self._enable_warnings = False
         self._warned = False
-        self._includes = set()
+        self._includes = {}
+        self._include_names = set()
         self._includepaths = []
 
-    def get_names(self):
-        return self._names
-
     def get_includes(self):
-        return self._includes
+        return self._include_names
 
     def set_strip_prefix(self, strip_prefix):
         self._strip_prefix = strip_prefix
@@ -105,22 +83,42 @@ class Transformer(object):
     def parse(self):
         nodes = []
         for symbol in self.generator.get_symbols():
-            try:
-                node = self._traverse_one(symbol)
-            except SkipError:
+            if symbol.ident.startswith('_'):
                 continue
-            self._add_node(node)
-        return self._namespace
+            node = self._traverse_one(symbol)
+            if node:
+                self._namespace.append(node)
 
     def set_include_paths(self, paths):
         self._includepaths = list(paths)
 
     def register_include(self, include):
-        if include in self._includes:
+        if include in self._include_names:
             return
         filename = self._find_include(include)
         self._parse_include(filename)
-        self._includes.add(include)
+        self._include_names.add(include)
+
+    def lookup_giname(self, name):
+        """Given a name of the form Foo or Bar.Foo,
+return the corresponding Node, or None if none
+available.  Will throw KeyError however for unknown
+namespaces."""
+        if '.' not in name:
+            return self._namespace.get(name)
+        else:
+            (ns, name) = name.split('.', 1)
+            include = self._includes[ns]
+            return include.get(name)
+
+    def lookup_typenode(self, typeobj):
+        """Given a Type object, if it points to a giname,
+calls lookup_giname() on the name.  Otherwise return
+None."""
+        if typeobj.target_giname:
+            return self.lookup_giname(typeobj.target_giname)
+        return None
+
 
     # Private
 
@@ -205,26 +203,7 @@ context will be used."""
         for pkg in parser.get_pkgconfig_packages():
             self._pkg_config_packages.add(pkg)
         namespace = parser.get_namespace()
-        nsname = namespace.name
-        for node in namespace.nodes:
-            if isinstance(node, Alias):
-                self._names.aliases[node.name] = (nsname, node)
-            elif isinstance(node, (GLibBoxed, Interface, Class)):
-                self._names.type_names[node.type_name] = (nsname, node)
-            giname = '%s.%s' % (nsname, node.name)
-            self._names.names[giname] = (nsname, node)
-            if hasattr(node, 'ctype'):
-                self._names.ctypes[node.ctype] = (nsname, node)
-            elif hasattr(node, 'symbol'):
-                self._names.ctypes[node.symbol] = (nsname, node)
-
-    def _add_node(self, node):
-        if node is None:
-            return
-        if node.name.startswith('_'):
-            return
-        self._namespace.nodes.append(node)
-        self._names.names[node.name] = (None, node)
+        self._includes[namespace.name] = namespace
 
     def _strip_namespace_func(self, name):
         prefix = self._namespace.name.lower() + '_'
@@ -263,17 +242,16 @@ context will be used."""
             return self._create_struct(symbol)
         elif stype == CSYMBOL_TYPE_ENUM:
             return self._create_enum(symbol)
-        elif stype == CSYMBOL_TYPE_OBJECT:
-            return self._create_object(symbol)
         elif stype == CSYMBOL_TYPE_MEMBER:
             return self._create_member(symbol)
         elif stype == CSYMBOL_TYPE_UNION:
             return self._create_union(symbol)
-        elif stype == CSYMBOL_TYPE_CONST:
-            return self._create_const(symbol)
+        # FIXME - we should require an annotation on
+        # #defines to have them be constants, really
+        #elif stype == CSYMBOL_TYPE_CONST:
+        #    return self._create_const(symbol)
         else:
-            raise NotImplementedError(
-                'Transformer: unhandled symbol: %r' % (symbol, ))
+            print 'transformer: unhandled symbol: %r' % (symbol, )
 
     def _enum_common_prefix(self, symbol):
         def common_prefix(a, b):
@@ -323,72 +301,11 @@ context will be used."""
             klass = Enum
         node = klass(enum_name, symbol.ident, members)
         node.add_symbol_reference(symbol)
-        self._names.type_names[symbol.ident] = (None, node)
         return node
 
-    def _create_object(self, symbol):
-        node = Member(symbol.ident, symbol.base_type.name,
-                      symbol.ident)
-        node.add_symbol_reference(symbol)
-        return node
-
-    def _type_is_callback(self, type):
-        if isinstance(type, Callback):
-            return True
-        node = self._names.names.get(type.name)
-        if node and isinstance(node[1], Callback):
-            return True
-        return False
-
-    def _handle_closure(self, param, closure_idx, closure_param):
-        if (closure_param.type.name == 'any' and
-            closure_param.name.endswith('data')):
-            param.closure_name = closure_param.name
-            param.closure_index = closure_idx
-            return True
-        return False
-
-    def _handle_destroy(self, param, destroy_idx, destroy_param):
-        if (destroy_param.type.name == 'GLib.DestroyNotify' or
-            destroy_param.type.ctype == 'GDestroyNotify'):
-            param.destroy_name = destroy_param.name
-            param.destroy_index = destroy_idx
-            return True
-        return False
-
-    def _augment_callback_params(self, params):
-        for i, param in enumerate(params):
-            if not self._type_is_callback(param.type):
-                continue
-
-            # set a default scope
-            if param.scope is None:
-                param.scope = 'call'
-
-            # j is the index where we look for closure/destroy to
-            # group with the callback param
-            j = i + 1
-            if j == len(params):
-                continue # no more args -> nothing to group
-            # look at the param directly following for either a
-            # closure or a destroy; only one of these will fire
-            had_closure = self._handle_closure(param, j, params[j])
-            had_destroy = self._handle_destroy(param, j, params[j])
-            j += 1
-            # are we out of params, or did we find neither?
-            if j == len(params) or (not had_closure and not had_destroy):
-                continue
-            # we found either a closure or a destroy; check the
-            # parameter following for the other
-            if not had_closure:
-                self._handle_closure(param, j, params[j])
-            if not had_destroy:
-                self._handle_destroy(param, j, params[j])
-
     def _create_function(self, symbol):
         parameters = list(self._create_parameters(symbol.base_type))
         return_ = self._create_return(symbol.base_type.base_type)
-        self._augment_callback_params(parameters)
         name = self._strip_namespace_func(symbol.ident)
         func = Function(name, return_, parameters, symbol.ident)
         func.add_symbol_reference(symbol)
@@ -412,7 +329,6 @@ context will be used."""
         return value
 
     def _create_parameters(self, base_type):
-
         # warn if we see annotations for unknown parameters
         param_names = set(child.ident for child in base_type.child_list)
         for child in base_type.child_list:
@@ -438,20 +354,17 @@ context will be used."""
                 else:
                     derefed_name = canonical_ctype
                 derefed_name = self.resolve_param_type(derefed_name)
-                ftype = Array(None, ctype, self.parse_ctype(derefed_name))
+                ftype = Array(ctype, self.parse_ctype(derefed_name))
                 child_list = list(symbol.base_type.child_list)
                 ftype.zeroterminated = False
                 if child_list:
-                    ftype.size = '%d' % (child_list[0].const_int, )
+                    ftype.size = child_list[0].const_int
             else:
-                ftype = self._create_type(symbol.base_type,
-                                          is_param=False, is_retval=False)
-            ftype = self.resolve_param_type(ftype)
+                ftype = self._create_type_from_base(symbol.base_type)
             # Fields are assumed to be read-write
             # (except for Objects, see also glibtransformer.py)
-            node = Field(symbol.ident, ftype, ftype.name,
+            node = Field(symbol.ident, ftype, symbol.ident,
                          readable=True, writable=True, bits=symbol.const_int)
-            node.add_symbol_reference(symbol)
         return node
 
     def _create_typedef(self, symbol):
@@ -527,47 +440,33 @@ context will be used."""
         else:
             return derefed_typename
 
-    def _create_type(self, source_type, is_param, is_retval):
+    def _create_type_from_base(self, source_type):
         ctype = self._create_source_type(source_type)
-        if ctype.startswith('va_list'):
-            raise SkipError()
-        # FIXME: FILE* should not be skipped, it should be handled
-        #        properly instead
-        elif ctype == 'FILE*':
-            raise SkipError
-
-        is_member = not (is_param or is_retval)
-        # Here we handle basic type parsing; most of the heavy lifting
-        # and inference comes in annotationparser.py when we merge
-        # in annotation data.
-        derefed_name = self.parse_ctype(ctype, is_member)
-        rettype = Type(derefed_name, ctype)
-        rettype.canonical = self._canonicalize_ctype(ctype)
-        derefed_ctype = ctype.replace('*', '')
-        rettype.derefed_canonical = self._canonicalize_ctype(derefed_ctype)
-
-        canontype = type_name_from_ctype(ctype)
-        # Is it a const char * or a const gpointer?
-        if ((canontype == TYPE_STRING or source_type.type == CTYPE_POINTER) and
-            (source_type.base_type.type_qualifier & TYPE_QUALIFIER_CONST)):
-            rettype.is_const = True
-        return rettype
+        const = ((source_type.type == CTYPE_POINTER) and
+                 (source_type.base_type.type_qualifier & TYPE_QUALIFIER_CONST))
+        return self.create_type(ctype, is_const=const)
+
+    def create_type(self, ctype, is_const=False):
+        canonical = self._canonicalize_ctype(ctype)
+
+        if canonical in type_names:
+            return Type(target_fundamental=canonical, ctype=canonical,
+                        is_const=is_const)
+        elif canonical in default_array_types:
+            element_type = canonical[:-1]
+            return Array(element_type, canonical, is_const=is_const)
+
+        return Type(ctype=ctype)
 
     def _create_parameter(self, symbol):
         if symbol.type == CSYMBOL_TYPE_ELLIPSIS:
             ptype = Varargs()
         else:
-            ptype = self._create_type(symbol.base_type,
-                                      is_param=True, is_retval=False)
-            ptype = self.resolve_param_type(ptype)
+            ptype = self._create_type_from_base(symbol.base_type)
         return Parameter(symbol.ident, ptype)
 
     def _create_return(self, source_type):
-        rtype = self._create_type(source_type,
-                                  is_param=False, is_retval=True)
-        rtype = self.resolve_param_type(rtype)
-        return_ = Return(rtype)
-        return return_
+        return Return(self._create_type_from_base(source_type))
 
     def _create_const(self, symbol):
         # Don't create constants for non-public things
@@ -594,7 +493,7 @@ context will be used."""
 
     def _create_typedef_struct(self, symbol, disguised=False):
         name = self.remove_prefix(symbol.ident)
-        struct = Struct(name, symbol.ident, disguised)
+        struct = Record(name, symbol.ident, disguised)
         struct.add_symbol_reference(symbol)
         self._typedefs_ns[symbol.ident] = struct
         self._create_struct(symbol)
@@ -643,7 +542,7 @@ context will be used."""
         return compound
 
     def _create_struct(self, symbol, anonymous=False):
-        return self._create_compound(Struct, symbol, anonymous)
+        return self._create_compound(Record, symbol, anonymous)
 
     def _create_union(self, symbol, anonymous=False):
         return self._create_compound(Union, symbol, anonymous)
@@ -654,15 +553,15 @@ context will be used."""
 
         # Mark the 'user_data' arguments
         for i, param in enumerate(parameters):
-            if (param.type.name == 'any' and
-                param.name == 'user_data'):
+            if (param.type.target_fundamental == 'any' and
+                param.argname == 'user_data'):
                 param.closure_index = i
 
         if symbol.ident.find('_') > 0:
             name = self.remove_prefix(symbol.ident, True)
         else:
             name = self.remove_prefix(symbol.ident)
-        callback = Callback(name, retval, parameters, symbol.ident)
+        callback = Callback(name, retval, parameters)
         callback.add_symbol_reference(symbol)
 
         return callback
@@ -673,53 +572,6 @@ context will be used."""
             return item.name
         return '%s.%s' % (nsname, item.name)
 
-    def _resolve_type_name_1(self, type_name, ctype, names):
-        # First look using the built-in names
-        if ctype:
-            try:
-                return type_names[ctype]
-            except KeyError, e:
-                pass
-        try:
-            return type_names[type_name]
-        except KeyError, e:
-            pass
-
-        if ctype:
-            ctype = ctype.replace('*', '')
-            resolved = names.ctypes.get(ctype)
-            if resolved:
-                return self._typepair_to_str(resolved)
-        type_name = self.remove_prefix(type_name)
-        resolved = names.aliases.get(type_name)
-        if resolved:
-            return self._typepair_to_str(resolved)
-        resolved = names.names.get(type_name)
-        if resolved:
-            return self._typepair_to_str(resolved)
-        resolved = names.type_names.get(type_name)
-        if resolved:
-            return self._typepair_to_str(resolved)
-        raise KeyError("failed to find %r" % (type_name, ))
-
-    def resolve_type_name_full(self, type_name, ctype,
-                               names, allow_invalid=True):
-        try:
-            return self._resolve_type_name_1(type_name, ctype, names)
-        except KeyError, e:
-            try:
-                return self._resolve_type_name_1(type_name, ctype, self._names)
-            except KeyError, e:
-                if not allow_invalid:
-                    raise
-                return type_name
-
-    def resolve_type_name(self, type_name, ctype=None):
-        try:
-            return self.resolve_type_name_full(type_name, ctype, self._names)
-        except KeyError, e:
-            return type_name
-
     def gtypename_to_giname(self, gtname, names):
         resolved = names.type_names.get(gtname)
         if resolved:
@@ -737,23 +589,6 @@ context will be used."""
         else:
             return None
 
-    def resolve_param_type_full(self, ptype, names, **kwargs):
-        if isinstance(ptype, Node):
-            ptype.name = self.resolve_type_name_full(ptype.name,
-                                                     self.ctype_of(ptype),
-                                                     names, **kwargs)
-        elif isinstance(ptype, basestring):
-            return self.resolve_type_name_full(ptype, ptype, names, **kwargs)
-        else:
-            raise AssertionError("Unhandled param: %r" % (ptype, ))
-        return ptype
-
-    def resolve_param_type(self, ptype):
-        try:
-            return self.resolve_param_type_full(ptype, self._names)
-        except KeyError, e:
-            return ptype
-
     def follow_aliases(self, type_name, names):
         while True:
             resolved = names.aliases.get(type_name)
@@ -763,8 +598,3 @@ context will be used."""
             else:
                 break
         return type_name
-
-    def iter_enums(self):
-        for node in self._namespace.nodes:
-            if isinstance(node, Enum):
-                yield node



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