diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index 9f3f033..a966d43 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -1,30 +1,24 @@
 PLATFORM_VERSION = 2.0
 
+SUBDIRS = libcodegen
+
 bin_SCRIPTS = pygobject-codegen-$(PLATFORM_VERSION)
 
 codegendir = $(pkgdatadir)/$(PLATFORM_VERSION)/codegen
 
 codegen_PYTHON = \
-	__init__.py \
-	argtypes.py \
-	reversewrapper.py \
 	code-coverage.py \
 	codegen.py \
-	definitions.py \
+	createdefs.py \
 	defsconvert.py \
 	defsgen.py \
-	defsparser.py \
-	docextract.py \
 	docextract_to_xml.py \
 	docgen.py \
 	h2def.py \
-	defsgen.py \
-	createdefs.py \
+	__init__.py \
 	mergedefs.py \
 	missingdefs.py \
 	mkskel.py \
-	override.py \
-	scanvirtuals.py \
-	scmexpr.py
+	scanvirtuals.py
 
 EXTRA_DIST = README.defs pygobject-codegen-$(PLATFORM_VERSION).in
diff --git a/codegen/__init__.py b/codegen/__init__.py
index 86188f9..e69de29 100644
--- a/codegen/__init__.py
+++ b/codegen/__init__.py
@@ -1,16 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-
-__all__ = [
-    'argtypes',
-    'codegen',
-    'definitions',
-    'defsparser',
-    'docextract',
-    'docgen',
-    'h2def',
-    'defsgen'
-    'mergedefs',
-    'mkskel',
-    'override',
-    'scmexpr'
-]
diff --git a/codegen/argtypes.py b/codegen/argtypes.py
deleted file mode 100644
index b35f6ef..0000000
--- a/codegen/argtypes.py
+++ /dev/null
@@ -1,1043 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-import string
-import keyword
-import struct
-
-py_ssize_t_clean = False
-
-class ArgTypeError(Exception):
-    pass
-
-class ArgTypeNotFoundError(ArgTypeError):
-    pass
-
-class ArgTypeConfigurationError(ArgTypeError):
-    pass
-
-
-class VarList:
-    """Nicely format a C variable list"""
-    def __init__(self):
-        self.vars = {}
-    def add(self, ctype, name):
-        if self.vars.has_key(ctype):
-            self.vars[ctype] = self.vars[ctype] + (name,)
-        else:
-            self.vars[ctype] = (name,)
-    def __str__(self):
-        ret = []
-        for type in self.vars.keys():
-            ret.append('    ')
-            ret.append(type)
-            ret.append(' ')
-            ret.append(string.join(self.vars[type], ', '))
-            ret.append(';\n')
-        if ret:
-            ret.append('\n')
-            return string.join(ret, '')
-        return ''
-
-class WrapperInfo:
-    """A class that holds information about variable defs, code
-    snippets, etcd for use in writing out the function/method
-    wrapper."""
-    def __init__(self):
-        self.varlist = VarList()
-        self.parsestr = ''
-        self.parselist = ['', 'kwlist']
-        self.codebefore = []
-        self.codeafter = []
-        self.arglist = []
-        self.kwlist = []
-    def get_parselist(self):
-        return string.join(self.parselist, ', ')
-    def get_codebefore(self):
-        return string.join(self.codebefore, '')
-    def get_codeafter(self):
-        return string.join(self.codeafter, '')
-    def get_arglist(self):
-        return string.join(self.arglist, ', ')
-    def get_varlist(self):
-        return str(self.varlist)
-    def get_kwlist(self):
-        ret = '    static char *kwlist[] = { %s };\n' % \
-              string.join(self.kwlist + [ 'NULL' ], ', ')
-        if not self.get_varlist():
-            ret = ret + '\n'
-        return ret
-
-    def add_parselist(self, codes, parseargs, keywords):
-        self.parsestr = self.parsestr + codes
-        for arg in parseargs:
-            self.parselist.append(arg)
-        for kw in keywords:
-            if keyword.iskeyword(kw):
-                kw = kw + '_'
-            self.kwlist.append('"%s"' % kw)
-
-class ArgType:
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        """Add code to the WrapperInfo instance to handle
-        parameter."""
-        raise RuntimeError, "write_param not implemented for %s" % \
-              self.__class__.__name__
-    def write_return(self, ptype, ownsreturn, info):
-        """Adds a variable named ret of the return type to
-        info.varlist, and add any required code to info.codeafter to
-        convert the return value to a python object."""
-        raise RuntimeError, "write_return not implemented for %s" % \
-              self.__class__.__name__
-
-class NoneArg(ArgType):
-    def write_return(self, ptype, ownsreturn, info):
-        info.codeafter.append('    Py_INCREF(Py_None);\n' +
-                              '    return Py_None;')
-
-class StringArg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt != None:
-            if pdflt != 'NULL': pdflt = '"' + pdflt + '"'
-            info.varlist.add('char', '*' + pname + ' = ' + pdflt)
-        else:
-            info.varlist.add('char', '*' + pname)
-        info.arglist.append(pname)
-        if pnull:
-            info.add_parselist('z', ['&' + pname], [pname])
-        else:
-            info.add_parselist('s', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        if ownsreturn:
-            # have to free result ...
-            info.varlist.add('gchar', '*ret')
-            info.codeafter.append('    if (ret) {\n' +
-                                  '        PyObject *py_ret = PyString_FromString(ret);\n' +
-                                  '        g_free(ret);\n' +
-                                  '        return py_ret;\n' +
-                                  '    }\n' +
-                                  '    Py_INCREF(Py_None);\n' +
-                                  '    return Py_None;')
-        else:
-            info.varlist.add('const gchar', '*ret')
-            info.codeafter.append('    if (ret)\n' +
-                                  '        return PyString_FromString(ret);\n'+
-                                  '    Py_INCREF(Py_None);\n' +
-                                  '    return Py_None;')
-
-class UCharArg(ArgType):
-    # allows strings with embedded NULLs.
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('guchar', '*' + pname + ' = "' + pdflt + '"')
-        else:
-            info.varlist.add('guchar', '*' + pname)
-        if py_ssize_t_clean:
-            info.varlist.add('Py_ssize_t', pname + '_len')
-        else:
-            info.varlist.add('int', pname + '_len')
-        info.arglist.append(pname)
-        if pnull:
-            info.add_parselist('z#', ['&' + pname, '&' + pname + '_len'],
-                               [pname])
-        else:
-            info.add_parselist('s#', ['&' + pname, '&' + pname + '_len'],
-                               [pname])
-
-class CharArg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('char', pname + " = '" + pdflt + "'")
-        else:
-            info.varlist.add('char', pname)
-        info.arglist.append(pname)
-        info.add_parselist('c', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('gchar', 'ret')
-        info.codeafter.append('    return PyString_FromStringAndSize(&ret, 1);')
-class GUniCharArg(ArgType):
-    ret_tmpl = ('#if !defined(Py_UNICODE_SIZE) || Py_UNICODE_SIZE == 2\n'
-                '    if (ret > 0xffff) {\n'
-                '        PyErr_SetString(PyExc_RuntimeError, "returned character can not be represented in 16-bit unicode");\n'
-                '        return NULL;\n'
-                '    }\n'
-                '#endif\n'
-                '    py_ret = (Py_UNICODE)ret;\n'
-                '    return PyUnicode_FromUnicode(&py_ret, 1);\n')
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('gunichar', pname + " = '" + pdflt + "'")
-        else:
-            info.varlist.add('gunichar', pname)
-        info.arglist.append(pname)
-        info.add_parselist('O&', ['pyg_pyobj_to_unichar_conv', '&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('gunichar', 'ret')
-        info.varlist.add('Py_UNICODE', 'py_ret')
-        info.codeafter.append(self.ret_tmpl)
-
-
-class IntArg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('int', pname + ' = ' + pdflt)
-        else:
-            info.varlist.add('int', pname)
-        info.arglist.append(pname)
-        info.add_parselist('i', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('int', 'ret')
-        info.codeafter.append('    return PyInt_FromLong(ret);')
-
-class UIntArg(ArgType):
-    dflt = ('    if (py_%(name)s) {\n'
-            '        if (PyLong_Check(py_%(name)s))\n'
-            '            %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
-            '        else if (PyInt_Check(py_%(name)s))\n'
-            '            %(name)s = PyInt_AsLong(py_%(name)s);\n'
-            '        else\n'
-            '            PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
-            '        if (PyErr_Occurred())\n'
-            '            return NULL;\n'
-            '    }\n')
-    before = ('    if (PyLong_Check(py_%(name)s))\n'
-              '        %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
-              '    else if (PyInt_Check(py_%(name)s))\n'
-              '        %(name)s = PyInt_AsLong(py_%(name)s);\n'
-              '    else\n'
-              '        PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
-              '    if (PyErr_Occurred())\n'
-              '        return NULL;\n')
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if not pdflt:
-            pdflt = '0';
-
-        info.varlist.add(ptype, pname + ' = ' + pdflt)
-        info.codebefore.append(self.dflt % {'name':pname})
-        info.varlist.add('PyObject', "*py_" + pname + ' = NULL')
-        info.arglist.append(pname)
-        info.add_parselist('O', ['&py_' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add(ptype, 'ret')
-        info.codeafter.append('    return PyLong_FromUnsignedLong(ret);')
-
-class SizeArg(ArgType):
-
-    if struct.calcsize('P') <= struct.calcsize('l'):
-        llp64 = True
-    else:
-        llp64 = False
-
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add(ptype, pname + ' = ' + pdflt)
-        else:
-            info.varlist.add(ptype, pname)
-        info.arglist.append(pname)
-        if self.llp64:
-            info.add_parselist('k', ['&' + pname], [pname])
-        else:
-            info.add_parselist('K', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add(ptype, 'ret')
-        if self.llp64:
-            info.codeafter.append('    return PyLong_FromUnsignedLongLong(ret);\n')
-        else:
-            info.codeafter.append('    return PyLong_FromUnsignedLong(ret);\n')
-
-class SSizeArg(ArgType):
-
-    if struct.calcsize('P') <= struct.calcsize('l'):
-        llp64 = True
-    else:
-        llp64 = False
-
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add(ptype, pname + ' = ' + pdflt)
-        else:
-            info.varlist.add(ptype, pname)
-        info.arglist.append(pname)
-        if self.llp64:
-            info.add_parselist('l', ['&' + pname], [pname])
-        else:
-            info.add_parselist('L', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add(ptype, 'ret')
-        if self.llp64:
-            info.codeafter.append('    return PyLong_FromLongLong(ret);\n')
-        else:
-            info.codeafter.append('    return PyLong_FromLong(ret);\n')
-
-class LongArg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add(ptype, pname + ' = ' + pdflt)
-        else:
-            info.varlist.add(ptype, pname)
-        info.arglist.append(pname)
-        info.add_parselist('l', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add(ptype, 'ret')
-        info.codeafter.append('    return PyInt_FromLong(ret);\n')
-
-class BoolArg(IntArg):
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('int', 'ret')
-        info.codeafter.append('    return PyBool_FromLong(ret);\n')
-
-class TimeTArg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('time_t', pname + ' = ' + pdflt)
-        else:
-            info.varlist.add('time_t', pname)
-        info.arglist.append(pname)
-        info.add_parselist('i', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('time_t', 'ret')
-        info.codeafter.append('    return PyInt_FromLong(ret);')
-
-class ULongArg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('unsigned long', pname + ' = ' + pdflt)
-        else:
-            info.varlist.add('unsigned long', pname)
-        info.arglist.append(pname)
-        info.add_parselist('k', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add(ptype, 'ret')
-        info.codeafter.append('    return PyLong_FromUnsignedLong(ret);\n')
-
-class UInt32Arg(ULongArg):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        ULongArg.write_param(self, ptype, pname, pdflt, pnull, info)
-        ## if sizeof(unsigned long) > sizeof(unsigned int), we need to
-        ## check the value is within guint32 range
-        if struct.calcsize('L') > struct.calcsize('I'):
-            info.codebefore.append((
-                '    if (%(pname)s > G_MAXUINT32) {\n'
-                '        PyErr_SetString(PyExc_ValueError,\n'
-                '                        "Value out of range in conversion of"\n'
-                '                        " %(pname)s parameter to unsigned 32 bit integer");\n'
-                '        return NULL;\n'
-                '    }\n') % vars())
-
-class Int64Arg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('gint64', pname + ' = ' + pdflt)
-        else:
-            info.varlist.add('gint64', pname)
-        info.arglist.append(pname)
-        info.add_parselist('L', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('gint64', 'ret')
-        info.codeafter.append('    return PyLong_FromLongLong(ret);')
-
-class UInt64Arg(ArgType):
-    dflt = '    if (py_%(name)s)\n' \
-           '        %(name)s = PyLong_AsUnsignedLongLong(py_%(name)s);\n'
-    before = '    %(name)s = PyLong_AsUnsignedLongLong(py_%(name)s);\n'
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('guint64', pname + ' = ' + pdflt)
-            info.codebefore.append(self.dflt % {'name':pname})
-        else:
-            info.varlist.add('guint64', pname)
-            info.codebefore.append(self.before % {'name':pname})
-        info.varlist.add('PyObject', "*py_" + pname + ' = NULL')
-        info.arglist.append(pname)
-        info.add_parselist('O!', ['&PyLong_Type', '&py_' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('guint64', 'ret')
-        info.codeafter.append('    return PyLong_FromUnsignedLongLong(ret);')
-
-
-class DoubleArg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('double', pname + ' = ' + pdflt)
-        else:
-            info.varlist.add('double', pname)
-        info.arglist.append(pname)
-        info.add_parselist('d', ['&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('double', 'ret')
-        info.codeafter.append('    return PyFloat_FromDouble(ret);')
-
-class FileArg(ArgType):
-    nulldflt = ('    if (py_%(name)s == Py_None)\n'
-                '        %(name)s = NULL;\n'
-                '    else if (py_%(name)s && PyFile_Check(py_%(name)s)\n'
-                '        %s = PyFile_AsFile(py_%(name)s);\n'
-                '    else if (py_%(name)s) {\n'
-                '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n'
-                '        return NULL;\n'
-                '    }')
-    null = ('    if (py_%(name)s && PyFile_Check(py_%(name)s)\n'
-            '        %(name)s = PyFile_AsFile(py_%(name)s);\n'
-            '    else if (py_%(name)s != Py_None) {\n'
-            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n'
-            '        return NULL;\n'
-            '    }\n')
-    dflt = ('    if (py_%(name)s)\n'
-            '        %(name)s = PyFile_AsFile(py_%(name)s);\n')
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pnull:
-            if pdflt:
-                info.varlist.add('FILE', '*' + pname + ' = ' + pdflt)
-                info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
-                info.codebefore.append(self.nulldflt % {'name':pname})
-            else:
-                info.varlist.add('FILE', '*' + pname + ' = NULL')
-                info.varlist.add('PyObject', '*py_' + pname)
-                info.codebefore.append(self.null & {'name':pname})
-            info.arglist.appned(pname)
-            info.add_parselist('O', ['&py_' + pname], [pname])
-        else:
-            if pdflt:
-                info.varlist.add('FILE', '*' + pname + ' = ' + pdflt)
-                info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
-                info.codebefore.append(self.dflt % {'name':pname})
-                info.arglist.append(pname)
-            else:
-                info.varlist.add('PyObject', '*' + pname)
-                info.arglist.append('PyFile_AsFile(' + pname + ')')
-            info.add_parselist('O!', ['&PyFile_Type', '&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('FILE', '*ret')
-        info.codeafter.append('    if (ret)\n' +
-                              '        return PyFile_FromFile(ret, "", "", fclose);\n' +
-                              '    Py_INCREF(Py_None);\n' +
-                              '    return Py_None;')
-
-class EnumArg(ArgType):
-    enum = ('    if (pyg_enum_get_value(%(typecode)s, py_%(name)s, (gpointer)&%(name)s))\n'
-            '        return NULL;\n')
-    def __init__(self, enumname, typecode):
-        self.enumname = enumname
-        self.typecode = typecode
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add(self.enumname, pname + ' = ' + pdflt)
-        else:
-            info.varlist.add(self.enumname, pname)
-        info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
-        info.codebefore.append(self.enum % { 'typecode': self.typecode,
-                                             'name': pname})
-        info.arglist.append(pname)
-        info.add_parselist('O', ['&py_' + pname], [pname]);
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('gint', 'ret')
-        info.codeafter.append('    return pyg_enum_from_gtype(%s, ret);' % self.typecode)
-
-class FlagsArg(ArgType):
-    flag = ('    if (%(default)spyg_flags_get_value(%(typecode)s, py_%(name)s, (gpointer)&%(name)s))\n'
-            '        return NULL;\n')
-    def __init__(self, flagname, typecode):
-        self.flagname = flagname
-        self.typecode = typecode
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add(self.flagname, pname + ' = ' + pdflt)
-            default = "py_%s && " % (pname,)
-        else:
-            info.varlist.add(self.flagname, pname)
-            default = ""
-        info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
-        info.codebefore.append(self.flag % {'default':default,
-                                            'typecode':self.typecode,
-                                            'name':pname})
-        info.arglist.append(pname)
-        info.add_parselist('O', ['&py_' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('guint', 'ret')
-        info.codeafter.append('    return pyg_flags_from_gtype(%s, ret);' % self.typecode)
-
-class ObjectArg(ArgType):
-    # should change these checks to more typesafe versions that check
-    # a little further down in the class heirachy.
-    nulldflt = ('    if ((PyObject *)py_%(name)s == Py_None)\n'
-                '        %(name)s = NULL;\n'
-                '    else if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n'
-                '        %(name)s = %(cast)s(py_%(name)s->obj);\n'
-                '    else if (py_%(name)s) {\n'
-                '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
-                '        return NULL;\n'
-                '    }\n')
-    null = ('    if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n'
-            '        %(name)s = %(cast)s(py_%(name)s->obj);\n'
-            '    else if ((PyObject *)py_%(name)s != Py_None) {\n'
-            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
-            '        return NULL;\n'
-            '    }\n')
-    dflt = '    if (py_%(name)s)\n' \
-           '        %(name)s = %(cast)s(py_%(name)s->obj);\n'
-    def __init__(self, objname, parent, typecode):
-        self.objname = objname
-        self.cast = string.replace(typecode, '_TYPE_', '_', 1)
-        self.parent = parent
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pnull:
-            if pdflt:
-                info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt)
-                info.varlist.add('PyGObject', '*py_' + pname + ' = NULL')
-                info.codebefore.append(self.nulldflt % {'name':pname,
-                                                        'cast':self.cast,
-                                                        'type':self.objname})
-            else:
-                info.varlist.add(self.objname, '*' + pname + ' = NULL')
-                info.varlist.add('PyGObject', '*py_' + pname)
-                info.codebefore.append(self.null % {'name':pname,
-                                                    'cast':self.cast,
-                                                    'type':self.objname})
-            if ptype.endswith('*'):
-                typename = ptype[:-1]
-                try:
-                    const, typename = typename.split('const-')
-                except ValueError:
-                    const = ''
-                if typename != ptype:
-                    info.arglist.append('(%s *) %s' % (ptype[:-1], pname))
-                else:
-                    info.arglist.append(pname)
-
-            info.add_parselist('O', ['&py_' + pname], [pname])
-        else:
-            if pdflt:
-                info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt)
-                info.varlist.add('PyGObject', '*py_' + pname + ' = NULL')
-                info.codebefore.append(self.dflt % {'name':pname,
-                                                    'cast':self.cast})
-                info.arglist.append(pname)
-                info.add_parselist('O!', ['&Py%s_Type' % self.objname,
-                                         '&py_' + pname], [pname])
-            else:
-                info.varlist.add('PyGObject', '*' + pname)
-                info.arglist.append('%s(%s->obj)' % (self.cast, pname))
-                info.add_parselist('O!', ['&Py%s_Type' % self.objname,
-                                          '&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        if ptype.endswith('*'):
-            typename = ptype[:-1]
-            try:
-                const, typename = typename.split('const-')
-            except ValueError:
-                const = ''
-        info.varlist.add(typename, '*ret')
-        if ownsreturn:
-            info.varlist.add('PyObject', '*py_ret')
-            info.codeafter.append('    py_ret = pygobject_new((GObject *)ret);\n'
-                                  '    if (ret != NULL)\n'
-                                  '        g_object_unref(ret);\n'
-                                  '    return py_ret;')
-        else:
-            info.codeafter.append('    /* pygobject_new handles NULL checking */\n' +
-                                  '    return pygobject_new((GObject *)ret);')
-
-class BoxedArg(ArgType):
-    # haven't done support for default args.  Is it needed?
-    check = ('    if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n'
-             '        %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n'
-             '    else {\n'
-             '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n'
-             '        return NULL;\n'
-             '    }\n')
-    null = ('    if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n'
-            '        %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n'
-            '    else if (py_%(name)s != Py_None) {\n'
-            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n'
-            '        return NULL;\n'
-            '    }\n')
-    def __init__(self, ptype, typecode):
-        self.typename = ptype
-        self.typecode = typecode
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pnull:
-            info.varlist.add(self.typename, '*' + pname + ' = NULL')
-            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
-            info.codebefore.append(self.null % {'name':  pname,
-                                                'typename': self.typename,
-                                                'typecode': self.typecode})
-        else:
-            info.varlist.add(self.typename, '*' + pname + ' = NULL')
-            info.varlist.add('PyObject', '*py_' + pname)
-            info.codebefore.append(self.check % {'name':  pname,
-                                                 'typename': self.typename,
-                                                 'typecode': self.typecode})
-        if ptype[-1] == '*':
-            typename = ptype[:-1]
-            if typename[:6] == 'const-': typename = typename[6:]
-            if typename != self.typename:
-                info.arglist.append('(%s *)%s' % (ptype[:-1], pname))
-            else:
-                info.arglist.append(pname)
-        else:
-            info.arglist.append(pname)
-        info.add_parselist('O', ['&py_' + pname], [pname])
-    ret_tmpl = '    /* pyg_boxed_new handles NULL checking */\n' \
-               '    return pyg_boxed_new(%(typecode)s, %(ret)s, %(copy)s, TRUE);'
-    def write_return(self, ptype, ownsreturn, info):
-        if ptype[-1] == '*':
-            decl_type = self.typename
-            ret = 'ret'
-            if ptype[:6] == 'const-':
-                decl_type = 'const ' + self.typename
-                ret = '(%s*) ret' % (self.typename,)
-            info.varlist.add(decl_type, '*ret')
-        else:
-            info.varlist.add(self.typename, 'ret')
-            ret = '&ret'
-            ownsreturn = 0 # of course it can't own a ref to a local var ...
-        info.codeafter.append(self.ret_tmpl %
-                              { 'typecode': self.typecode,
-                                'ret': ret,
-                                'copy': ownsreturn and 'FALSE' or 'TRUE'})
-
-class CustomBoxedArg(ArgType):
-    # haven't done support for default args.  Is it needed?
-    null = ('    if (%(check)s(py_%(name)s))\n'
-            '        %(name)s = %(get)s(py_%(name)s);\n'
-            '    else if (py_%(name)s != Py_None) {\n'
-            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
-            '        return NULL;\n'
-            '    }\n')
-    def __init__(self, ptype, pytype, getter, new):
-        self.pytype = pytype
-        self.getter = getter
-        self.checker = 'Py' + ptype + '_Check'
-        self.new = new
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pnull:
-            info.varlist.add(ptype[:-1], '*' + pname + ' = NULL')
-            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
-            info.codebefore.append(self.null % {'name':  pname,
-                                                'get':   self.getter,
-                                                'check': self.checker,
-                                                'type':  ptype[:-1]})
-            info.arglist.append(pname)
-            info.add_parselist('O', ['&py_' + pname], [pname])
-        else:
-            info.varlist.add('PyObject', '*' + pname)
-            info.arglist.append(self.getter + '(' + pname + ')')
-            info.add_parselist('O!', ['&' + self.pytype, '&' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add(ptype[:-1], '*ret')
-        info.codeafter.append('    if (ret)\n' +
-                              '        return ' + self.new + '(ret);\n' +
-                              '    Py_INCREF(Py_None);\n' +
-                              '    return Py_None;')
-
-class PointerArg(ArgType):
-    # haven't done support for default args.  Is it needed?
-    check = ('    if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n'
-             '        %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n'
-             '    else {\n'
-             '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n'
-             '        return NULL;\n'
-             '    }\n')
-    null = ('    if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n'
-            '        %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n'
-            '    else if (py_%(name)s != Py_None) {\n'
-            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n'
-            '        return NULL;\n'
-            '    }\n')
-    def __init__(self, ptype, typecode):
-        self.typename = ptype
-        self.typecode = typecode
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pnull:
-            info.varlist.add(self.typename, '*' + pname + ' = NULL')
-            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
-            info.codebefore.append(self.null % {'name':  pname,
-                                                'typename': self.typename,
-                                                'typecode': self.typecode})
-        else:
-            info.varlist.add(self.typename, '*' + pname + ' = NULL')
-            info.varlist.add('PyObject', '*py_' + pname)
-            info.codebefore.append(self.check % {'name':  pname,
-                                                 'typename': self.typename,
-                                                 'typecode': self.typecode})
-        info.arglist.append(pname)
-        info.add_parselist('O', ['&py_' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        if ptype[-1] == '*':
-            info.varlist.add(self.typename, '*ret')
-            info.codeafter.append('    /* pyg_pointer_new handles NULL checking */\n' +
-                                  '    return pyg_pointer_new(' + self.typecode + ', ret);')
-        else:
-            info.varlist.add(self.typename, 'ret')
-            info.codeafter.append('    /* pyg_pointer_new handles NULL checking */\n' +
-                                  '    return pyg_pointer_new(' + self.typecode + ', &ret);')
-
-class AtomArg(IntArg):
-    dflt = '    if (py_%(name)s) {\n' \
-           '        %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n' \
-           '        if (PyErr_Occurred())\n' \
-           '            return NULL;\n' \
-           '    }\n'
-    atom = ('    %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n'
-            '    if (PyErr_Occurred())\n'
-            '        return NULL;\n')
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('GdkAtom', pname + ' = ' + pdflt)
-            info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
-            info.codebefore.append(self.dflt % {'name': pname})
-        else:
-            info.varlist.add('GdkAtom', pname)
-            info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
-            info.codebefore.append(self.atom % {'name': pname})
-        info.arglist.append(pname)
-        info.add_parselist('O', ['&py_' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('GdkAtom', 'ret')
-        info.varlist.add('PyObject *', 'py_ret')
-        info.varlist.add('gchar *', 'name')
-        info.codeafter.append('    name = gdk_atom_name(ret);\n'
-                              '    py_ret = PyString_FromString(name);\n'
-                              '    g_free(name);\n'
-                              '    return py_ret;')
-
-class GTypeArg(ArgType):
-    gtype = ('    if ((%(name)s = pyg_type_from_object(py_%(name)s)) == 0)\n'
-             '        return NULL;\n')
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        info.varlist.add('GType', pname)
-        info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
-        info.codebefore.append(self.gtype % {'name': pname})
-        info.arglist.append(pname)
-        info.add_parselist('O', ['&py_' + pname], [pname])
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('GType', 'ret')
-        info.codeafter.append('    return pyg_type_wrapper_new(ret);')
-
-# simple GError handler.
-class GErrorArg(ArgType):
-    handleerror = ('    if (pyg_error_check(&%(name)s))\n'
-                   '        return NULL;\n')
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        info.varlist.add('GError', '*' + pname + ' = NULL')
-        info.arglist.append('&' + pname)
-        info.codeafter.append(self.handleerror % { 'name': pname })
-
-class GtkTreePathArg(ArgType):
-    # haven't done support for default args.  Is it needed?
-    normal = ('    %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n'
-              '    if (!%(name)s) {\n'
-              '        PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n'
-              '        return NULL;\n'
-              '    }\n')
-    null = ('    if (py_%(name)s != Py_None) {\n'
-            '        %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n'
-            '        if (!%(name)s) {\n'
-            '            PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n'
-            '            return NULL;\n'
-            '        }\n'
-            '    }\n')
-    freepath = ('    if (%(name)s)\n'
-                '        gtk_tree_path_free(%(name)s);\n')
-    def __init__(self):
-        pass
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pnull:
-            info.varlist.add('GtkTreePath', '*' + pname + ' = NULL')
-            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
-            info.codebefore.append(self.null % {'name':  pname})
-            info.arglist.append(pname)
-            info.add_parselist('O', ['&py_' + pname], [pname])
-        else:
-            info.varlist.add('GtkTreePath', '*' + pname)
-            info.varlist.add('PyObject', '*py_' + pname)
-            info.codebefore.append(self.normal % {'name': pname})
-            info.arglist.append(pname)
-            info.add_parselist('O', ['&py_' + pname], [pname])
-        info.codeafter.append(self.freepath % {'name': pname})
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('GtkTreePath', '*ret')
-        if ownsreturn:
-            info.codeafter.append('    if (ret) {\n'
-                                  '        PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n'
-                                  '        gtk_tree_path_free(ret);\n'
-                                  '        return py_ret;\n'
-                                  '    }\n'
-                                  '    Py_INCREF(Py_None);\n'
-                                  '    return Py_None;')
-        else:
-            info.codeafter.append('    if (ret) {\n'
-                                  '        PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n'
-                                  '        return py_ret;\n'
-                                  '    }\n'
-                                  '    Py_INCREF(Py_None);\n'
-                                  '    return Py_None;')
-
-class GdkRectanglePtrArg(ArgType):
-    normal = ('    if (!pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s))\n'
-              '        return NULL;\n')
-    null =   ('    if (py_%(name)s == Py_None)\n'
-              '        %(name)s = NULL;\n'
-              '    else if (pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s_rect))\n'
-              '        %(name)s = &%(name)s_rect;\n'
-              '    else\n'
-              '            return NULL;\n')
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pnull:
-            info.varlist.add('GdkRectangle', pname + '_rect = { 0, 0, 0, 0 }')
-            info.varlist.add('GdkRectangle', '*' + pname)
-            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
-            info.add_parselist('O', ['&py_' + pname], [pname])
-            info.arglist.append(pname)
-            info.codebefore.append(self.null % {'name':  pname})
-        else:
-            info.varlist.add('GdkRectangle', pname + ' = { 0, 0, 0, 0 }')
-            info.varlist.add('PyObject', '*py_' + pname)
-            info.add_parselist('O', ['&py_' + pname], [pname])
-            info.arglist.append('&' + pname)
-            info.codebefore.append(self.normal % {'name':  pname})
-
-class GdkRectangleArg(ArgType):
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('GdkRectangle', 'ret')
-        info.codeafter.append('    return pyg_boxed_new(GDK_TYPE_RECTANGLE, &ret, TRUE, TRUE);')
-
-class PyObjectArg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        info.varlist.add('PyObject', '*' + pname)
-        info.add_parselist('O', ['&' + pname], [pname])
-        info.arglist.append(pname)
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add("PyObject", "*ret")
-        if ownsreturn:
-            info.codeafter.append('    if (ret) {\n'
-                                  '       return ret;\n'
-                                  '    }\n'
-                                  '    Py_INCREF(Py_None);\n'
-                                  '    return Py_None;')
-        else:
-            info.codeafter.append('    if (!ret) ret = Py_None;\n'
-                                  '    Py_INCREF(ret);\n'
-                                  '    return ret;')
-
-class CairoArg(ArgType):
-    def write_param(self, ptype, pname, pdflt, pnull, info):
-        info.varlist.add('PycairoContext', '*' + pname)
-        info.add_parselist('O!', ['&PycairoContext_Type', '&' + pname], [pname])
-        info.arglist.append('%s->ctx' % pname)
-    def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add("cairo_t", "*ret")
-        if ownsreturn:
-            info.codeafter.append('    return PycairoContext_FromContext(ret, NULL, NULL);')
-        else:
-            info.codeafter.append('    cairo_reference(ret);\n'
-                                  '    return PycairoContext_FromContext(ret, NULL, NULL);')
-
-
-class ArgMatcher:
-    def __init__(self):
-        self.argtypes = {}
-        self.reverse_argtypes = {}
-        self.reverse_rettypes = {}
-
-    def register(self, ptype, handler, overwrite=False):
-        if not overwrite and ptype in self.argtypes:
-            return
-        self.argtypes[ptype] = handler
-    def register_reverse(self, ptype, handler):
-        self.reverse_argtypes[ptype] = handler
-    def register_reverse_ret(self, ptype, handler):
-        self.reverse_rettypes[ptype] = handler
-
-    def register_enum(self, ptype, typecode):
-        if typecode is None:
-            self.register(ptype, IntArg())
-        else:
-            self.register(ptype, EnumArg(ptype, typecode))
-    def register_flag(self, ptype, typecode):
-        if typecode is None:
-            self.register(ptype, IntArg())
-        else:
-            self.register(ptype, FlagsArg(ptype, typecode))
-    def register_object(self, ptype, parent, typecode):
-        oa = ObjectArg(ptype, parent, typecode)
-        self.register(ptype, oa)  # in case I forget the * in the .defs
-        self.register(ptype+'*', oa)
-        self.register('const-'+ptype+'*', oa)
-        if ptype == 'GdkPixmap':
-            # hack to handle GdkBitmap synonym.
-            self.register('GdkBitmap', oa)
-            self.register('GdkBitmap*', oa)
-    def register_boxed(self, ptype, typecode):
-        if self.argtypes.has_key(ptype): return
-        arg = BoxedArg(ptype, typecode)
-        self.register(ptype, arg)
-        self.register(ptype+'*', arg)
-        self.register('const-'+ptype+'*', arg)
-    def register_custom_boxed(self, ptype, pytype, getter, new):
-        arg = CustomBoxedArg(ptype, pytype, getter, new)
-        self.register(ptype+'*', arg)
-        self.register('const-'+ptype+'*', arg)
-    def register_pointer(self, ptype, typecode):
-        arg = PointerArg(ptype, typecode)
-        self.register(ptype, arg)
-        self.register(ptype+'*', arg)
-        self.register('const-'+ptype+'*', arg)
-
-    def get(self, ptype):
-        try:
-            return self.argtypes[ptype]
-        except KeyError:
-            if ptype[:8] == 'GdkEvent' and ptype[-1] == '*':
-                return self.argtypes['GdkEvent*']
-            raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
-    def _get_reverse_common(self, ptype, registry):
-        props = dict(c_type=ptype)
-        try:
-            return registry[ptype], props
-        except KeyError:
-            try:
-                handler = self.argtypes[ptype]
-            except KeyError:
-                if ptype.startswith('GdkEvent') and ptype.endswith('*'):
-                    handler = self.argtypes['GdkEvent*']
-                else:
-                    raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
-            if isinstance(handler, ObjectArg):
-                return registry['GObject*'], props
-            elif isinstance(handler, EnumArg):
-                props['typecode'] = handler.typecode
-                props['enumname'] = handler.enumname
-                return registry['GEnum'], props
-            elif isinstance(handler, FlagsArg):
-                props['typecode'] = handler.typecode
-                props['flagname'] = handler.flagname
-                return registry['GFlags'], props
-            elif isinstance(handler, BoxedArg):
-                props['typecode'] = handler.typecode
-                props['typename'] = handler.typename
-                return registry['GBoxed'], props
-            else:
-                raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
-
-    def get_reverse(self, ptype):
-        return self._get_reverse_common(ptype, self.reverse_argtypes)
-
-    def get_reverse_ret(self, ptype):
-        ret, props = self._get_reverse_common(ptype, self.reverse_rettypes)
-        if hasattr(ptype, 'optional') and ptype.optional:
-            if ret.supports_optional:
-                props['optional'] = True
-            else:
-                raise ArgTypeNotFoundError("Unsupported 'optional' for %s"
-                                           % (ptype,))
-        return ret, props
-
-    def object_is_a(self, otype, parent):
-        if otype == None: return 0
-        if otype == parent: return 1
-        if not self.argtypes.has_key(otype): return 0
-        return self.object_is_a(self.get(otype).parent, parent)
-
-matcher = ArgMatcher()
-
-arg = NoneArg()
-matcher.register(None, arg)
-matcher.register('none', arg)
-
-arg = StringArg()
-matcher.register('char*', arg)
-matcher.register('gchar*', arg)
-matcher.register('const-char*', arg)
-matcher.register('char-const*', arg)
-matcher.register('const-gchar*', arg)
-matcher.register('gchar-const*', arg)
-matcher.register('string', arg)
-matcher.register('static_string', arg)
-
-arg = UCharArg()
-matcher.register('unsigned-char*', arg)
-matcher.register('const-guchar*', arg)
-matcher.register('const-guint8*', arg)
-matcher.register('guchar*', arg)
-
-arg = CharArg()
-matcher.register('char', arg)
-matcher.register('gchar', arg)
-matcher.register('guchar', arg)
-
-arg = GUniCharArg()
-matcher.register('gunichar', arg)
-
-arg = IntArg()
-matcher.register('int', arg)
-matcher.register('gint', arg)
-matcher.register('short', arg)
-matcher.register('gshort', arg)
-matcher.register('gushort', arg)
-matcher.register('gsize', SizeArg())
-matcher.register('gssize', SSizeArg())
-matcher.register('guint8', arg)
-matcher.register('gint8', arg)
-matcher.register('guint16', arg)
-matcher.register('gint16', arg)
-matcher.register('gint32', arg)
-matcher.register('GTime', arg)
-matcher.register('GSeekType', arg) # Hack, but we have no python wrapper
-
-arg = LongArg()
-matcher.register('long', arg)
-matcher.register('glong', arg)
-
-arg = UIntArg()
-matcher.register('guint', arg)
-
-arg = BoolArg()
-matcher.register('gboolean', arg)
-
-arg = TimeTArg()
-matcher.register('time_t', arg)
-
-matcher.register('guint32', UInt32Arg())
-
-arg = ULongArg()
-matcher.register('gulong', arg)
-
-arg = Int64Arg()
-matcher.register('gint64', arg)
-matcher.register('long-long', arg)
-matcher.register('goffset', arg)
-
-arg = UInt64Arg()
-matcher.register('guint64', arg)
-matcher.register('unsigned-long-long', arg)
-
-arg = DoubleArg()
-matcher.register('double', arg)
-matcher.register('gdouble', arg)
-matcher.register('float', arg)
-matcher.register('gfloat', arg)
-
-arg = FileArg()
-matcher.register('FILE*', arg)
-
-# enums, flags, objects
-
-matcher.register('GdkAtom', AtomArg())
-
-matcher.register('GType', GTypeArg())
-matcher.register('GtkType', GTypeArg())
-
-matcher.register('GError**', GErrorArg())
-matcher.register('GtkTreePath*', GtkTreePathArg())
-matcher.register('GdkRectangle*', GdkRectanglePtrArg())
-matcher.register('GtkAllocation*', GdkRectanglePtrArg())
-matcher.register('GdkRectangle', GdkRectangleArg())
-matcher.register('PyObject*', PyObjectArg())
-
-matcher.register('GdkNativeWindow', ULongArg())
-
-matcher.register_object('GObject', None, 'G_TYPE_OBJECT')
-
-del arg
-
-matcher.register('cairo_t*', CairoArg())
-matcher.register_boxed("GClosure", "G_TYPE_CLOSURE")
diff --git a/codegen/code-coverage.py b/codegen/code-coverage.py
index fd15034..1f1803f 100755
--- a/codegen/code-coverage.py
+++ b/codegen/code-coverage.py
@@ -36,7 +36,7 @@ def main():
     for symbol in read_symbols(library, type='T', dynamic=1):
         if symbol[0] == '_': continue
         if symbol not in wrapper_symbols:
-            print symbol
+            sys.stdout.write("%s\n" % symbol)
 
 if __name__ == '__main__':
     main()
diff --git a/codegen/codegen.py b/codegen/codegen.py
index ab9153c..3666740 100644
--- a/codegen/codegen.py
+++ b/codegen/codegen.py
@@ -4,11 +4,8 @@ import os
 import string
 import sys
 
-import argtypes
-import definitions
-import defsparser
-import override
-import reversewrapper
+from libcodegen import argtypes, definitions, defsparser, override, \
+     reversewrapper
 import warnings
 
 class Coverage(object):
@@ -94,8 +91,7 @@ class FileOutput:
 class Wrapper:
     type_tmpl = (
         'PyTypeObject G_GNUC_INTERNAL Py%(typename)s_Type = {\n'
-        '    PyObject_HEAD_INIT(NULL)\n'
-        '    0,                                 /* ob_size */\n'
+        '    PyVarObject_HEAD_INIT(NULL, 0)\n'
         '    "%(classname)s",                   /* tp_name */\n'
         '    sizeof(%(tp_basicsize)s),          /* tp_basicsize */\n'
         '    0,                                 /* tp_itemsize */\n'
@@ -104,7 +100,11 @@ class Wrapper:
         '    (printfunc)0,                      /* tp_print */\n'
         '    (getattrfunc)%(tp_getattr)s,       /* tp_getattr */\n'
         '    (setattrfunc)%(tp_setattr)s,       /* tp_setattr */\n'
+        '#if PY_VERSION_HEX < 0x03000000\n'
         '    (cmpfunc)%(tp_compare)s,           /* tp_compare */\n'
+        '#else\n'
+        '    NULL,\n'
+        '#endif\n'
         '    (reprfunc)%(tp_repr)s,             /* tp_repr */\n'
         '    (PyNumberMethods*)%(tp_as_number)s,     /* tp_as_number */\n'
         '    (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n'
@@ -265,7 +265,7 @@ class Wrapper:
         self.fp.write('\n/* ----------- %s ----------- */\n\n' %
                       self.objinfo.c_name)
         substdict = self.get_initial_class_substdict()
-        if not substdict.has_key('tp_flags'):
+        if 'tp_flags' not in substdict:
             substdict['tp_flags'] = 'Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE'
         substdict['typename'] = self.objinfo.c_name
         if self.overrides.modulename:
@@ -295,7 +295,7 @@ class Wrapper:
                 self.write_function(slotname, data)
                 substdict[slot] = slotfunc
             else:
-                if not substdict.has_key(slot):
+                if slot not in substdict:
                     substdict[slot] = '0'
 
         self.fp.write(self.type_tmpl % substdict)
@@ -423,7 +423,8 @@ class Wrapper:
                     constructor))[0]
                 self.fp.write(code)
             initfunc = '_wrap_' + funcname
-        except argtypes.ArgTypeError, ex:
+        except argtypes.ArgTypeError:
+            exc_class, ex, tb = sys.exc_info()
             sys.stderr.write('Could not write constructor for %s: %s\n'
                              % (self.objinfo.c_name, str(ex)))
 
@@ -500,7 +501,8 @@ class Wrapper:
                                  'flags': methflags,
                                  'docstring': meth.docstring })
                 methods_coverage.declare_wrapped()
-            except argtypes.ArgTypeError, ex:
+            except argtypes.ArgTypeError:
+                exc_class, ex, tb = sys.exc_info()
                 methods_coverage.declare_not_wrapped()
                 sys.stderr.write('Could not write method %s.%s: %s\n'
                                 % (klass, meth.name, str(ex)))
@@ -522,7 +524,8 @@ class Wrapper:
                                  'flags': methflags,
                                  'docstring': 'NULL' })
                 methods_coverage.declare_wrapped()
-            except argtypes.ArgTypeError, ex:
+            except argtypes.ArgTypeError:
+                exc_class, ex, tb = sys.exc_info()
                 methods_coverage.declare_not_wrapped()
                 sys.stderr.write('Could not write method %s.%s: %s\n'
                                 % (klass, method_name, str(ex)))
@@ -576,7 +579,8 @@ class Wrapper:
                                  'flags': methflags + '|METH_CLASS',
                                  'docstring': 'NULL'})
                 vaccessors_coverage.declare_wrapped()
-            except argtypes.ArgTypeError, ex:
+            except argtypes.ArgTypeError:
+                exc_class, ex, tb = sys.exc_info()
                 vaccessors_coverage.declare_not_wrapped()
                 sys.stderr.write(
                     'Could not write virtual accessor method %s.%s: %s\n'
@@ -619,7 +623,8 @@ class Wrapper:
                     self.fp.write(buf.flush())
                 virtuals.append((fixname(meth.name), '_wrap_' + method_name))
                 vproxies_coverage.declare_wrapped()
-            except argtypes.ArgTypeError, ex:
+            except argtypes.ArgTypeError:
+                exc_class, ex, tb = sys.exc_info()
                 vproxies_coverage.declare_not_wrapped()
                 virtuals.append((fixname(meth.name), None))
                 sys.stderr.write('Could not write virtual proxy %s.%s: %s\n'
@@ -707,7 +712,8 @@ class Wrapper:
                                     'field': self.get_field_accessor(cfname),
                                     'codeafter': info.get_codeafter() })
                     gettername = funcname
-                except argtypes.ArgTypeError, ex:
+                except argtypes.ArgTypeError:
+                    exc_class, ex, tb = sys.exc_info()
                     sys.stderr.write(
                         "Could not write getter for %s.%s: %s\n"
                         % (self.objinfo.c_name, fname, str(ex)))
@@ -734,19 +740,19 @@ _wrap__get_symbol_names(PyObject *self)
 """)
         for obj, bases in writer.get_classes():
             self.fp.write('    PyList_Append(pylist, '
-                          'PyString_FromString("%s"));\n' % (obj.name))
+                          '_PyUnicode_FromString("%s"));\n' % (obj.name))
 
         for name, cname, flags, docstring in functions:
             self.fp.write('    PyList_Append(pylist, '
-                          'PyString_FromString("%s"));\n' % (name))
+                          '_PyUnicode_FromString("%s"));\n' % (name))
 
         for enum in writer.get_enums():
             self.fp.write('    PyList_Append(pylist, '
-                          'PyString_FromString("%s"));\n' % (enum.name))
+                          '_PyUnicode_FromString("%s"));\n' % (enum.name))
             for nick, value in enum.values:
                 name = value[len(self.overrides.modulename)+1:]
                 self.fp.write('    PyList_Append(pylist, '
-                              'PyString_FromString("%s"));\n' % (name))
+                              '_PyUnicode_FromString("%s"));\n' % (name))
 
         self.fp.write("    return pylist;\n}\n\n");
 
@@ -764,7 +770,7 @@ _wrap__get_symbol(PyObject *self, PyObject *args)
         return NULL;
 
     if (!modulename)
-       modulename = PyString_FromString("%s");
+       modulename = _PyUnicode_FromString("%s");
 
     if (!module)
        module = PyDict_GetItemString(d, "__module__");
@@ -847,7 +853,8 @@ _wrap__get_symbol(PyObject *self, PyObject *args)
                 functions.append((func.name, '_wrap_' + funcname,
                                   methflags, func.docstring))
                 functions_coverage.declare_wrapped()
-            except argtypes.ArgTypeError, ex:
+            except argtypes.ArgTypeError:
+                exc_class, ex, tb = sys.exc_info()
                 functions_coverage.declare_not_wrapped()
                 sys.stderr.write('Could not write function %s: %s\n'
                                  % (func.name, str(ex)))
@@ -861,7 +868,8 @@ _wrap__get_symbol(PyObject *self, PyObject *args)
                 functions.append((funcname, '_wrap_' + funcname,
                                   methflags, 'NULL'))
                 functions_coverage.declare_wrapped()
-            except argtypes.ArgTypeError, ex:
+            except argtypes.ArgTypeError:
+                exc_class, ex, tb = sys.exc_info()
                 functions_coverage.declare_not_wrapped()
                 sys.stderr.write('Could not write function %s: %s\n'
                                  % (funcname, str(ex)))
@@ -990,17 +998,16 @@ class GObjectWrapper(Wrapper):
     def write_property_based_constructor(self, constructor):
         self.objinfo.has_new_constructor_api = True
         out = self.fp
-        print >> out, "static int"
-        print >> out, '_wrap_%s(PyGObject *self, PyObject *args,' \
-              ' PyObject *kwargs)\n{' % constructor.c_name
+        out.write("static int\n")
+        out.write('_wrap_%s(PyGObject *self, PyObject *args,' \
+                  ' PyObject *kwargs)\n{\n' % constructor.c_name)
         if constructor.params:
-            s = "    GType obj_type = pyg_type_from_object((PyObject *) self);"
-            print >> out, s
+            s = "    GType obj_type = pyg_type_from_object((PyObject *) self);\n"
+            out.write(s)
 
         def py_str_list_to_c(arg):
             if arg:
-                return "{" + ", ".join(
-                    map(lambda s: '"' + s + '"', arg)) + ", NULL }"
+                return "{" + ", ".join(['"%s"' % s for s in arg ]) + ", NULL }"
             else:
                 return "{ NULL }"
 
@@ -1020,21 +1027,19 @@ class GObjectWrapper(Wrapper):
             [param.pname
              for param in mandatory_arguments + optional_arguments])
 
-            print >> out, "    GParameter params[%i];" % \
-                  len(constructor.params)
-            print >> out, "    PyObject *parsed_args[%i] = {NULL, };" % \
-                  len(constructor.params)
-            print >> out, "    char *arg_names[] = %s;" % arg_names
-            print >> out, "    char *prop_names[] = %s;" % prop_names
-            print >> out, "    guint nparams, i;"
-            print >> out
+            out.write("    GParameter params[%i];\n" % len(constructor.params))
+            out.write("    PyObject *parsed_args[%i] = {NULL, };\n" % len(constructor.params))
+            out.write("    char *arg_names[] = %s;\n" % arg_names)
+            out.write("    char *prop_names[] = %s;\n" % prop_names)
+            out.write("    guint nparams, i;\n\n")
+
             if constructor.deprecated is not None:
                 out.write(
                     '    if (PyErr_Warn(PyExc_DeprecationWarning, '
                     '"%s") < 0)\n' %
                     constructor.deprecated)
-                print >> out, '        return -1;'
-                print >> out
+                out.write('        return -1;\n\n')
+
             out.write("    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ")
             template = '"'
             if mandatory_arguments:
@@ -1042,9 +1047,9 @@ class GObjectWrapper(Wrapper):
             if optional_arguments:
                 template += "|" + "O"*len(optional_arguments)
             template += ':%s.__init__"' % classname
-            print >> out, template, ", arg_names",
+            out.write("%s, arg_names" % template)
             for i in range(len(constructor.params)):
-                print >> out, ", &parsed_args[%i]" % i,
+                out.write(", &parsed_args[%i]" % i)
 
             out.write(
                 "))\n"
@@ -1086,7 +1091,7 @@ class GObjectWrapper(Wrapper):
             '    }\n' % classname)
 
         if not constructor.caller_owns_return:
-            print >> out, "    g_object_ref(self->obj);\n"
+            out.write("    g_object_ref(self->obj);\n")
 
         out.write(
             '    return 0;\n'
@@ -1172,7 +1177,8 @@ class GInterfaceWrapper(GObjectWrapper):
                     self.fp.write(buf.flush())
                 proxies.append((fixname(meth.name), '_wrap_' + method_name))
                 iproxies_coverage.declare_wrapped()
-            except argtypes.ArgTypeError, ex:
+            except argtypes.ArgTypeError:
+                exc_class, ex, tb = sys.exc_info()
                 iproxies_coverage.declare_not_wrapped()
                 proxies.append((fixname(meth.name), None))
                 sys.stderr.write('Could not write interface proxy %s.%s: %s\n'
@@ -1367,6 +1373,7 @@ typedef intargfunc ssizeargfunc;
 typedef intobjargproc ssizeobjargproc;
 #endif
 
+#include <pyglib.h>
 ''')
         self.fp.write(self.overrides.get_headers())
         self.fp.resetline()
@@ -1615,10 +1622,10 @@ typedef intobjargproc ssizeobjargproc;
                 indent_str + 'pyg_set_object_has_new_constructor(%s);\n' %
                 obj.typecode)
         else:
-            print >> sys.stderr, (
+            sys.stderr.write(
                 "Warning: Constructor for %s needs to be updated to new API\n"
                 "         See http://live.gnome.org/PyGTK_2fWhatsNew28"
-                "#update-constructors") % obj.c_name
+                "#update-constructors\n" % obj.c_name)
 
         if obj.class_init_func is not None:
             self.fp.write(
@@ -1680,8 +1687,7 @@ def main(argv):
         elif opt == '--errorfilename':
             errorfilename = arg
         elif opt in ('-t', '--load-types'):
-            globals = {}
-            execfile(arg, globals)
+            os.spawnlp(os.P_WAIT, sys.executable, sys.executable, arg)
         elif opt == '-D':
             nameval = arg.split('=')
             try:
@@ -1693,7 +1699,7 @@ def main(argv):
         elif opt == '--py_ssize_t-clean':
             py_ssize_t_clean = True
     if len(args) < 1:
-        print >> sys.stderr, usage
+        sys.stderr.write("%s\n" % usage)
         return 1
     if errorfilename:
         sys.stderr = open(errorfilename, "w")
diff --git a/codegen/definitions.py b/codegen/definitions.py
deleted file mode 100644
index 88b6cdb..0000000
--- a/codegen/definitions.py
+++ /dev/null
@@ -1,567 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-import copy
-import sys
-
-def get_valid_scheme_definitions(defs):
-    return [x for x in defs if isinstance(x, tuple) and len(x) >= 2]
-
-def unescape(s):
-    s = s.replace('\r\n', '\\r\\n').replace('\t', '\\t')
-    return s.replace('\r', '\\r').replace('\n', '\\n')
-
-def make_docstring(lines):
-    return "(char *) " + '\n'.join(['"%s"' % unescape(s) for s in lines])
-
-# New Parameter class, wich emulates a tuple for compatibility reasons
-class Parameter(object):
-    def __init__(self, ptype, pname, pdflt, pnull, pdir=None):
-        self.ptype = ptype
-        self.pname = pname
-        self.pdflt = pdflt
-        self.pnull = pnull
-        self.pdir = pdir
-
-    def __len__(self): return 4
-    def __getitem__(self, i):
-        return (self.ptype, self.pname, self.pdflt, self.pnull)[i]
-
-    def merge(self, old):
-        if old.pdflt is not None:
-            self.pdflt = old.pdflt
-        if old.pnull is not None:
-            self.pnull = old.pnull
-
-# We currently subclass 'str' to make impact on the rest of codegen as
-# little as possible.  Later we can subclass 'object' instead, but
-# then we must find and adapt all places which expect return types to
-# be strings.
-class ReturnType(str):
-    def __new__(cls, *args, **kwds):
-        return str.__new__(cls, *args[:1])
-    def __init__(self, type_name, optional=False):
-        str.__init__(self)
-        self.optional = optional
-
-# Parameter for property based constructors
-class Property(object):
-    def __init__(self, pname, optional, argname):
-        self.pname = pname
-        self.optional = optional
-        self.argname = argname
-
-    def __len__(self): return 4
-    def __getitem__(self, i):
-        return ('', self.pname, self.optional, self.argname)[i]
-
-    def merge(self, old):
-        if old.optional is not None:
-            self.optional = old.optional
-        if old.argname is not None:
-            self.argname = old.argname
-
-
-class Definition:
-    docstring = "NULL"
-    def __init__(self, *args):
-        """Create a new defs object of this type.  The arguments are the
-        components of the definition"""
-        raise RuntimeError, "this is an abstract class"
-    def merge(self, old):
-        """Merge in customisations from older version of definition"""
-        raise RuntimeError, "this is an abstract class"
-    def write_defs(self, fp=sys.stdout):
-        """write out this definition in defs file format"""
-        raise RuntimeError, "this is an abstract class"
-
-    def guess_return_value_ownership(self):
-        "return 1 if caller owns return value"
-        if getattr(self, 'is_constructor_of', False):
-            self.caller_owns_return = True
-        elif self.ret in ('char*', 'gchar*', 'string'):
-            self.caller_owns_return = True
-        else:
-            self.caller_owns_return = False
-
-
-class ObjectDef(Definition):
-    def __init__(self, name, *args):
-        self.name = name
-        self.module = None
-        self.parent = None
-        self.c_name = None
-        self.typecode = None
-        self.fields = []
-        self.implements = []
-        self.class_init_func = None
-        self.has_new_constructor_api = False
-        for arg in get_valid_scheme_definitions(args):
-            if arg[0] == 'in-module':
-                self.module = arg[1]
-            elif arg[0] == 'docstring':
-                self.docstring = make_docstring(arg[1:])
-            elif arg[0] == 'parent':
-                self.parent = arg[1]
-            elif arg[0] == 'c-name':
-                self.c_name = arg[1]
-            elif arg[0] == 'gtype-id':
-                self.typecode = arg[1]
-            elif arg[0] == 'fields':
-                for parg in arg[1:]:
-                    self.fields.append((parg[0], parg[1]))
-            elif arg[0] == 'implements':
-                self.implements.append(arg[1])
-    def merge(self, old):
-        # currently the .h parser doesn't try to work out what fields of
-        # an object structure should be public, so we just copy the list
-        # from the old version ...
-        self.fields = old.fields
-        self.implements = old.implements
-    def write_defs(self, fp=sys.stdout):
-        fp.write('(define-object ' + self.name + '\n')
-        if self.module:
-            fp.write('  (in-module "' + self.module + '")\n')
-        if self.parent != (None, None):
-            fp.write('  (parent "' + self.parent + '")\n')
-        for interface in self.implements:
-            fp.write('  (implements "' + interface + '")\n')
-        if self.c_name:
-            fp.write('  (c-name "' + self.c_name + '")\n')
-        if self.typecode:
-            fp.write('  (gtype-id "' + self.typecode + '")\n')
-        if self.fields:
-            fp.write('  (fields\n')
-            for (ftype, fname) in self.fields:
-                fp.write('    \'("' + ftype + '" "' + fname + '")\n')
-            fp.write('  )\n')
-        fp.write(')\n\n')
-
-class InterfaceDef(Definition):
-    def __init__(self, name, *args):
-        self.name = name
-        self.module = None
-        self.c_name = None
-        self.typecode = None
-        self.vtable = None
-        self.fields = []
-        self.interface_info = None
-        for arg in get_valid_scheme_definitions(args):
-            if arg[0] == 'in-module':
-                self.module = arg[1]
-            elif arg[0] == 'docstring':
-                self.docstring = make_docstring(arg[1:])
-            elif arg[0] == 'c-name':
-                self.c_name = arg[1]
-            elif arg[0] == 'gtype-id':
-                self.typecode = arg[1]
-            elif arg[0] == 'vtable':
-                self.vtable = arg[1]
-        if self.vtable is None:
-            self.vtable = self.c_name + "Iface"
-    def write_defs(self, fp=sys.stdout):
-        fp.write('(define-interface ' + self.name + '\n')
-        if self.module:
-            fp.write('  (in-module "' + self.module + '")\n')
-        if self.c_name:
-            fp.write('  (c-name "' + self.c_name + '")\n')
-        if self.typecode:
-            fp.write('  (gtype-id "' + self.typecode + '")\n')
-        fp.write(')\n\n')
-
-class EnumDef(Definition):
-    def __init__(self, name, *args):
-        self.deftype = 'enum'
-        self.name = name
-        self.in_module = None
-        self.c_name = None
-        self.typecode = None
-        self.values = []
-        for arg in get_valid_scheme_definitions(args):
-            if arg[0] == 'in-module':
-                self.in_module = arg[1]
-            elif arg[0] == 'c-name':
-                self.c_name = arg[1]
-            elif arg[0] == 'gtype-id':
-                self.typecode = arg[1]
-            elif arg[0] == 'values':
-                for varg in arg[1:]:
-                    self.values.append((varg[0], varg[1]))
-    def merge(self, old):
-        pass
-    def write_defs(self, fp=sys.stdout):
-        fp.write('(define-' + self.deftype + ' ' + self.name + '\n')
-        if self.in_module:
-            fp.write('  (in-module "' + self.in_module + '")\n')
-        fp.write('  (c-name "' + self.c_name + '")\n')
-        fp.write('  (gtype-id "' + self.typecode + '")\n')
-        if self.values:
-            fp.write('  (values\n')
-            for name, val in self.values:
-                fp.write('    \'("' + name + '" "' + val + '")\n')
-            fp.write('  )\n')
-        fp.write(')\n\n')
-
-class FlagsDef(EnumDef):
-    def __init__(self, *args):
-        apply(EnumDef.__init__, (self,) + args)
-        self.deftype = 'flags'
-
-class BoxedDef(Definition):
-    def __init__(self, name, *args):
-        self.name = name
-        self.module = None
-        self.c_name = None
-        self.typecode = None
-        self.copy = None
-        self.release = None
-        self.fields = []
-        for arg in get_valid_scheme_definitions(args):
-            if arg[0] == 'in-module':
-                self.module = arg[1]
-            elif arg[0] == 'c-name':
-                self.c_name = arg[1]
-            elif arg[0] == 'gtype-id':
-                self.typecode = arg[1]
-            elif arg[0] == 'copy-func':
-                self.copy = arg[1]
-            elif arg[0] == 'release-func':
-                self.release = arg[1]
-            elif arg[0] == 'fields':
-                for parg in arg[1:]:
-                    self.fields.append((parg[0], parg[1]))
-    def merge(self, old):
-        # currently the .h parser doesn't try to work out what fields of
-        # an object structure should be public, so we just copy the list
-        # from the old version ...
-        self.fields = old.fields
-    def write_defs(self, fp=sys.stdout):
-        fp.write('(define-boxed ' + self.name + '\n')
-        if self.module:
-            fp.write('  (in-module "' + self.module + '")\n')
-        if self.c_name:
-            fp.write('  (c-name "' + self.c_name + '")\n')
-        if self.typecode:
-            fp.write('  (gtype-id "' + self.typecode + '")\n')
-        if self.copy:
-            fp.write('  (copy-func "' + self.copy + '")\n')
-        if self.release:
-            fp.write('  (release-func "' + self.release + '")\n')
-        if self.fields:
-            fp.write('  (fields\n')
-            for (ftype, fname) in self.fields:
-                fp.write('    \'("' + ftype + '" "' + fname + '")\n')
-            fp.write('  )\n')
-        fp.write(')\n\n')
-
-class PointerDef(Definition):
-    def __init__(self, name, *args):
-        self.name = name
-        self.module = None
-        self.c_name = None
-        self.typecode = None
-        self.fields = []
-        for arg in get_valid_scheme_definitions(args):
-            if arg[0] == 'in-module':
-                self.module = arg[1]
-            elif arg[0] == 'c-name':
-                self.c_name = arg[1]
-            elif arg[0] == 'gtype-id':
-                self.typecode = arg[1]
-            elif arg[0] == 'fields':
-                for parg in arg[1:]:
-                    self.fields.append((parg[0], parg[1]))
-    def merge(self, old):
-        # currently the .h parser doesn't try to work out what fields of
-        # an object structure should be public, so we just copy the list
-        # from the old version ...
-        self.fields = old.fields
-    def write_defs(self, fp=sys.stdout):
-        fp.write('(define-pointer ' + self.name + '\n')
-        if self.module:
-            fp.write('  (in-module "' + self.module + '")\n')
-        if self.c_name:
-            fp.write('  (c-name "' + self.c_name + '")\n')
-        if self.typecode:
-            fp.write('  (gtype-id "' + self.typecode + '")\n')
-        if self.fields:
-            fp.write('  (fields\n')
-            for (ftype, fname) in self.fields:
-                fp.write('    \'("' + ftype + '" "' + fname + '")\n')
-            fp.write('  )\n')
-        fp.write(')\n\n')
-
-class MethodDefBase(Definition):
-    def __init__(self, name, *args):
-        dump = 0
-        self.name = name
-        self.ret = None
-        self.caller_owns_return = None
-        self.unblock_threads = None
-        self.c_name = None
-        self.typecode = None
-        self.of_object = None
-        self.params = [] # of form (type, name, default, nullok)
-        self.varargs = 0
-        self.deprecated = None
-        for arg in get_valid_scheme_definitions(args):
-            if arg[0] == 'of-object':
-                self.of_object = arg[1]
-            elif arg[0] == 'docstring':
-                self.docstring = make_docstring(arg[1:])
-            elif arg[0] == 'c-name':
-                self.c_name = arg[1]
-            elif arg[0] == 'gtype-id':
-                self.typecode = arg[1]
-            elif arg[0] == 'return-type':
-                type_name = arg[1]
-                optional = False
-                for prop in arg[2:]:
-                    if prop[0] == 'optional':
-                        optional = True
-                self.ret = ReturnType(type_name, optional)
-            elif arg[0] == 'caller-owns-return':
-                self.caller_owns_return = arg[1] in ('t', '#t')
-            elif arg[0] == 'unblock-threads':
-                self.unblock_threads = arg[1] in ('t', '#t')
-            elif arg[0] == 'parameters':
-                for parg in arg[1:]:
-                    ptype = parg[0]
-                    pname = parg[1]
-                    pdflt = None
-                    pnull = 0
-                    pdir = None
-                    for farg in parg[2:]:
-                        assert isinstance(farg, tuple)
-                        if farg[0] == 'default':
-                            pdflt = farg[1]
-                        elif farg[0] == 'null-ok':
-                            pnull = 1
-                        elif farg[0] == 'direction':
-                            pdir = farg[1]
-                    self.params.append(Parameter(ptype, pname, pdflt, pnull, pdir))
-            elif arg[0] == 'varargs':
-                self.varargs = arg[1] in ('t', '#t')
-            elif arg[0] == 'deprecated':
-                self.deprecated = arg[1]
-            else:
-                sys.stderr.write("Warning: %s argument unsupported.\n"
-                                 % (arg[0]))
-                dump = 1
-        if dump:
-            self.write_defs(sys.stderr)
-
-        if self.caller_owns_return is None and self.ret is not None:
-            self.guess_return_value_ownership()
-
-    def merge(self, old, parmerge):
-        self.caller_owns_return = old.caller_owns_return
-        self.varargs = old.varargs
-        # here we merge extra parameter flags accross to the new object.
-        if not parmerge:
-            self.params = copy.deepcopy(old.params)
-            return
-        for i in range(len(self.params)):
-            ptype, pname, pdflt, pnull = self.params[i]
-            for p2 in old.params:
-                if p2[1] == pname:
-                    self.params[i] = (ptype, pname, p2[2], p2[3])
-                    break
-    def _write_defs(self, fp=sys.stdout):
-        if self.of_object != (None, None):
-            fp.write('  (of-object "' + self.of_object + '")\n')
-        if self.c_name:
-            fp.write('  (c-name "' + self.c_name + '")\n')
-        if self.typecode:
-            fp.write('  (gtype-id "' + self.typecode + '")\n')
-        if self.caller_owns_return:
-            fp.write('  (caller-owns-return #t)\n')
-        if self.unblock_threads:
-            fp.write('  (unblock_threads #t)\n')
-        if self.ret:
-            fp.write('  (return-type "' + self.ret + '")\n')
-        if self.deprecated:
-            fp.write('  (deprecated "' + self.deprecated + '")\n')
-        if self.params:
-            fp.write('  (parameters\n')
-            for ptype, pname, pdflt, pnull in self.params:
-                fp.write('    \'("' + ptype + '" "' + pname +'"')
-                if pdflt: fp.write(' (default "' + pdflt + '")')
-                if pnull: fp.write(' (null-ok)')
-                fp.write(')\n')
-            fp.write('  )\n')
-        if self.varargs:
-            fp.write('  (varargs #t)\n')
-        fp.write(')\n\n')
-
-
-class MethodDef(MethodDefBase):
-    def __init__(self, name, *args):
-        MethodDefBase.__init__(self, name, *args)
-        for item in ('c_name', 'of_object'):
-            if self.__dict__[item] == None:
-                self.write_defs(sys.stderr)
-                raise RuntimeError, "definition missing required %s" % (item,)
-
-    def write_defs(self, fp=sys.stdout):
-        fp.write('(define-method ' + self.name + '\n')
-        self._write_defs(fp)
-
-class VirtualDef(MethodDefBase):
-    def write_defs(self, fp=sys.stdout):
-        fp.write('(define-virtual ' + self.name + '\n')
-        self._write_defs(fp)
-
-class FunctionDef(Definition):
-    def __init__(self, name, *args):
-        dump = 0
-        self.name = name
-        self.in_module = None
-        self.is_constructor_of = None
-        self.ret = None
-        self.caller_owns_return = None
-        self.unblock_threads = None
-        self.c_name = None
-        self.typecode = None
-        self.params = [] # of form (type, name, default, nullok)
-        self.varargs = 0
-        self.deprecated = None
-        for arg in get_valid_scheme_definitions(args):
-            if arg[0] == 'in-module':
-                self.in_module = arg[1]
-            elif arg[0] == 'docstring':
-                self.docstring = make_docstring(arg[1:])
-            elif arg[0] == 'is-constructor-of':
-                self.is_constructor_of = arg[1]
-            elif arg[0] == 'c-name':
-                self.c_name = arg[1]
-            elif arg[0] == 'gtype-id':
-                self.typecode = arg[1]
-            elif arg[0] == 'return-type':
-                self.ret = arg[1]
-            elif arg[0] == 'caller-owns-return':
-                self.caller_owns_return = arg[1] in ('t', '#t')
-            elif arg[0] == 'unblock-threads':
-                self.unblock_threads = arg[1] in ('t', '#t')
-            elif arg[0] == 'parameters':
-                for parg in arg[1:]:
-                    ptype = parg[0]
-                    pname = parg[1]
-                    pdflt = None
-                    pnull = 0
-                    for farg in parg[2:]:
-                        if farg[0] == 'default':
-                            pdflt = farg[1]
-                        elif farg[0] == 'null-ok':
-                            pnull = 1
-                    self.params.append(Parameter(ptype, pname, pdflt, pnull))
-            elif arg[0] == 'properties':
-                if self.is_constructor_of is None:
-                    print >> sys.stderr, "Warning: (properties ...) "\
-                          "is only valid for constructors"
-                for prop in arg[1:]:
-                    pname = prop[0]
-                    optional = False
-                    argname = pname
-                    for farg in prop[1:]:
-                        if farg[0] == 'optional':
-                            optional = True
-                        elif farg[0] == 'argname':
-                            argname = farg[1]
-                    self.params.append(Property(pname, optional, argname))
-            elif arg[0] == 'varargs':
-                self.varargs = arg[1] in ('t', '#t')
-            elif arg[0] == 'deprecated':
-                self.deprecated = arg[1]
-            else:
-                sys.stderr.write("Warning: %s argument unsupported\n"
-                                 % (arg[0],))
-                dump = 1
-        if dump:
-            self.write_defs(sys.stderr)
-
-        if self.caller_owns_return is None and self.ret is not None:
-            self.guess_return_value_ownership()
-        for item in ('c_name',):
-            if self.__dict__[item] == None:
-                self.write_defs(sys.stderr)
-                raise RuntimeError, "definition missing required %s" % (item,)
-
-    _method_write_defs = MethodDef.__dict__['write_defs']
-
-    def merge(self, old, parmerge):
-        self.caller_owns_return = old.caller_owns_return
-        self.varargs = old.varargs
-        if not parmerge:
-            self.params = copy.deepcopy(old.params)
-            return
-        # here we merge extra parameter flags accross to the new object.
-        def merge_param(param):
-            for old_param in old.params:
-                if old_param.pname == param.pname:
-                    if isinstance(old_param, Property):
-                        # h2def never scans Property's, therefore if
-                        # we have one it was manually written, so we
-                        # keep it.
-                        return copy.deepcopy(old_param)
-                    else:
-                        param.merge(old_param)
-                        return param
-            raise RuntimeError, "could not find %s in old_parameters %r" % (
-                param.pname, [p.pname for p in old.params])
-        try:
-            self.params = map(merge_param, self.params)
-        except RuntimeError:
-            # parameter names changed and we can't find a match; it's
-            # safer to keep the old parameter list untouched.
-            self.params = copy.deepcopy(old.params)
-
-        if not self.is_constructor_of:
-            try:
-                self.is_constructor_of = old.is_constructor_of
-            except AttributeError:
-                pass
-        if isinstance(old, MethodDef):
-            self.name = old.name
-            # transmogrify from function into method ...
-            self.write_defs = self._method_write_defs
-            self.of_object = old.of_object
-            del self.params[0]
-    def write_defs(self, fp=sys.stdout):
-        fp.write('(define-function ' + self.name + '\n')
-        if self.in_module:
-            fp.write('  (in-module "' + self.in_module + '")\n')
-        if self.is_constructor_of:
-            fp.write('  (is-constructor-of "' + self.is_constructor_of +'")\n')
-        if self.c_name:
-            fp.write('  (c-name "' + self.c_name + '")\n')
-        if self.typecode:
-            fp.write('  (gtype-id "' + self.typecode + '")\n')
-        if self.caller_owns_return:
-            fp.write('  (caller-owns-return #t)\n')
-        if self.unblock_threads:
-            fp.write('  (unblock-threads #t)\n')
-        if self.ret:
-            fp.write('  (return-type "' + self.ret + '")\n')
-        if self.deprecated:
-            fp.write('  (deprecated "' + self.deprecated + '")\n')
-        if self.params:
-            if isinstance(self.params[0], Parameter):
-                fp.write('  (parameters\n')
-                for ptype, pname, pdflt, pnull in self.params:
-                    fp.write('    \'("' + ptype + '" "' + pname +'"')
-                    if pdflt: fp.write(' (default "' + pdflt + '")')
-                    if pnull: fp.write(' (null-ok)')
-                    fp.write(')\n')
-                fp.write('  )\n')
-            elif isinstance(self.params[0], Property):
-                fp.write('  (properties\n')
-                for prop in self.params:
-                    fp.write('    \'("' + prop.pname +'"')
-                    if prop.optional: fp.write(' (optional)')
-                    fp.write(')\n')
-                fp.write('  )\n')
-            else:
-                assert False, "strange parameter list %r" % self.params[0]
-        if self.varargs:
-            fp.write('  (varargs #t)\n')
-
-        fp.write(')\n\n')
diff --git a/codegen/defsgen.py b/codegen/defsgen.py
index 670d411..f761db9 100644
--- a/codegen/defsgen.py
+++ b/codegen/defsgen.py
@@ -86,7 +86,7 @@ import os
 import re, string
 import sys
 import ctypes
-import defsparser
+from libcodegen import defsparser
 
 #------------------ utility defs -----------------
 
@@ -409,7 +409,7 @@ class DefsWriter:
     def write_untyped_enum_defs(self, fp):
         fp.write(';; Untyped enumerations and flags ...\n\n')
         filter = self._c_names
-        for cname, (isflags, entries) in self.defs['untypedenums'].items():
+        for cname, (isflags, entries) in list(self.defs['untypedenums'].items()):
             if filter and cname in filter: continue
             module, name = split_prefix(cname, self.prefix, self.use_prefix)
             if isflags:
@@ -656,10 +656,10 @@ def main(args):
                 defines[nameval[0]] = None
 
     if not args[0:1]:
-        print 'Must specify at least one input file name'
+        sys.stdout.write('Must specify at least one input file name\n')
         return -1
     if not modulelibs:
-        print 'Must specify one or more modulelib names'
+        sys.stdout.write('Must specify one or more modulelib names\n')
         return -1
 
     # load the gobject and module libraries and init the gtype system
@@ -723,15 +723,15 @@ def main(args):
     if onlyobjdefs or all:
         dw.write_obj_defs(types)
         if separate:
-            print "Wrote object defs to %s-types.defs" % separate
+            sys.stdout.write("Wrote object defs to %s-types.defs\n" % separate)
     if onlyenums or all:
         dw.write_enum_defs(types)
         if separate:
-            print "Wrote enum and flags defs to %s-types.defs" % separate
+            sys.stdout.write("Wrote enum and flags defs to %s-types.defs\n" % separate)
     if onlyvirtuals or all:
         dw.write_func_defs(args, onlyvirtuals)
         if separate:
-            print "Wrote function and virtual defs to %s.defs" % separate
+            sys.stdout.write("Wrote function and virtual defs to %s.defs\n" % separate)
 
 if __name__ == '__main__':
     sys.exit(main(sys.argv))
diff --git a/codegen/defsparser.py b/codegen/defsparser.py
deleted file mode 100644
index 37ba0a2..0000000
--- a/codegen/defsparser.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-import os, sys
-import scmexpr
-from definitions import BoxedDef, EnumDef, FlagsDef, FunctionDef, \
-     InterfaceDef, MethodDef, ObjectDef, PointerDef, VirtualDef
-
-include_path = ['.']
-
-class IncludeParser(scmexpr.Parser):
-    """A simple parser that follows include statements automatically"""
-    def include(self, input_filename):
-        global include_path
-        if os.path.isabs(input_filename):
-            filename = input_filename
-            # set self.filename to the include name, to handle recursive includes
-            oldfile = self.filename
-            self.filename = filename
-            self.startParsing()
-            self.filename = oldfile
-        else:
-            inc_path = [os.path.dirname(self.filename)] + include_path
-            for filename in [os.path.join(path_entry, input_filename)
-                             for path_entry in inc_path]:
-                if not os.path.exists(filename):
-                    continue
-                # set self.filename to the include name, to handle recursive includes
-                oldfile = self.filename
-                self.filename = filename
-                self.startParsing()
-                self.filename = oldfile
-                break
-            else:
-                raise IOError("%s not found in include path %s" % (input_filename, inc_path))
-
-class DefsParser(IncludeParser):
-    def __init__(self, arg, defines={}):
-        IncludeParser.__init__(self, arg)
-        self.objects = []
-        self.interfaces = []
-        self.enums = []      # enums and flags
-        self.boxes = []      # boxed types
-        self.pointers = []   # pointer types
-        self.functions = []  # functions and methods
-        self.virtuals = []   # virtual methods
-        self.c_name = {}     # hash of c names of functions
-        self.methods = {}    # hash of methods of particular objects
-        self.defines = defines      # -Dfoo=bar options, as dictionary
-
-    def define_object(self, *args):
-        odef = apply(ObjectDef, args)
-        self.objects.append(odef)
-        self.c_name[odef.c_name] = odef
-    def define_interface(self, *args):
-        idef = apply(InterfaceDef, args)
-        self.interfaces.append(idef)
-        self.c_name[idef.c_name] = idef
-    def define_enum(self, *args):
-        edef = apply(EnumDef, args)
-        self.enums.append(edef)
-        self.c_name[edef.c_name] = edef
-    def define_flags(self, *args):
-        fdef = apply(FlagsDef, args)
-        self.enums.append(fdef)
-        self.c_name[fdef.c_name] = fdef
-    def define_boxed(self, *args):
-        bdef = apply(BoxedDef, args)
-        self.boxes.append(bdef)
-        self.c_name[bdef.c_name] = bdef
-    def define_pointer(self, *args):
-        pdef = apply(PointerDef, args)
-        self.pointers.append(pdef)
-        self.c_name[pdef.c_name] = pdef
-    def define_function(self, *args):
-        fdef = apply(FunctionDef, args)
-        self.functions.append(fdef)
-        self.c_name[fdef.c_name] = fdef
-    def define_method(self, *args):
-        mdef = apply(MethodDef, args)
-        self.functions.append(mdef)
-        self.c_name[mdef.c_name] = mdef
-    def define_virtual(self, *args):
-        vdef = apply(VirtualDef, args)
-        self.virtuals.append(vdef)
-    def merge(self, old, parmerge):
-        for obj in self.objects:
-            if old.c_name.has_key(obj.c_name):
-                obj.merge(old.c_name[obj.c_name])
-        for f in self.functions:
-            if old.c_name.has_key(f.c_name):
-                f.merge(old.c_name[f.c_name], parmerge)
-
-    def printMissing(self, old):
-        for obj in self.objects:
-            if not old.c_name.has_key(obj.c_name):
-                obj.write_defs()
-        for f in self.functions:
-            if not old.c_name.has_key(f.c_name):
-                f.write_defs()
-
-    def write_defs(self, fp=sys.stdout):
-        for obj in self.objects:
-            obj.write_defs(fp)
-        for enum in self.enums:
-            enum.write_defs(fp)
-        for boxed in self.boxes:
-            boxed.write_defs(fp)
-        for pointer in self.pointers:
-            pointer.write_defs(fp)
-        for func in self.functions:
-            func.write_defs(fp)
-
-    def find_object(self, c_name):
-        for obj in self.objects:
-            if obj.c_name == c_name:
-                return obj
-        else:
-            raise ValueError('object %r not found' % c_name)
-
-    def find_constructor(self, obj, overrides):
-        for func in self.functions:
-            if isinstance(func, FunctionDef) and \
-               func.is_constructor_of == obj.c_name and \
-               not overrides.is_ignored(func.c_name):
-                return func
-
-    def find_methods(self, obj):
-        objname = obj.c_name
-        return filter(lambda func, on=objname: isinstance(func, MethodDef) and
-                      func.of_object == on, self.functions)
-
-    def find_virtuals(self, obj):
-        objname = obj.c_name
-        retval = filter(lambda func, on=objname: isinstance(func, VirtualDef) and
-                        func.of_object == on, self.virtuals)
-        return retval
-
-    def find_functions(self):
-        return filter(lambda func: isinstance(func, FunctionDef) and
-                      not func.is_constructor_of, self.functions)
-
-    def ifdef(self, *args):
-        if args[0] in self.defines:
-            for arg in args[1:]:
-                #print >> sys.stderr, "-----> Handling conditional definition (%s): %s" % (args[0], arg)
-                self.handle(arg)
-        else:
-            pass
-            #print >> sys.stderr, "-----> Conditional %s is not true" % (args[0],)
-
-    def ifndef(self, *args):
-        if args[0] not in self.defines:
-            for arg in args[1:]:
-                self.handle(arg)
diff --git a/codegen/docextract.py b/codegen/docextract.py
deleted file mode 100644
index e6c6505..0000000
--- a/codegen/docextract.py
+++ /dev/null
@@ -1,185 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-'''Simple module for extracting GNOME style doc comments from C
-sources, so I can use them for other purposes.'''
-
-import sys, os, string, re
-
-__all__ = ['extract']
-
-class FunctionDoc:
-    def __init__(self):
-        self.name = None
-        self.params = []
-        self.description = ''
-        self.ret = ''
-    def set_name(self, name):
-        self.name = name
-    def add_param(self, name, description):
-        if name == '...':
-            name = 'Varargs'
-        self.params.append((name, description))
-    def append_to_last_param(self, extra):
-        self.params[-1] = (self.params[-1][0], self.params[-1][1] + extra)
-    def append_to_named_param(self, name, extra):
-        for i in range(len(self.params)):
-            if self.params[i][0] == name:
-                self.params[i] = (name, self.params[i][1] + extra)
-                return
-        # fall through to adding extra parameter ...
-        self.add_param(name, extra)
-    def append_description(self, extra):
-        self.description = self.description + extra
-    def append_return(self, extra):
-        self.ret = self.ret + extra
-
-    def get_param_description(self, name):
-        for param, description in self.params:
-            if param == name:
-                return description
-        else:
-            return ''
-
-comment_start_pat = re.compile(r'^\s*/\*\*\s')
-comment_end_pat = re.compile(r'^\s*\*+/')
-comment_line_lead = re.compile(r'^\s*\*\s*')
-funcname_pat = re.compile(r'^(\w+)\s*:?')
-return_pat = re.compile(r'^(returns:|return\s+value:|returns\s*)(.*\n?)$',
-                        re.IGNORECASE)
-param_pat = re.compile(r'^@(\S+)\s*:(.*\n?)$')
-
-def parse_file(fp, doc_dict):
-    line = fp.readline()
-    in_comment_block = 0
-    while line:
-        if not in_comment_block:
-            if comment_start_pat.match(line):
-                in_comment_block = 1
-                cur_doc = FunctionDoc()
-                in_description = 0
-                in_return = 0
-            line = fp.readline()
-            continue
-
-        # we are inside a comment block ...
-        if comment_end_pat.match(line):
-            if not cur_doc.name:
-                sys.stderr.write("no function name found in doc comment\n")
-            else:
-                doc_dict[cur_doc.name] = cur_doc
-            in_comment_block = 0
-            line = fp.readline()
-            continue
-
-        # inside a comment block, and not the end of the block ...
-        line = comment_line_lead.sub('', line)
-        if not line: line = '\n'
-
-        if not cur_doc.name:
-            match = funcname_pat.match(line)
-            if match:
-                cur_doc.set_name(match.group(1))
-        elif in_return:
-            match = return_pat.match(line)
-            if match:
-                # assume the last return statement was really part of the
-                # description
-                return_start = match.group(1)
-                cur_doc.ret = match.group(2)
-                cur_doc.description = cur_doc.description + return_start + \
-                                      cur_doc.ret
-            else:
-                cur_doc.append_return(line)
-        elif in_description:
-            if line[:12] == 'Description:':
-                line = line[12:]
-            match = return_pat.match(line)
-            if match:
-                in_return = 1
-                return_start = match.group(1)
-                cur_doc.append_return(match.group(2))
-            else:
-                cur_doc.append_description(line)
-        elif line == '\n':
-            # end of parameters
-            in_description = 1
-        else:
-            match = param_pat.match(line)
-            if match:
-                param = match.group(1)
-                desc = match.group(2)
-                if param == 'returns':
-                    cur_doc.ret = desc
-                else:
-                    cur_doc.add_param(param, desc)
-            else:
-                # must be continuation
-                try:
-                    if param == 'returns':
-                        cur_doc.append_return(line)
-                    else:
-                        cur_doc.append_to_last_param(line)
-                except:
-                    sys.stderr.write('something weird while reading param\n')
-        line = fp.readline()
-
-def parse_dir(dir, doc_dict):
-    for file in os.listdir(dir):
-        if file in ('.', '..'): continue
-        path = os.path.join(dir, file)
-        if os.path.isdir(path):
-            parse_dir(path, doc_dict)
-        if len(file) > 2 and file[-2:] == '.c':
-            parse_file(open(path, 'r'), doc_dict)
-
-def extract(dirs, doc_dict=None):
-    if not doc_dict: doc_dict = {}
-    for dir in dirs:
-        parse_dir(dir, doc_dict)
-    return doc_dict
-
-tmpl_section_pat = re.compile(r'^<!-- ##### (\w+) (\w+) ##### -->$')
-def parse_tmpl(fp, doc_dict):
-    cur_doc = None
-
-    line = fp.readline()
-    while line:
-        match = tmpl_section_pat.match(line)
-        if match:
-            cur_doc = None  # new input shouldn't affect the old doc dict
-            sect_type = match.group(1)
-            sect_name = match.group(2)
-
-            if sect_type == 'FUNCTION':
-                cur_doc = doc_dict.get(sect_name)
-                if not cur_doc:
-                    cur_doc = FunctionDoc()
-                    cur_doc.set_name(sect_name)
-                    doc_dict[sect_name] = cur_doc
-        elif line == '<!-- # Unused Parameters # -->\n':
-            cur_doc = None # don't worry about unused params.
-        elif cur_doc:
-            if line[:10] == '@Returns: ':
-                if string.strip(line[10:]):
-                    cur_doc.append_return(line[10:])
-            elif line[0] == '@':
-                pos = string.find(line, ':')
-                if pos >= 0:
-                    cur_doc.append_to_named_param(line[1:pos], line[pos+1:])
-                else:
-                    cur_doc.append_description(line)
-            else:
-                cur_doc.append_description(line)
-
-        line = fp.readline()
-
-def extract_tmpl(dirs, doc_dict=None):
-    if not doc_dict: doc_dict = {}
-    for dir in dirs:
-        for file in os.listdir(dir):
-            if file in ('.', '..'): continue
-            path = os.path.join(dir, file)
-            if os.path.isdir(path):
-                continue
-            if len(file) > 2 and file[-2:] == '.sgml':
-                parse_tmpl(open(path, 'r'), doc_dict)
-    return doc_dict
diff --git a/codegen/docextract_to_xml.py b/codegen/docextract_to_xml.py
index f8d3bae..f05df56 100755
--- a/codegen/docextract_to_xml.py
+++ b/codegen/docextract_to_xml.py
@@ -11,7 +11,7 @@ import re
 import string
 import sys
 
-import docextract
+from libcodegen import docextract
 
 def escape_text(unescaped_text):
     # Escape every "&" not part of an entity reference
@@ -34,7 +34,8 @@ if __name__ == '__main__':
     try:
         opts, args = getopt.getopt(sys.argv[1:], "d:s:o:",
                                    ["source-dir="])
-    except getopt.error, e:
+    except getopt.error:
+        exc_class, e, tb = sys.exc_info()
         sys.stderr.write('docgen.py: %s\n' % e)
         sys.stderr.write(
             'usage: docgen.py [-s /src/dir]\n')
@@ -55,28 +56,28 @@ if __name__ == '__main__':
 
     if docs:
 
-        print "<root>"
+        sys.stdout.write("<root>\n")
 
-        for name, value in docs.items():
-            print "<function name=\"" + escape_text(name) + "\">"
+        for name, value in list(docs.items()):
+            sys.stdout.write("<function name=\"" + escape_text(name) + "\">\n")
 
-            print "<description>"
+            sys.stdout.write("<description>\n")
             #The value is a docextract.FunctionDoc
-            print escape_text(value.description)
-            print "</description>"
+            sys.stdout.write("%s\n" % escape_text(value.description))
+            sys.stdout.write("</description>\n")
 
              # Loop through the parameters:
-            print "<parameters>"
+            sys.stdout.write("<parameters>\n")
             for name, description in value.params:
-                print "<parameter name=\"" + escape_text(name) + "\">"
-                print "<parameter_description>" + escape_text(description) + "</parameter_description>"
-                print "</parameter>"
+                sys.stdout.write("<parameter name=\"" + escape_text(name) + "\">\n")
+                sys.stdout.write("<parameter_description>" + escape_text(description) + "</parameter_description>\n")
+                sys.stdout.write("</parameter>\n")
 
-            print "</parameters>"
+            sys.stdout.write("</parameters>\n")
 
             # Show the return-type:
-            print "<return>" + escape_text(value.ret) + "</return>"
+            sys.stdout.write("<return>" + escape_text(value.ret) + "</return>\n")
 
-            print "</function>\n"
+            sys.stdout.write("</function>\n\n")
 
-        print "</root>"
+        sys.stdout.write("</root>\n")
diff --git a/codegen/docgen.py b/codegen/docgen.py
index b9e2f67..5fc9045 100644
--- a/codegen/docgen.py
+++ b/codegen/docgen.py
@@ -4,10 +4,7 @@ import os
 import re
 import sys
 
-import definitions
-import defsparser
-import docextract
-import override
+from libcodegen import definitions, defsparser, docextract, override
 
 
 class Node:
@@ -180,9 +177,12 @@ class DocWriter:
                                    self.docs.get(constructor.c_name, None))
             self.close_section()
 
+        def _ignored(meth):
+            return not self.overrides.is_ignored(meth.c_name)
+
         methods = self.parser.find_methods(obj_def)
-        methods = filter(lambda meth, self=self:
-                         not self.overrides.is_ignored(meth.c_name), methods)
+        methods = list(filter(_ignored, methods))
+
         if methods:
             self.write_heading('Methods')
             for method in methods:
@@ -522,8 +522,11 @@ class DocbookDocWriter(DocWriter):
                     self._fp.write('\n')
 
                 indent = indent + '  '
-            node.subclasses.sort(lambda a, b:
-                                 cmp(self.pyname(a.name), self.pyname(b.name)))
+
+            def _sort_func(a, b):
+                return cmp(self.pyname(a.name), self.pyname(b.name))
+            node.subclasses.sort(_sort_func)
+
             for child in node.subclasses:
                 handle_node(child, indent)
 
@@ -731,7 +734,8 @@ def main(args):
         opts, args = getopt.getopt(args[1:], "d:s:o:",
                                    ["defs-file=", "override=", "source-dir=",
                                     "output-prefix="])
-    except getopt.error, e:
+    except getopt.error:
+        exc_class, e, tb = sys.exc_info()
         sys.stderr.write('docgen.py: %s\n' % e)
         sys.stderr.write(
             'usage: docgen.py -d file.defs [-s /src/dir] [-o output-prefix]\n')
diff --git a/codegen/h2def.py b/codegen/h2def.py
index 3ed3642..3fa2de0 100755
--- a/codegen/h2def.py
+++ b/codegen/h2def.py
@@ -16,7 +16,7 @@ import re
 import string
 import sys
 
-import defsparser
+from libcodegen import defsparser
 
 # ------------------ Create typecodes from typenames ---------
 
@@ -287,7 +287,7 @@ class DefsWriter:
         if defsfilter:
             filter = defsparser.DefsParser(defsfilter)
             filter.startParsing()
-            for func in filter.functions + filter.methods.values():
+            for func in filter.functions + list(filter.methods.values()):
                 self._functions[func.c_name] = func
             for obj in filter.objects + filter.boxes + filter.interfaces:
                 self._objects[obj.c_name] = obj
@@ -436,7 +436,7 @@ class DefsWriter:
         self._write_arguments(args)
 
     def _write_method(self, obj, name, ret, args):
-        regex = string.join(map(lambda x: x+'_?', string.lower(obj)),'')
+        regex = string.join([x+'_?' for x in string.lower(obj)],'')
         mname = re.sub(regex, '', name, 1)
         if self.prefix:
             l = len(self.prefix) + 1
@@ -502,7 +502,7 @@ def main(args):
             defsfilter = v
 
     if not args[0:1]:
-        print 'Must specify at least one input file name'
+        sys.stdout.write('Must specify at least one input file name\n')
         return -1
 
     # read all the object definitions in
@@ -522,11 +522,11 @@ def main(args):
                         defsfilter=defsfilter)
         dw.write_obj_defs(objdefs, types)
         dw.write_enum_defs(enums, types)
-        print "Wrote %s-types.defs" % separate
+        sys.stdout.write("Wrote %s-types.defs\n" % separate)
 
         for filename in args:
             dw.write_def(filename)
-        print "Wrote %s.defs" % separate
+        sys.stdout.write("Wrote %s.defs\nn" % separate)
     else:
         dw = DefsWriter(prefix=modulename, verbose=verbose,
                         defsfilter=defsfilter)
diff --git a/codegen/libcodegen/Makefile.am b/codegen/libcodegen/Makefile.am
new file mode 100644
index 0000000..d67a4ba
--- /dev/null
+++ b/codegen/libcodegen/Makefile.am
@@ -0,0 +1,14 @@
+PLATFORM_VERSION = 2.0
+libcodegendir = $(pkgdatadir)/$(PLATFORM_VERSION)/codegen/libcodegen
+
+libcodegen_PYTHON = \
+	__init__.py \
+	argtypes.py \
+	reversewrapper.py \
+	definitions.py \
+	defsparser.py \
+	docextract.py \
+	override.py \
+	scmexpr.py \
+	string_compat.py
+
diff --git a/codegen/libcodegen/__init__.py b/codegen/libcodegen/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/codegen/libcodegen/argtypes.py b/codegen/libcodegen/argtypes.py
new file mode 100644
index 0000000..a6ddb91
--- /dev/null
+++ b/codegen/libcodegen/argtypes.py
@@ -0,0 +1,1043 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+from libcodegen.string_compat import string
+import keyword
+import struct
+
+py_ssize_t_clean = False
+
+class ArgTypeError(Exception):
+    pass
+
+class ArgTypeNotFoundError(ArgTypeError):
+    pass
+
+class ArgTypeConfigurationError(ArgTypeError):
+    pass
+
+
+class VarList:
+    """Nicely format a C variable list"""
+    def __init__(self):
+        self.vars = {}
+    def add(self, ctype, name):
+        if ctype in self.vars:
+            self.vars[ctype] = self.vars[ctype] + (name,)
+        else:
+            self.vars[ctype] = (name,)
+    def __str__(self):
+        ret = []
+        for type in list(self.vars.keys()):
+            ret.append('    ')
+            ret.append(type)
+            ret.append(' ')
+            ret.append(string.join(self.vars[type], ', '))
+            ret.append(';\n')
+        if ret:
+            ret.append('\n')
+            return string.join(ret, '')
+        return ''
+
+class WrapperInfo:
+    """A class that holds information about variable defs, code
+    snippets, etcd for use in writing out the function/method
+    wrapper."""
+    def __init__(self):
+        self.varlist = VarList()
+        self.parsestr = ''
+        self.parselist = ['', 'kwlist']
+        self.codebefore = []
+        self.codeafter = []
+        self.arglist = []
+        self.kwlist = []
+    def get_parselist(self):
+        return string.join(self.parselist, ', ')
+    def get_codebefore(self):
+        return string.join(self.codebefore, '')
+    def get_codeafter(self):
+        return string.join(self.codeafter, '')
+    def get_arglist(self):
+        return string.join(self.arglist, ', ')
+    def get_varlist(self):
+        return str(self.varlist)
+    def get_kwlist(self):
+        ret = '    static char *kwlist[] = { %s };\n' % \
+              string.join(self.kwlist + [ 'NULL' ], ', ')
+        if not self.get_varlist():
+            ret = ret + '\n'
+        return ret
+
+    def add_parselist(self, codes, parseargs, keywords):
+        self.parsestr = self.parsestr + codes
+        for arg in parseargs:
+            self.parselist.append(arg)
+        for kw in keywords:
+            if keyword.iskeyword(kw):
+                kw = kw + '_'
+            self.kwlist.append('"%s"' % kw)
+
+class ArgType:
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        """Add code to the WrapperInfo instance to handle
+        parameter."""
+        raise RuntimeError("write_param not implemented for %s" % \
+              self.__class__.__name__)
+    def write_return(self, ptype, ownsreturn, info):
+        """Adds a variable named ret of the return type to
+        info.varlist, and add any required code to info.codeafter to
+        convert the return value to a python object."""
+        raise RuntimeError("write_return not implemented for %s" % \
+              self.__class__.__name__)
+
+class NoneArg(ArgType):
+    def write_return(self, ptype, ownsreturn, info):
+        info.codeafter.append('    Py_INCREF(Py_None);\n' +
+                              '    return Py_None;')
+
+class StringArg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt != None:
+            if pdflt != 'NULL': pdflt = '"' + pdflt + '"'
+            info.varlist.add('char', '*' + pname + ' = ' + pdflt)
+        else:
+            info.varlist.add('char', '*' + pname)
+        info.arglist.append(pname)
+        if pnull:
+            info.add_parselist('z', ['&' + pname], [pname])
+        else:
+            info.add_parselist('s', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        if ownsreturn:
+            # have to free result ...
+            info.varlist.add('gchar', '*ret')
+            info.codeafter.append('    if (ret) {\n' +
+                                  '        PyObject *py_ret = _PyUnicode_FromString(ret);\n' +
+                                  '        g_free(ret);\n' +
+                                  '        return py_ret;\n' +
+                                  '    }\n' +
+                                  '    Py_INCREF(Py_None);\n' +
+                                  '    return Py_None;')
+        else:
+            info.varlist.add('const gchar', '*ret')
+            info.codeafter.append('    if (ret)\n' +
+                                  '        return _PyUnicode_FromString(ret);\n'+
+                                  '    Py_INCREF(Py_None);\n' +
+                                  '    return Py_None;')
+
+class UCharArg(ArgType):
+    # allows strings with embedded NULLs.
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('guchar', '*' + pname + ' = "' + pdflt + '"')
+        else:
+            info.varlist.add('guchar', '*' + pname)
+        if py_ssize_t_clean:
+            info.varlist.add('Py_ssize_t', pname + '_len')
+        else:
+            info.varlist.add('int', pname + '_len')
+        info.arglist.append(pname)
+        if pnull:
+            info.add_parselist('z#', ['&' + pname, '&' + pname + '_len'],
+                               [pname])
+        else:
+            info.add_parselist('s#', ['&' + pname, '&' + pname + '_len'],
+                               [pname])
+
+class CharArg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('char', pname + " = '" + pdflt + "'")
+        else:
+            info.varlist.add('char', pname)
+        info.arglist.append(pname)
+        info.add_parselist('c', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('gchar', 'ret')
+        info.codeafter.append('    return _PyUnicode_FromStringAndSize(&ret, 1);')
+class GUniCharArg(ArgType):
+    ret_tmpl = ('#if !defined(Py_UNICODE_SIZE) || Py_UNICODE_SIZE == 2\n'
+                '    if (ret > 0xffff) {\n'
+                '        PyErr_SetString(PyExc_RuntimeError, "returned character can not be represented in 16-bit unicode");\n'
+                '        return NULL;\n'
+                '    }\n'
+                '#endif\n'
+                '    py_ret = (Py_UNICODE)ret;\n'
+                '    return PyUnicode_FromUnicode(&py_ret, 1);\n')
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('gunichar', pname + " = '" + pdflt + "'")
+        else:
+            info.varlist.add('gunichar', pname)
+        info.arglist.append(pname)
+        info.add_parselist('O&', ['pyg_pyobj_to_unichar_conv', '&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('gunichar', 'ret')
+        info.varlist.add('Py_UNICODE', 'py_ret')
+        info.codeafter.append(self.ret_tmpl)
+
+
+class IntArg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('int', pname + ' = ' + pdflt)
+        else:
+            info.varlist.add('int', pname)
+        info.arglist.append(pname)
+        info.add_parselist('i', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('int', 'ret')
+        info.codeafter.append('    return _PyLong_FromLong(ret);')
+
+class UIntArg(ArgType):
+    dflt = ('    if (py_%(name)s) {\n'
+            '        if (PyLong_Check(py_%(name)s))\n'
+            '            %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
+            '        else if (_PyLong_Check(py_%(name)s))\n'
+            '            %(name)s = _PyLong_AsLong(py_%(name)s);\n'
+            '        else\n'
+            '            PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
+            '        if (PyErr_Occurred())\n'
+            '            return NULL;\n'
+            '    }\n')
+    before = ('    if (PyLong_Check(py_%(name)s))\n'
+              '        %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
+              '    else if (_PyLong_Check(py_%(name)s))\n'
+              '        %(name)s = _PyLong_AsLong(py_%(name)s);\n'
+              '    else\n'
+              '        PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
+              '    if (PyErr_Occurred())\n'
+              '        return NULL;\n')
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if not pdflt:
+            pdflt = '0';
+
+        info.varlist.add(ptype, pname + ' = ' + pdflt)
+        info.codebefore.append(self.dflt % {'name':pname})
+        info.varlist.add('PyObject', "*py_" + pname + ' = NULL')
+        info.arglist.append(pname)
+        info.add_parselist('O', ['&py_' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add(ptype, 'ret')
+        info.codeafter.append('    return PyLong_FromUnsignedLong(ret);')
+
+class SizeArg(ArgType):
+
+    if struct.calcsize('P') <= struct.calcsize('l'):
+        llp64 = True
+    else:
+        llp64 = False
+
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add(ptype, pname + ' = ' + pdflt)
+        else:
+            info.varlist.add(ptype, pname)
+        info.arglist.append(pname)
+        if self.llp64:
+            info.add_parselist('k', ['&' + pname], [pname])
+        else:
+            info.add_parselist('K', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add(ptype, 'ret')
+        if self.llp64:
+            info.codeafter.append('    return PyLong_FromUnsignedLongLong(ret);\n')
+        else:
+            info.codeafter.append('    return PyLong_FromUnsignedLong(ret);\n')
+
+class SSizeArg(ArgType):
+
+    if struct.calcsize('P') <= struct.calcsize('l'):
+        llp64 = True
+    else:
+        llp64 = False
+
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add(ptype, pname + ' = ' + pdflt)
+        else:
+            info.varlist.add(ptype, pname)
+        info.arglist.append(pname)
+        if self.llp64:
+            info.add_parselist('l', ['&' + pname], [pname])
+        else:
+            info.add_parselist('L', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add(ptype, 'ret')
+        if self.llp64:
+            info.codeafter.append('    return PyLong_FromLongLong(ret);\n')
+        else:
+            info.codeafter.append('    return PyLong_FromLong(ret);\n')
+
+class LongArg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add(ptype, pname + ' = ' + pdflt)
+        else:
+            info.varlist.add(ptype, pname)
+        info.arglist.append(pname)
+        info.add_parselist('l', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add(ptype, 'ret')
+        info.codeafter.append('    return _PyLong_FromLong(ret);\n')
+
+class BoolArg(IntArg):
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('int', 'ret')
+        info.codeafter.append('    return PyBool_FromLong(ret);\n')
+
+class TimeTArg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('time_t', pname + ' = ' + pdflt)
+        else:
+            info.varlist.add('time_t', pname)
+        info.arglist.append(pname)
+        info.add_parselist('i', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('time_t', 'ret')
+        info.codeafter.append('    return _PyLong_FromLong(ret);')
+
+class ULongArg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('unsigned long', pname + ' = ' + pdflt)
+        else:
+            info.varlist.add('unsigned long', pname)
+        info.arglist.append(pname)
+        info.add_parselist('k', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add(ptype, 'ret')
+        info.codeafter.append('    return PyLong_FromUnsignedLong(ret);\n')
+
+class UInt32Arg(ULongArg):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        ULongArg.write_param(self, ptype, pname, pdflt, pnull, info)
+        ## if sizeof(unsigned long) > sizeof(unsigned int), we need to
+        ## check the value is within guint32 range
+        if struct.calcsize('L') > struct.calcsize('I'):
+            info.codebefore.append((
+                '    if (%(pname)s > G_MAXUINT32) {\n'
+                '        PyErr_SetString(PyExc_ValueError,\n'
+                '                        "Value out of range in conversion of"\n'
+                '                        " %(pname)s parameter to unsigned 32 bit integer");\n'
+                '        return NULL;\n'
+                '    }\n') % vars())
+
+class Int64Arg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('gint64', pname + ' = ' + pdflt)
+        else:
+            info.varlist.add('gint64', pname)
+        info.arglist.append(pname)
+        info.add_parselist('L', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('gint64', 'ret')
+        info.codeafter.append('    return PyLong_FromLongLong(ret);')
+
+class UInt64Arg(ArgType):
+    dflt = '    if (py_%(name)s)\n' \
+           '        %(name)s = PyLong_AsUnsignedLongLong(py_%(name)s);\n'
+    before = '    %(name)s = PyLong_AsUnsignedLongLong(py_%(name)s);\n'
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('guint64', pname + ' = ' + pdflt)
+            info.codebefore.append(self.dflt % {'name':pname})
+        else:
+            info.varlist.add('guint64', pname)
+            info.codebefore.append(self.before % {'name':pname})
+        info.varlist.add('PyObject', "*py_" + pname + ' = NULL')
+        info.arglist.append(pname)
+        info.add_parselist('O!', ['&PyLong_Type', '&py_' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('guint64', 'ret')
+        info.codeafter.append('    return PyLong_FromUnsignedLongLong(ret);')
+
+
+class DoubleArg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('double', pname + ' = ' + pdflt)
+        else:
+            info.varlist.add('double', pname)
+        info.arglist.append(pname)
+        info.add_parselist('d', ['&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('double', 'ret')
+        info.codeafter.append('    return PyFloat_FromDouble(ret);')
+
+class FileArg(ArgType):
+    nulldflt = ('    if (py_%(name)s == Py_None)\n'
+                '        %(name)s = NULL;\n'
+                '    else if (py_%(name)s && PyFile_Check(py_%(name)s)\n'
+                '        %s = PyFile_AsFile(py_%(name)s);\n'
+                '    else if (py_%(name)s) {\n'
+                '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n'
+                '        return NULL;\n'
+                '    }')
+    null = ('    if (py_%(name)s && PyFile_Check(py_%(name)s)\n'
+            '        %(name)s = PyFile_AsFile(py_%(name)s);\n'
+            '    else if (py_%(name)s != Py_None) {\n'
+            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n'
+            '        return NULL;\n'
+            '    }\n')
+    dflt = ('    if (py_%(name)s)\n'
+            '        %(name)s = PyFile_AsFile(py_%(name)s);\n')
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pnull:
+            if pdflt:
+                info.varlist.add('FILE', '*' + pname + ' = ' + pdflt)
+                info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
+                info.codebefore.append(self.nulldflt % {'name':pname})
+            else:
+                info.varlist.add('FILE', '*' + pname + ' = NULL')
+                info.varlist.add('PyObject', '*py_' + pname)
+                info.codebefore.append(self.null & {'name':pname})
+            info.arglist.appned(pname)
+            info.add_parselist('O', ['&py_' + pname], [pname])
+        else:
+            if pdflt:
+                info.varlist.add('FILE', '*' + pname + ' = ' + pdflt)
+                info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
+                info.codebefore.append(self.dflt % {'name':pname})
+                info.arglist.append(pname)
+            else:
+                info.varlist.add('PyObject', '*' + pname)
+                info.arglist.append('PyFile_AsFile(' + pname + ')')
+            info.add_parselist('O!', ['&PyFile_Type', '&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('FILE', '*ret')
+        info.codeafter.append('    if (ret)\n' +
+                              '        return PyFile_FromFile(ret, "", "", fclose);\n' +
+                              '    Py_INCREF(Py_None);\n' +
+                              '    return Py_None;')
+
+class EnumArg(ArgType):
+    enum = ('    if (pyg_enum_get_value(%(typecode)s, py_%(name)s, (gpointer)&%(name)s))\n'
+            '        return NULL;\n')
+    def __init__(self, enumname, typecode):
+        self.enumname = enumname
+        self.typecode = typecode
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add(self.enumname, pname + ' = ' + pdflt)
+        else:
+            info.varlist.add(self.enumname, pname)
+        info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
+        info.codebefore.append(self.enum % { 'typecode': self.typecode,
+                                             'name': pname})
+        info.arglist.append(pname)
+        info.add_parselist('O', ['&py_' + pname], [pname]);
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('gint', 'ret')
+        info.codeafter.append('    return pyg_enum_from_gtype(%s, ret);' % self.typecode)
+
+class FlagsArg(ArgType):
+    flag = ('    if (%(default)spyg_flags_get_value(%(typecode)s, py_%(name)s, (gpointer)&%(name)s))\n'
+            '        return NULL;\n')
+    def __init__(self, flagname, typecode):
+        self.flagname = flagname
+        self.typecode = typecode
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add(self.flagname, pname + ' = ' + pdflt)
+            default = "py_%s && " % (pname,)
+        else:
+            info.varlist.add(self.flagname, pname)
+            default = ""
+        info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
+        info.codebefore.append(self.flag % {'default':default,
+                                            'typecode':self.typecode,
+                                            'name':pname})
+        info.arglist.append(pname)
+        info.add_parselist('O', ['&py_' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('guint', 'ret')
+        info.codeafter.append('    return pyg_flags_from_gtype(%s, ret);' % self.typecode)
+
+class ObjectArg(ArgType):
+    # should change these checks to more typesafe versions that check
+    # a little further down in the class heirachy.
+    nulldflt = ('    if ((PyObject *)py_%(name)s == Py_None)\n'
+                '        %(name)s = NULL;\n'
+                '    else if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n'
+                '        %(name)s = %(cast)s(py_%(name)s->obj);\n'
+                '    else if (py_%(name)s) {\n'
+                '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
+                '        return NULL;\n'
+                '    }\n')
+    null = ('    if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n'
+            '        %(name)s = %(cast)s(py_%(name)s->obj);\n'
+            '    else if ((PyObject *)py_%(name)s != Py_None) {\n'
+            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
+            '        return NULL;\n'
+            '    }\n')
+    dflt = '    if (py_%(name)s)\n' \
+           '        %(name)s = %(cast)s(py_%(name)s->obj);\n'
+    def __init__(self, objname, parent, typecode):
+        self.objname = objname
+        self.cast = string.replace(typecode, '_TYPE_', '_', 1)
+        self.parent = parent
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pnull:
+            if pdflt:
+                info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt)
+                info.varlist.add('PyGObject', '*py_' + pname + ' = NULL')
+                info.codebefore.append(self.nulldflt % {'name':pname,
+                                                        'cast':self.cast,
+                                                        'type':self.objname})
+            else:
+                info.varlist.add(self.objname, '*' + pname + ' = NULL')
+                info.varlist.add('PyGObject', '*py_' + pname)
+                info.codebefore.append(self.null % {'name':pname,
+                                                    'cast':self.cast,
+                                                    'type':self.objname})
+            if ptype.endswith('*'):
+                typename = ptype[:-1]
+                try:
+                    const, typename = typename.split('const-')
+                except ValueError:
+                    const = ''
+                if typename != ptype:
+                    info.arglist.append('(%s *) %s' % (ptype[:-1], pname))
+                else:
+                    info.arglist.append(pname)
+
+            info.add_parselist('O', ['&py_' + pname], [pname])
+        else:
+            if pdflt:
+                info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt)
+                info.varlist.add('PyGObject', '*py_' + pname + ' = NULL')
+                info.codebefore.append(self.dflt % {'name':pname,
+                                                    'cast':self.cast})
+                info.arglist.append(pname)
+                info.add_parselist('O!', ['&Py%s_Type' % self.objname,
+                                         '&py_' + pname], [pname])
+            else:
+                info.varlist.add('PyGObject', '*' + pname)
+                info.arglist.append('%s(%s->obj)' % (self.cast, pname))
+                info.add_parselist('O!', ['&Py%s_Type' % self.objname,
+                                          '&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        if ptype.endswith('*'):
+            typename = ptype[:-1]
+            try:
+                const, typename = typename.split('const-')
+            except ValueError:
+                const = ''
+        info.varlist.add(typename, '*ret')
+        if ownsreturn:
+            info.varlist.add('PyObject', '*py_ret')
+            info.codeafter.append('    py_ret = pygobject_new((GObject *)ret);\n'
+                                  '    if (ret != NULL)\n'
+                                  '        g_object_unref(ret);\n'
+                                  '    return py_ret;')
+        else:
+            info.codeafter.append('    /* pygobject_new handles NULL checking */\n' +
+                                  '    return pygobject_new((GObject *)ret);')
+
+class BoxedArg(ArgType):
+    # haven't done support for default args.  Is it needed?
+    check = ('    if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n'
+             '        %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n'
+             '    else {\n'
+             '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n'
+             '        return NULL;\n'
+             '    }\n')
+    null = ('    if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n'
+            '        %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n'
+            '    else if (py_%(name)s != Py_None) {\n'
+            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n'
+            '        return NULL;\n'
+            '    }\n')
+    def __init__(self, ptype, typecode):
+        self.typename = ptype
+        self.typecode = typecode
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pnull:
+            info.varlist.add(self.typename, '*' + pname + ' = NULL')
+            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
+            info.codebefore.append(self.null % {'name':  pname,
+                                                'typename': self.typename,
+                                                'typecode': self.typecode})
+        else:
+            info.varlist.add(self.typename, '*' + pname + ' = NULL')
+            info.varlist.add('PyObject', '*py_' + pname)
+            info.codebefore.append(self.check % {'name':  pname,
+                                                 'typename': self.typename,
+                                                 'typecode': self.typecode})
+        if ptype[-1] == '*':
+            typename = ptype[:-1]
+            if typename[:6] == 'const-': typename = typename[6:]
+            if typename != self.typename:
+                info.arglist.append('(%s *)%s' % (ptype[:-1], pname))
+            else:
+                info.arglist.append(pname)
+        else:
+            info.arglist.append(pname)
+        info.add_parselist('O', ['&py_' + pname], [pname])
+    ret_tmpl = '    /* pyg_boxed_new handles NULL checking */\n' \
+               '    return pyg_boxed_new(%(typecode)s, %(ret)s, %(copy)s, TRUE);'
+    def write_return(self, ptype, ownsreturn, info):
+        if ptype[-1] == '*':
+            decl_type = self.typename
+            ret = 'ret'
+            if ptype[:6] == 'const-':
+                decl_type = 'const ' + self.typename
+                ret = '(%s*) ret' % (self.typename,)
+            info.varlist.add(decl_type, '*ret')
+        else:
+            info.varlist.add(self.typename, 'ret')
+            ret = '&ret'
+            ownsreturn = 0 # of course it can't own a ref to a local var ...
+        info.codeafter.append(self.ret_tmpl %
+                              { 'typecode': self.typecode,
+                                'ret': ret,
+                                'copy': ownsreturn and 'FALSE' or 'TRUE'})
+
+class CustomBoxedArg(ArgType):
+    # haven't done support for default args.  Is it needed?
+    null = ('    if (%(check)s(py_%(name)s))\n'
+            '        %(name)s = %(get)s(py_%(name)s);\n'
+            '    else if (py_%(name)s != Py_None) {\n'
+            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
+            '        return NULL;\n'
+            '    }\n')
+    def __init__(self, ptype, pytype, getter, new):
+        self.pytype = pytype
+        self.getter = getter
+        self.checker = 'Py' + ptype + '_Check'
+        self.new = new
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pnull:
+            info.varlist.add(ptype[:-1], '*' + pname + ' = NULL')
+            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
+            info.codebefore.append(self.null % {'name':  pname,
+                                                'get':   self.getter,
+                                                'check': self.checker,
+                                                'type':  ptype[:-1]})
+            info.arglist.append(pname)
+            info.add_parselist('O', ['&py_' + pname], [pname])
+        else:
+            info.varlist.add('PyObject', '*' + pname)
+            info.arglist.append(self.getter + '(' + pname + ')')
+            info.add_parselist('O!', ['&' + self.pytype, '&' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add(ptype[:-1], '*ret')
+        info.codeafter.append('    if (ret)\n' +
+                              '        return ' + self.new + '(ret);\n' +
+                              '    Py_INCREF(Py_None);\n' +
+                              '    return Py_None;')
+
+class PointerArg(ArgType):
+    # haven't done support for default args.  Is it needed?
+    check = ('    if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n'
+             '        %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n'
+             '    else {\n'
+             '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n'
+             '        return NULL;\n'
+             '    }\n')
+    null = ('    if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n'
+            '        %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n'
+            '    else if (py_%(name)s != Py_None) {\n'
+            '        PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n'
+            '        return NULL;\n'
+            '    }\n')
+    def __init__(self, ptype, typecode):
+        self.typename = ptype
+        self.typecode = typecode
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pnull:
+            info.varlist.add(self.typename, '*' + pname + ' = NULL')
+            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
+            info.codebefore.append(self.null % {'name':  pname,
+                                                'typename': self.typename,
+                                                'typecode': self.typecode})
+        else:
+            info.varlist.add(self.typename, '*' + pname + ' = NULL')
+            info.varlist.add('PyObject', '*py_' + pname)
+            info.codebefore.append(self.check % {'name':  pname,
+                                                 'typename': self.typename,
+                                                 'typecode': self.typecode})
+        info.arglist.append(pname)
+        info.add_parselist('O', ['&py_' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        if ptype[-1] == '*':
+            info.varlist.add(self.typename, '*ret')
+            info.codeafter.append('    /* pyg_pointer_new handles NULL checking */\n' +
+                                  '    return pyg_pointer_new(' + self.typecode + ', ret);')
+        else:
+            info.varlist.add(self.typename, 'ret')
+            info.codeafter.append('    /* pyg_pointer_new handles NULL checking */\n' +
+                                  '    return pyg_pointer_new(' + self.typecode + ', &ret);')
+
+class AtomArg(IntArg):
+    dflt = '    if (py_%(name)s) {\n' \
+           '        %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n' \
+           '        if (PyErr_Occurred())\n' \
+           '            return NULL;\n' \
+           '    }\n'
+    atom = ('    %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n'
+            '    if (PyErr_Occurred())\n'
+            '        return NULL;\n')
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pdflt:
+            info.varlist.add('GdkAtom', pname + ' = ' + pdflt)
+            info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
+            info.codebefore.append(self.dflt % {'name': pname})
+        else:
+            info.varlist.add('GdkAtom', pname)
+            info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
+            info.codebefore.append(self.atom % {'name': pname})
+        info.arglist.append(pname)
+        info.add_parselist('O', ['&py_' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('GdkAtom', 'ret')
+        info.varlist.add('PyObject *', 'py_ret')
+        info.varlist.add('gchar *', 'name')
+        info.codeafter.append('    name = gdk_atom_name(ret);\n'
+                              '    py_ret = _PyUnicode_FromString(name);\n'
+                              '    g_free(name);\n'
+                              '    return py_ret;')
+
+class GTypeArg(ArgType):
+    gtype = ('    if ((%(name)s = pyg_type_from_object(py_%(name)s)) == 0)\n'
+             '        return NULL;\n')
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        info.varlist.add('GType', pname)
+        info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
+        info.codebefore.append(self.gtype % {'name': pname})
+        info.arglist.append(pname)
+        info.add_parselist('O', ['&py_' + pname], [pname])
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('GType', 'ret')
+        info.codeafter.append('    return pyg_type_wrapper_new(ret);')
+
+# simple GError handler.
+class GErrorArg(ArgType):
+    handleerror = ('    if (pyg_error_check(&%(name)s))\n'
+                   '        return NULL;\n')
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        info.varlist.add('GError', '*' + pname + ' = NULL')
+        info.arglist.append('&' + pname)
+        info.codeafter.append(self.handleerror % { 'name': pname })
+
+class GtkTreePathArg(ArgType):
+    # haven't done support for default args.  Is it needed?
+    normal = ('    %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n'
+              '    if (!%(name)s) {\n'
+              '        PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n'
+              '        return NULL;\n'
+              '    }\n')
+    null = ('    if (py_%(name)s != Py_None) {\n'
+            '        %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n'
+            '        if (!%(name)s) {\n'
+            '            PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n'
+            '            return NULL;\n'
+            '        }\n'
+            '    }\n')
+    freepath = ('    if (%(name)s)\n'
+                '        gtk_tree_path_free(%(name)s);\n')
+    def __init__(self):
+        pass
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pnull:
+            info.varlist.add('GtkTreePath', '*' + pname + ' = NULL')
+            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
+            info.codebefore.append(self.null % {'name':  pname})
+            info.arglist.append(pname)
+            info.add_parselist('O', ['&py_' + pname], [pname])
+        else:
+            info.varlist.add('GtkTreePath', '*' + pname)
+            info.varlist.add('PyObject', '*py_' + pname)
+            info.codebefore.append(self.normal % {'name': pname})
+            info.arglist.append(pname)
+            info.add_parselist('O', ['&py_' + pname], [pname])
+        info.codeafter.append(self.freepath % {'name': pname})
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('GtkTreePath', '*ret')
+        if ownsreturn:
+            info.codeafter.append('    if (ret) {\n'
+                                  '        PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n'
+                                  '        gtk_tree_path_free(ret);\n'
+                                  '        return py_ret;\n'
+                                  '    }\n'
+                                  '    Py_INCREF(Py_None);\n'
+                                  '    return Py_None;')
+        else:
+            info.codeafter.append('    if (ret) {\n'
+                                  '        PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n'
+                                  '        return py_ret;\n'
+                                  '    }\n'
+                                  '    Py_INCREF(Py_None);\n'
+                                  '    return Py_None;')
+
+class GdkRectanglePtrArg(ArgType):
+    normal = ('    if (!pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s))\n'
+              '        return NULL;\n')
+    null =   ('    if (py_%(name)s == Py_None)\n'
+              '        %(name)s = NULL;\n'
+              '    else if (pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s_rect))\n'
+              '        %(name)s = &%(name)s_rect;\n'
+              '    else\n'
+              '            return NULL;\n')
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        if pnull:
+            info.varlist.add('GdkRectangle', pname + '_rect = { 0, 0, 0, 0 }')
+            info.varlist.add('GdkRectangle', '*' + pname)
+            info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
+            info.add_parselist('O', ['&py_' + pname], [pname])
+            info.arglist.append(pname)
+            info.codebefore.append(self.null % {'name':  pname})
+        else:
+            info.varlist.add('GdkRectangle', pname + ' = { 0, 0, 0, 0 }')
+            info.varlist.add('PyObject', '*py_' + pname)
+            info.add_parselist('O', ['&py_' + pname], [pname])
+            info.arglist.append('&' + pname)
+            info.codebefore.append(self.normal % {'name':  pname})
+
+class GdkRectangleArg(ArgType):
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add('GdkRectangle', 'ret')
+        info.codeafter.append('    return pyg_boxed_new(GDK_TYPE_RECTANGLE, &ret, TRUE, TRUE);')
+
+class PyObjectArg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        info.varlist.add('PyObject', '*' + pname)
+        info.add_parselist('O', ['&' + pname], [pname])
+        info.arglist.append(pname)
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add("PyObject", "*ret")
+        if ownsreturn:
+            info.codeafter.append('    if (ret) {\n'
+                                  '       return ret;\n'
+                                  '    }\n'
+                                  '    Py_INCREF(Py_None);\n'
+                                  '    return Py_None;')
+        else:
+            info.codeafter.append('    if (!ret) ret = Py_None;\n'
+                                  '    Py_INCREF(ret);\n'
+                                  '    return ret;')
+
+class CairoArg(ArgType):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        info.varlist.add('PycairoContext', '*' + pname)
+        info.add_parselist('O!', ['&PycairoContext_Type', '&' + pname], [pname])
+        info.arglist.append('%s->ctx' % pname)
+    def write_return(self, ptype, ownsreturn, info):
+        info.varlist.add("cairo_t", "*ret")
+        if ownsreturn:
+            info.codeafter.append('    return PycairoContext_FromContext(ret, NULL, NULL);')
+        else:
+            info.codeafter.append('    cairo_reference(ret);\n'
+                                  '    return PycairoContext_FromContext(ret, NULL, NULL);')
+
+
+class ArgMatcher:
+    def __init__(self):
+        self.argtypes = {}
+        self.reverse_argtypes = {}
+        self.reverse_rettypes = {}
+
+    def register(self, ptype, handler, overwrite=False):
+        if not overwrite and ptype in self.argtypes:
+            return
+        self.argtypes[ptype] = handler
+    def register_reverse(self, ptype, handler):
+        self.reverse_argtypes[ptype] = handler
+    def register_reverse_ret(self, ptype, handler):
+        self.reverse_rettypes[ptype] = handler
+
+    def register_enum(self, ptype, typecode):
+        if typecode is None:
+            self.register(ptype, IntArg())
+        else:
+            self.register(ptype, EnumArg(ptype, typecode))
+    def register_flag(self, ptype, typecode):
+        if typecode is None:
+            self.register(ptype, IntArg())
+        else:
+            self.register(ptype, FlagsArg(ptype, typecode))
+    def register_object(self, ptype, parent, typecode):
+        oa = ObjectArg(ptype, parent, typecode)
+        self.register(ptype, oa)  # in case I forget the * in the .defs
+        self.register(ptype+'*', oa)
+        self.register('const-'+ptype+'*', oa)
+        if ptype == 'GdkPixmap':
+            # hack to handle GdkBitmap synonym.
+            self.register('GdkBitmap', oa)
+            self.register('GdkBitmap*', oa)
+    def register_boxed(self, ptype, typecode):
+        if ptype in self.argtypes: return
+        arg = BoxedArg(ptype, typecode)
+        self.register(ptype, arg)
+        self.register(ptype+'*', arg)
+        self.register('const-'+ptype+'*', arg)
+    def register_custom_boxed(self, ptype, pytype, getter, new):
+        arg = CustomBoxedArg(ptype, pytype, getter, new)
+        self.register(ptype+'*', arg)
+        self.register('const-'+ptype+'*', arg)
+    def register_pointer(self, ptype, typecode):
+        arg = PointerArg(ptype, typecode)
+        self.register(ptype, arg)
+        self.register(ptype+'*', arg)
+        self.register('const-'+ptype+'*', arg)
+
+    def get(self, ptype):
+        try:
+            return self.argtypes[ptype]
+        except KeyError:
+            if ptype[:8] == 'GdkEvent' and ptype[-1] == '*':
+                return self.argtypes['GdkEvent*']
+            raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
+    def _get_reverse_common(self, ptype, registry):
+        props = dict(c_type=ptype)
+        try:
+            return registry[ptype], props
+        except KeyError:
+            try:
+                handler = self.argtypes[ptype]
+            except KeyError:
+                if ptype.startswith('GdkEvent') and ptype.endswith('*'):
+                    handler = self.argtypes['GdkEvent*']
+                else:
+                    raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
+            if isinstance(handler, ObjectArg):
+                return registry['GObject*'], props
+            elif isinstance(handler, EnumArg):
+                props['typecode'] = handler.typecode
+                props['enumname'] = handler.enumname
+                return registry['GEnum'], props
+            elif isinstance(handler, FlagsArg):
+                props['typecode'] = handler.typecode
+                props['flagname'] = handler.flagname
+                return registry['GFlags'], props
+            elif isinstance(handler, BoxedArg):
+                props['typecode'] = handler.typecode
+                props['typename'] = handler.typename
+                return registry['GBoxed'], props
+            else:
+                raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
+
+    def get_reverse(self, ptype):
+        return self._get_reverse_common(ptype, self.reverse_argtypes)
+
+    def get_reverse_ret(self, ptype):
+        ret, props = self._get_reverse_common(ptype, self.reverse_rettypes)
+        if hasattr(ptype, 'optional') and ptype.optional:
+            if ret.supports_optional:
+                props['optional'] = True
+            else:
+                raise ArgTypeNotFoundError("Unsupported 'optional' for %s"
+                                           % (ptype,))
+        return ret, props
+
+    def object_is_a(self, otype, parent):
+        if otype == None: return 0
+        if otype == parent: return 1
+        if otype not in self.argtypes: return 0
+        return self.object_is_a(self.get(otype).parent, parent)
+
+matcher = ArgMatcher()
+
+arg = NoneArg()
+matcher.register(None, arg)
+matcher.register('none', arg)
+
+arg = StringArg()
+matcher.register('char*', arg)
+matcher.register('gchar*', arg)
+matcher.register('const-char*', arg)
+matcher.register('char-const*', arg)
+matcher.register('const-gchar*', arg)
+matcher.register('gchar-const*', arg)
+matcher.register('string', arg)
+matcher.register('static_string', arg)
+
+arg = UCharArg()
+matcher.register('unsigned-char*', arg)
+matcher.register('const-guchar*', arg)
+matcher.register('const-guint8*', arg)
+matcher.register('guchar*', arg)
+
+arg = CharArg()
+matcher.register('char', arg)
+matcher.register('gchar', arg)
+matcher.register('guchar', arg)
+
+arg = GUniCharArg()
+matcher.register('gunichar', arg)
+
+arg = IntArg()
+matcher.register('int', arg)
+matcher.register('gint', arg)
+matcher.register('short', arg)
+matcher.register('gshort', arg)
+matcher.register('gushort', arg)
+matcher.register('gsize', SizeArg())
+matcher.register('gssize', SSizeArg())
+matcher.register('guint8', arg)
+matcher.register('gint8', arg)
+matcher.register('guint16', arg)
+matcher.register('gint16', arg)
+matcher.register('gint32', arg)
+matcher.register('GTime', arg)
+matcher.register('GSeekType', arg) # Hack, but we have no python wrapper
+
+arg = LongArg()
+matcher.register('long', arg)
+matcher.register('glong', arg)
+
+arg = UIntArg()
+matcher.register('guint', arg)
+
+arg = BoolArg()
+matcher.register('gboolean', arg)
+
+arg = TimeTArg()
+matcher.register('time_t', arg)
+
+matcher.register('guint32', UInt32Arg())
+
+arg = ULongArg()
+matcher.register('gulong', arg)
+
+arg = Int64Arg()
+matcher.register('gint64', arg)
+matcher.register('long-long', arg)
+matcher.register('goffset', arg)
+
+arg = UInt64Arg()
+matcher.register('guint64', arg)
+matcher.register('unsigned-long-long', arg)
+
+arg = DoubleArg()
+matcher.register('double', arg)
+matcher.register('gdouble', arg)
+matcher.register('float', arg)
+matcher.register('gfloat', arg)
+
+arg = FileArg()
+matcher.register('FILE*', arg)
+
+# enums, flags, objects
+
+matcher.register('GdkAtom', AtomArg())
+
+matcher.register('GType', GTypeArg())
+matcher.register('GtkType', GTypeArg())
+
+matcher.register('GError**', GErrorArg())
+matcher.register('GtkTreePath*', GtkTreePathArg())
+matcher.register('GdkRectangle*', GdkRectanglePtrArg())
+matcher.register('GtkAllocation*', GdkRectanglePtrArg())
+matcher.register('GdkRectangle', GdkRectangleArg())
+matcher.register('PyObject*', PyObjectArg())
+
+matcher.register('GdkNativeWindow', ULongArg())
+
+matcher.register_object('GObject', None, 'G_TYPE_OBJECT')
+
+del arg
+
+matcher.register('cairo_t*', CairoArg())
+matcher.register_boxed("GClosure", "G_TYPE_CLOSURE")
diff --git a/codegen/libcodegen/definitions.py b/codegen/libcodegen/definitions.py
new file mode 100644
index 0000000..a31d822
--- /dev/null
+++ b/codegen/libcodegen/definitions.py
@@ -0,0 +1,567 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+import copy
+import sys
+
+def get_valid_scheme_definitions(defs):
+    return [x for x in defs if isinstance(x, tuple) and len(x) >= 2]
+
+def unescape(s):
+    s = s.replace('\r\n', '\\r\\n').replace('\t', '\\t')
+    return s.replace('\r', '\\r').replace('\n', '\\n')
+
+def make_docstring(lines):
+    return "(char *) " + '\n'.join(['"%s"' % unescape(s) for s in lines])
+
+# New Parameter class, wich emulates a tuple for compatibility reasons
+class Parameter(object):
+    def __init__(self, ptype, pname, pdflt, pnull, pdir=None):
+        self.ptype = ptype
+        self.pname = pname
+        self.pdflt = pdflt
+        self.pnull = pnull
+        self.pdir = pdir
+
+    def __len__(self): return 4
+    def __getitem__(self, i):
+        return (self.ptype, self.pname, self.pdflt, self.pnull)[i]
+
+    def merge(self, old):
+        if old.pdflt is not None:
+            self.pdflt = old.pdflt
+        if old.pnull is not None:
+            self.pnull = old.pnull
+
+# We currently subclass 'str' to make impact on the rest of codegen as
+# little as possible.  Later we can subclass 'object' instead, but
+# then we must find and adapt all places which expect return types to
+# be strings.
+class ReturnType(str):
+    def __new__(cls, *args, **kwds):
+        return str.__new__(cls, *args[:1])
+    def __init__(self, type_name, optional=False):
+        str.__init__(self)
+        self.optional = optional
+
+# Parameter for property based constructors
+class Property(object):
+    def __init__(self, pname, optional, argname):
+        self.pname = pname
+        self.optional = optional
+        self.argname = argname
+
+    def __len__(self): return 4
+    def __getitem__(self, i):
+        return ('', self.pname, self.optional, self.argname)[i]
+
+    def merge(self, old):
+        if old.optional is not None:
+            self.optional = old.optional
+        if old.argname is not None:
+            self.argname = old.argname
+
+
+class Definition:
+    docstring = "NULL"
+    def __init__(self, *args):
+        """Create a new defs object of this type.  The arguments are the
+        components of the definition"""
+        raise RuntimeError("this is an abstract class")
+    def merge(self, old):
+        """Merge in customisations from older version of definition"""
+        raise RuntimeError("this is an abstract class")
+    def write_defs(self, fp=sys.stdout):
+        """write out this definition in defs file format"""
+        raise RuntimeError("this is an abstract class")
+
+    def guess_return_value_ownership(self):
+        "return 1 if caller owns return value"
+        if getattr(self, 'is_constructor_of', False):
+            self.caller_owns_return = True
+        elif self.ret in ('char*', 'gchar*', 'string'):
+            self.caller_owns_return = True
+        else:
+            self.caller_owns_return = False
+
+
+class ObjectDef(Definition):
+    def __init__(self, name, *args):
+        self.name = name
+        self.module = None
+        self.parent = None
+        self.c_name = None
+        self.typecode = None
+        self.fields = []
+        self.implements = []
+        self.class_init_func = None
+        self.has_new_constructor_api = False
+        for arg in get_valid_scheme_definitions(args):
+            if arg[0] == 'in-module':
+                self.module = arg[1]
+            elif arg[0] == 'docstring':
+                self.docstring = make_docstring(arg[1:])
+            elif arg[0] == 'parent':
+                self.parent = arg[1]
+            elif arg[0] == 'c-name':
+                self.c_name = arg[1]
+            elif arg[0] == 'gtype-id':
+                self.typecode = arg[1]
+            elif arg[0] == 'fields':
+                for parg in arg[1:]:
+                    self.fields.append((parg[0], parg[1]))
+            elif arg[0] == 'implements':
+                self.implements.append(arg[1])
+    def merge(self, old):
+        # currently the .h parser doesn't try to work out what fields of
+        # an object structure should be public, so we just copy the list
+        # from the old version ...
+        self.fields = old.fields
+        self.implements = old.implements
+    def write_defs(self, fp=sys.stdout):
+        fp.write('(define-object ' + self.name + '\n')
+        if self.module:
+            fp.write('  (in-module "' + self.module + '")\n')
+        if self.parent != (None, None):
+            fp.write('  (parent "' + self.parent + '")\n')
+        for interface in self.implements:
+            fp.write('  (implements "' + interface + '")\n')
+        if self.c_name:
+            fp.write('  (c-name "' + self.c_name + '")\n')
+        if self.typecode:
+            fp.write('  (gtype-id "' + self.typecode + '")\n')
+        if self.fields:
+            fp.write('  (fields\n')
+            for (ftype, fname) in self.fields:
+                fp.write('    \'("' + ftype + '" "' + fname + '")\n')
+            fp.write('  )\n')
+        fp.write(')\n\n')
+
+class InterfaceDef(Definition):
+    def __init__(self, name, *args):
+        self.name = name
+        self.module = None
+        self.c_name = None
+        self.typecode = None
+        self.vtable = None
+        self.fields = []
+        self.interface_info = None
+        for arg in get_valid_scheme_definitions(args):
+            if arg[0] == 'in-module':
+                self.module = arg[1]
+            elif arg[0] == 'docstring':
+                self.docstring = make_docstring(arg[1:])
+            elif arg[0] == 'c-name':
+                self.c_name = arg[1]
+            elif arg[0] == 'gtype-id':
+                self.typecode = arg[1]
+            elif arg[0] == 'vtable':
+                self.vtable = arg[1]
+        if self.vtable is None:
+            self.vtable = self.c_name + "Iface"
+    def write_defs(self, fp=sys.stdout):
+        fp.write('(define-interface ' + self.name + '\n')
+        if self.module:
+            fp.write('  (in-module "' + self.module + '")\n')
+        if self.c_name:
+            fp.write('  (c-name "' + self.c_name + '")\n')
+        if self.typecode:
+            fp.write('  (gtype-id "' + self.typecode + '")\n')
+        fp.write(')\n\n')
+
+class EnumDef(Definition):
+    def __init__(self, name, *args):
+        self.deftype = 'enum'
+        self.name = name
+        self.in_module = None
+        self.c_name = None
+        self.typecode = None
+        self.values = []
+        for arg in get_valid_scheme_definitions(args):
+            if arg[0] == 'in-module':
+                self.in_module = arg[1]
+            elif arg[0] == 'c-name':
+                self.c_name = arg[1]
+            elif arg[0] == 'gtype-id':
+                self.typecode = arg[1]
+            elif arg[0] == 'values':
+                for varg in arg[1:]:
+                    self.values.append((varg[0], varg[1]))
+    def merge(self, old):
+        pass
+    def write_defs(self, fp=sys.stdout):
+        fp.write('(define-' + self.deftype + ' ' + self.name + '\n')
+        if self.in_module:
+            fp.write('  (in-module "' + self.in_module + '")\n')
+        fp.write('  (c-name "' + self.c_name + '")\n')
+        fp.write('  (gtype-id "' + self.typecode + '")\n')
+        if self.values:
+            fp.write('  (values\n')
+            for name, val in self.values:
+                fp.write('    \'("' + name + '" "' + val + '")\n')
+            fp.write('  )\n')
+        fp.write(')\n\n')
+
+class FlagsDef(EnumDef):
+    def __init__(self, *args):
+        EnumDef.__init__(*(self,) + args)
+        self.deftype = 'flags'
+
+class BoxedDef(Definition):
+    def __init__(self, name, *args):
+        self.name = name
+        self.module = None
+        self.c_name = None
+        self.typecode = None
+        self.copy = None
+        self.release = None
+        self.fields = []
+        for arg in get_valid_scheme_definitions(args):
+            if arg[0] == 'in-module':
+                self.module = arg[1]
+            elif arg[0] == 'c-name':
+                self.c_name = arg[1]
+            elif arg[0] == 'gtype-id':
+                self.typecode = arg[1]
+            elif arg[0] == 'copy-func':
+                self.copy = arg[1]
+            elif arg[0] == 'release-func':
+                self.release = arg[1]
+            elif arg[0] == 'fields':
+                for parg in arg[1:]:
+                    self.fields.append((parg[0], parg[1]))
+    def merge(self, old):
+        # currently the .h parser doesn't try to work out what fields of
+        # an object structure should be public, so we just copy the list
+        # from the old version ...
+        self.fields = old.fields
+    def write_defs(self, fp=sys.stdout):
+        fp.write('(define-boxed ' + self.name + '\n')
+        if self.module:
+            fp.write('  (in-module "' + self.module + '")\n')
+        if self.c_name:
+            fp.write('  (c-name "' + self.c_name + '")\n')
+        if self.typecode:
+            fp.write('  (gtype-id "' + self.typecode + '")\n')
+        if self.copy:
+            fp.write('  (copy-func "' + self.copy + '")\n')
+        if self.release:
+            fp.write('  (release-func "' + self.release + '")\n')
+        if self.fields:
+            fp.write('  (fields\n')
+            for (ftype, fname) in self.fields:
+                fp.write('    \'("' + ftype + '" "' + fname + '")\n')
+            fp.write('  )\n')
+        fp.write(')\n\n')
+
+class PointerDef(Definition):
+    def __init__(self, name, *args):
+        self.name = name
+        self.module = None
+        self.c_name = None
+        self.typecode = None
+        self.fields = []
+        for arg in get_valid_scheme_definitions(args):
+            if arg[0] == 'in-module':
+                self.module = arg[1]
+            elif arg[0] == 'c-name':
+                self.c_name = arg[1]
+            elif arg[0] == 'gtype-id':
+                self.typecode = arg[1]
+            elif arg[0] == 'fields':
+                for parg in arg[1:]:
+                    self.fields.append((parg[0], parg[1]))
+    def merge(self, old):
+        # currently the .h parser doesn't try to work out what fields of
+        # an object structure should be public, so we just copy the list
+        # from the old version ...
+        self.fields = old.fields
+    def write_defs(self, fp=sys.stdout):
+        fp.write('(define-pointer ' + self.name + '\n')
+        if self.module:
+            fp.write('  (in-module "' + self.module + '")\n')
+        if self.c_name:
+            fp.write('  (c-name "' + self.c_name + '")\n')
+        if self.typecode:
+            fp.write('  (gtype-id "' + self.typecode + '")\n')
+        if self.fields:
+            fp.write('  (fields\n')
+            for (ftype, fname) in self.fields:
+                fp.write('    \'("' + ftype + '" "' + fname + '")\n')
+            fp.write('  )\n')
+        fp.write(')\n\n')
+
+class MethodDefBase(Definition):
+    def __init__(self, name, *args):
+        dump = 0
+        self.name = name
+        self.ret = None
+        self.caller_owns_return = None
+        self.unblock_threads = None
+        self.c_name = None
+        self.typecode = None
+        self.of_object = None
+        self.params = [] # of form (type, name, default, nullok)
+        self.varargs = 0
+        self.deprecated = None
+        for arg in get_valid_scheme_definitions(args):
+            if arg[0] == 'of-object':
+                self.of_object = arg[1]
+            elif arg[0] == 'docstring':
+                self.docstring = make_docstring(arg[1:])
+            elif arg[0] == 'c-name':
+                self.c_name = arg[1]
+            elif arg[0] == 'gtype-id':
+                self.typecode = arg[1]
+            elif arg[0] == 'return-type':
+                type_name = arg[1]
+                optional = False
+                for prop in arg[2:]:
+                    if prop[0] == 'optional':
+                        optional = True
+                self.ret = ReturnType(type_name, optional)
+            elif arg[0] == 'caller-owns-return':
+                self.caller_owns_return = arg[1] in ('t', '#t')
+            elif arg[0] == 'unblock-threads':
+                self.unblock_threads = arg[1] in ('t', '#t')
+            elif arg[0] == 'parameters':
+                for parg in arg[1:]:
+                    ptype = parg[0]
+                    pname = parg[1]
+                    pdflt = None
+                    pnull = 0
+                    pdir = None
+                    for farg in parg[2:]:
+                        assert isinstance(farg, tuple)
+                        if farg[0] == 'default':
+                            pdflt = farg[1]
+                        elif farg[0] == 'null-ok':
+                            pnull = 1
+                        elif farg[0] == 'direction':
+                            pdir = farg[1]
+                    self.params.append(Parameter(ptype, pname, pdflt, pnull, pdir))
+            elif arg[0] == 'varargs':
+                self.varargs = arg[1] in ('t', '#t')
+            elif arg[0] == 'deprecated':
+                self.deprecated = arg[1]
+            else:
+                sys.stderr.write("Warning: %s argument unsupported.\n"
+                                 % (arg[0]))
+                dump = 1
+        if dump:
+            self.write_defs(sys.stderr)
+
+        if self.caller_owns_return is None and self.ret is not None:
+            self.guess_return_value_ownership()
+
+    def merge(self, old, parmerge):
+        self.caller_owns_return = old.caller_owns_return
+        self.varargs = old.varargs
+        # here we merge extra parameter flags accross to the new object.
+        if not parmerge:
+            self.params = copy.deepcopy(old.params)
+            return
+        for i in range(len(self.params)):
+            ptype, pname, pdflt, pnull = self.params[i]
+            for p2 in old.params:
+                if p2[1] == pname:
+                    self.params[i] = (ptype, pname, p2[2], p2[3])
+                    break
+    def _write_defs(self, fp=sys.stdout):
+        if self.of_object != (None, None):
+            fp.write('  (of-object "' + self.of_object + '")\n')
+        if self.c_name:
+            fp.write('  (c-name "' + self.c_name + '")\n')
+        if self.typecode:
+            fp.write('  (gtype-id "' + self.typecode + '")\n')
+        if self.caller_owns_return:
+            fp.write('  (caller-owns-return #t)\n')
+        if self.unblock_threads:
+            fp.write('  (unblock_threads #t)\n')
+        if self.ret:
+            fp.write('  (return-type "' + self.ret + '")\n')
+        if self.deprecated:
+            fp.write('  (deprecated "' + self.deprecated + '")\n')
+        if self.params:
+            fp.write('  (parameters\n')
+            for ptype, pname, pdflt, pnull in self.params:
+                fp.write('    \'("' + ptype + '" "' + pname +'"')
+                if pdflt: fp.write(' (default "' + pdflt + '")')
+                if pnull: fp.write(' (null-ok)')
+                fp.write(')\n')
+            fp.write('  )\n')
+        if self.varargs:
+            fp.write('  (varargs #t)\n')
+        fp.write(')\n\n')
+
+
+class MethodDef(MethodDefBase):
+    def __init__(self, name, *args):
+        MethodDefBase.__init__(self, name, *args)
+        for item in ('c_name', 'of_object'):
+            if self.__dict__[item] == None:
+                self.write_defs(sys.stderr)
+                raise RuntimeError("definition missing required %s" % (item,))
+
+    def write_defs(self, fp=sys.stdout):
+        fp.write('(define-method ' + self.name + '\n')
+        self._write_defs(fp)
+
+class VirtualDef(MethodDefBase):
+    def write_defs(self, fp=sys.stdout):
+        fp.write('(define-virtual ' + self.name + '\n')
+        self._write_defs(fp)
+
+class FunctionDef(Definition):
+    def __init__(self, name, *args):
+        dump = 0
+        self.name = name
+        self.in_module = None
+        self.is_constructor_of = None
+        self.ret = None
+        self.caller_owns_return = None
+        self.unblock_threads = None
+        self.c_name = None
+        self.typecode = None
+        self.params = [] # of form (type, name, default, nullok)
+        self.varargs = 0
+        self.deprecated = None
+        for arg in get_valid_scheme_definitions(args):
+            if arg[0] == 'in-module':
+                self.in_module = arg[1]
+            elif arg[0] == 'docstring':
+                self.docstring = make_docstring(arg[1:])
+            elif arg[0] == 'is-constructor-of':
+                self.is_constructor_of = arg[1]
+            elif arg[0] == 'c-name':
+                self.c_name = arg[1]
+            elif arg[0] == 'gtype-id':
+                self.typecode = arg[1]
+            elif arg[0] == 'return-type':
+                self.ret = arg[1]
+            elif arg[0] == 'caller-owns-return':
+                self.caller_owns_return = arg[1] in ('t', '#t')
+            elif arg[0] == 'unblock-threads':
+                self.unblock_threads = arg[1] in ('t', '#t')
+            elif arg[0] == 'parameters':
+                for parg in arg[1:]:
+                    ptype = parg[0]
+                    pname = parg[1]
+                    pdflt = None
+                    pnull = 0
+                    for farg in parg[2:]:
+                        if farg[0] == 'default':
+                            pdflt = farg[1]
+                        elif farg[0] == 'null-ok':
+                            pnull = 1
+                    self.params.append(Parameter(ptype, pname, pdflt, pnull))
+            elif arg[0] == 'properties':
+                if self.is_constructor_of is None:
+                    sys.stderr.write("Warning: (properties ...) "\
+                          "is only valid for constructors\n")
+                for prop in arg[1:]:
+                    pname = prop[0]
+                    optional = False
+                    argname = pname
+                    for farg in prop[1:]:
+                        if farg[0] == 'optional':
+                            optional = True
+                        elif farg[0] == 'argname':
+                            argname = farg[1]
+                    self.params.append(Property(pname, optional, argname))
+            elif arg[0] == 'varargs':
+                self.varargs = arg[1] in ('t', '#t')
+            elif arg[0] == 'deprecated':
+                self.deprecated = arg[1]
+            else:
+                sys.stderr.write("Warning: %s argument unsupported\n"
+                                 % (arg[0],))
+                dump = 1
+        if dump:
+            self.write_defs(sys.stderr)
+
+        if self.caller_owns_return is None and self.ret is not None:
+            self.guess_return_value_ownership()
+        for item in ('c_name',):
+            if self.__dict__[item] == None:
+                self.write_defs(sys.stderr)
+                raise RuntimeError("definition missing required %s" % (item,))
+
+    _method_write_defs = MethodDef.__dict__['write_defs']
+
+    def merge(self, old, parmerge):
+        self.caller_owns_return = old.caller_owns_return
+        self.varargs = old.varargs
+        if not parmerge:
+            self.params = copy.deepcopy(old.params)
+            return
+        # here we merge extra parameter flags accross to the new object.
+        def merge_param(param):
+            for old_param in old.params:
+                if old_param.pname == param.pname:
+                    if isinstance(old_param, Property):
+                        # h2def never scans Property's, therefore if
+                        # we have one it was manually written, so we
+                        # keep it.
+                        return copy.deepcopy(old_param)
+                    else:
+                        param.merge(old_param)
+                        return param
+            raise RuntimeError("could not find %s in old_parameters %r" % (
+                param.pname, [p.pname for p in old.params]))
+        try:
+            self.params = list(map(merge_param, self.params))
+        except RuntimeError:
+            # parameter names changed and we can't find a match; it's
+            # safer to keep the old parameter list untouched.
+            self.params = copy.deepcopy(old.params)
+
+        if not self.is_constructor_of:
+            try:
+                self.is_constructor_of = old.is_constructor_of
+            except AttributeError:
+                pass
+        if isinstance(old, MethodDef):
+            self.name = old.name
+            # transmogrify from function into method ...
+            self.write_defs = self._method_write_defs
+            self.of_object = old.of_object
+            del self.params[0]
+    def write_defs(self, fp=sys.stdout):
+        fp.write('(define-function ' + self.name + '\n')
+        if self.in_module:
+            fp.write('  (in-module "' + self.in_module + '")\n')
+        if self.is_constructor_of:
+            fp.write('  (is-constructor-of "' + self.is_constructor_of +'")\n')
+        if self.c_name:
+            fp.write('  (c-name "' + self.c_name + '")\n')
+        if self.typecode:
+            fp.write('  (gtype-id "' + self.typecode + '")\n')
+        if self.caller_owns_return:
+            fp.write('  (caller-owns-return #t)\n')
+        if self.unblock_threads:
+            fp.write('  (unblock-threads #t)\n')
+        if self.ret:
+            fp.write('  (return-type "' + self.ret + '")\n')
+        if self.deprecated:
+            fp.write('  (deprecated "' + self.deprecated + '")\n')
+        if self.params:
+            if isinstance(self.params[0], Parameter):
+                fp.write('  (parameters\n')
+                for ptype, pname, pdflt, pnull in self.params:
+                    fp.write('    \'("' + ptype + '" "' + pname +'"')
+                    if pdflt: fp.write(' (default "' + pdflt + '")')
+                    if pnull: fp.write(' (null-ok)')
+                    fp.write(')\n')
+                fp.write('  )\n')
+            elif isinstance(self.params[0], Property):
+                fp.write('  (properties\n')
+                for prop in self.params:
+                    fp.write('    \'("' + prop.pname +'"')
+                    if prop.optional: fp.write(' (optional)')
+                    fp.write(')\n')
+                fp.write('  )\n')
+            else:
+                assert False, "strange parameter list %r" % self.params[0]
+        if self.varargs:
+            fp.write('  (varargs #t)\n')
+
+        fp.write(')\n\n')
diff --git a/codegen/libcodegen/defsparser.py b/codegen/libcodegen/defsparser.py
new file mode 100644
index 0000000..8121161
--- /dev/null
+++ b/codegen/libcodegen/defsparser.py
@@ -0,0 +1,156 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+import os, sys
+from libcodegen import scmexpr
+from libcodegen.definitions import BoxedDef, EnumDef, FlagsDef, FunctionDef, \
+     InterfaceDef, MethodDef, ObjectDef, PointerDef, VirtualDef
+
+include_path = ['.']
+
+class IncludeParser(scmexpr.Parser):
+    """A simple parser that follows include statements automatically"""
+    def include(self, input_filename):
+        global include_path
+        if os.path.isabs(input_filename):
+            filename = input_filename
+            # set self.filename to the include name, to handle recursive includes
+            oldfile = self.filename
+            self.filename = filename
+            self.startParsing()
+            self.filename = oldfile
+        else:
+            inc_path = [os.path.dirname(self.filename)] + include_path
+            for filename in [os.path.join(path_entry, input_filename)
+                             for path_entry in inc_path]:
+                if not os.path.exists(filename):
+                    continue
+                # set self.filename to the include name, to handle recursive includes
+                oldfile = self.filename
+                self.filename = filename
+                self.startParsing()
+                self.filename = oldfile
+                break
+            else:
+                raise IOError("%s not found in include path %s" % (input_filename, inc_path))
+
+class DefsParser(IncludeParser):
+    def __init__(self, arg, defines={}):
+        IncludeParser.__init__(self, arg)
+        self.objects = []
+        self.interfaces = []
+        self.enums = []      # enums and flags
+        self.boxes = []      # boxed types
+        self.pointers = []   # pointer types
+        self.functions = []  # functions and methods
+        self.virtuals = []   # virtual methods
+        self.c_name = {}     # hash of c names of functions
+        self.methods = {}    # hash of methods of particular objects
+        self.defines = defines      # -Dfoo=bar options, as dictionary
+
+    def define_object(self, *args):
+        odef = ObjectDef(*args)
+        self.objects.append(odef)
+        self.c_name[odef.c_name] = odef
+    def define_interface(self, *args):
+        idef = InterfaceDef(*args)
+        self.interfaces.append(idef)
+        self.c_name[idef.c_name] = idef
+    def define_enum(self, *args):
+        edef = EnumDef(*args)
+        self.enums.append(edef)
+        self.c_name[edef.c_name] = edef
+    def define_flags(self, *args):
+        fdef = FlagsDef(*args)
+        self.enums.append(fdef)
+        self.c_name[fdef.c_name] = fdef
+    def define_boxed(self, *args):
+        bdef = BoxedDef(*args)
+        self.boxes.append(bdef)
+        self.c_name[bdef.c_name] = bdef
+    def define_pointer(self, *args):
+        pdef = PointerDef(*args)
+        self.pointers.append(pdef)
+        self.c_name[pdef.c_name] = pdef
+    def define_function(self, *args):
+        fdef = FunctionDef(*args)
+        self.functions.append(fdef)
+        self.c_name[fdef.c_name] = fdef
+    def define_method(self, *args):
+        mdef = MethodDef(*args)
+        self.functions.append(mdef)
+        self.c_name[mdef.c_name] = mdef
+    def define_virtual(self, *args):
+        vdef = VirtualDef(*args)
+        self.virtuals.append(vdef)
+    def merge(self, old, parmerge):
+        for obj in self.objects:
+            if obj.c_name in old.c_name:
+                obj.merge(old.c_name[obj.c_name])
+        for f in self.functions:
+            if f.c_name in old.c_name:
+                f.merge(old.c_name[f.c_name], parmerge)
+
+    def printMissing(self, old):
+        for obj in self.objects:
+            if obj.c_name not in old.c_name:
+                obj.write_defs()
+        for f in self.functions:
+            if f.c_name not in old.c_name:
+                f.write_defs()
+
+    def write_defs(self, fp=sys.stdout):
+        for obj in self.objects:
+            obj.write_defs(fp)
+        for enum in self.enums:
+            enum.write_defs(fp)
+        for boxed in self.boxes:
+            boxed.write_defs(fp)
+        for pointer in self.pointers:
+            pointer.write_defs(fp)
+        for func in self.functions:
+            func.write_defs(fp)
+
+    def find_object(self, c_name):
+        for obj in self.objects:
+            if obj.c_name == c_name:
+                return obj
+        else:
+            raise ValueError('object %r not found' % c_name)
+
+    def find_constructor(self, obj, overrides):
+        for func in self.functions:
+            if isinstance(func, FunctionDef) and \
+               func.is_constructor_of == obj.c_name and \
+               not overrides.is_ignored(func.c_name):
+                return func
+
+    def find_methods(self, obj):
+        objname = obj.c_name
+        def _find_methods(func):
+            return isinstance(func, MethodDef) and func.of_object == objname
+        return list(filter(_find_methods, self.functions))
+
+    def find_virtuals(self, obj):
+        objname = obj.c_name
+        def _find_virtuals(func):
+            return isinstance(func, VirtualDef) and func.of_object == objname
+        retval = list(filter(_find_virtuals, self.virtuals))
+        return retval
+
+    def find_functions(self):
+        def _find_functions(func):
+            return isinstance(func, FunctionDef) and not func.is_constructor_of
+        return list(filter(_find_functions, self.functions))
+
+    def ifdef(self, *args):
+        if args[0] in self.defines:
+            for arg in args[1:]:
+                #print >> sys.stderr, "-----> Handling conditional definition (%s): %s" % (args[0], arg)
+                self.handle(arg)
+        else:
+            pass
+            #print >> sys.stderr, "-----> Conditional %s is not true" % (args[0],)
+
+    def ifndef(self, *args):
+        if args[0] not in self.defines:
+            for arg in args[1:]:
+                self.handle(arg)
diff --git a/codegen/libcodegen/docextract.py b/codegen/libcodegen/docextract.py
new file mode 100644
index 0000000..c0bc0fe
--- /dev/null
+++ b/codegen/libcodegen/docextract.py
@@ -0,0 +1,186 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+'''Simple module for extracting GNOME style doc comments from C
+sources, so I can use them for other purposes.'''
+
+import sys, os, re
+from libcodegen.string_compat import string
+
+__all__ = ['extract']
+
+class FunctionDoc:
+    def __init__(self):
+        self.name = None
+        self.params = []
+        self.description = ''
+        self.ret = ''
+    def set_name(self, name):
+        self.name = name
+    def add_param(self, name, description):
+        if name == '...':
+            name = 'Varargs'
+        self.params.append((name, description))
+    def append_to_last_param(self, extra):
+        self.params[-1] = (self.params[-1][0], self.params[-1][1] + extra)
+    def append_to_named_param(self, name, extra):
+        for i in range(len(self.params)):
+            if self.params[i][0] == name:
+                self.params[i] = (name, self.params[i][1] + extra)
+                return
+        # fall through to adding extra parameter ...
+        self.add_param(name, extra)
+    def append_description(self, extra):
+        self.description = self.description + extra
+    def append_return(self, extra):
+        self.ret = self.ret + extra
+
+    def get_param_description(self, name):
+        for param, description in self.params:
+            if param == name:
+                return description
+        else:
+            return ''
+
+comment_start_pat = re.compile(r'^\s*/\*\*\s')
+comment_end_pat = re.compile(r'^\s*\*+/')
+comment_line_lead = re.compile(r'^\s*\*\s*')
+funcname_pat = re.compile(r'^(\w+)\s*:?')
+return_pat = re.compile(r'^(returns:|return\s+value:|returns\s*)(.*\n?)$',
+                        re.IGNORECASE)
+param_pat = re.compile(r'^@(\S+)\s*:(.*\n?)$')
+
+def parse_file(fp, doc_dict):
+    line = fp.readline()
+    in_comment_block = 0
+    while line:
+        if not in_comment_block:
+            if comment_start_pat.match(line):
+                in_comment_block = 1
+                cur_doc = FunctionDoc()
+                in_description = 0
+                in_return = 0
+            line = fp.readline()
+            continue
+
+        # we are inside a comment block ...
+        if comment_end_pat.match(line):
+            if not cur_doc.name:
+                sys.stderr.write("no function name found in doc comment\n")
+            else:
+                doc_dict[cur_doc.name] = cur_doc
+            in_comment_block = 0
+            line = fp.readline()
+            continue
+
+        # inside a comment block, and not the end of the block ...
+        line = comment_line_lead.sub('', line)
+        if not line: line = '\n'
+
+        if not cur_doc.name:
+            match = funcname_pat.match(line)
+            if match:
+                cur_doc.set_name(match.group(1))
+        elif in_return:
+            match = return_pat.match(line)
+            if match:
+                # assume the last return statement was really part of the
+                # description
+                return_start = match.group(1)
+                cur_doc.ret = match.group(2)
+                cur_doc.description = cur_doc.description + return_start + \
+                                      cur_doc.ret
+            else:
+                cur_doc.append_return(line)
+        elif in_description:
+            if line[:12] == 'Description:':
+                line = line[12:]
+            match = return_pat.match(line)
+            if match:
+                in_return = 1
+                return_start = match.group(1)
+                cur_doc.append_return(match.group(2))
+            else:
+                cur_doc.append_description(line)
+        elif line == '\n':
+            # end of parameters
+            in_description = 1
+        else:
+            match = param_pat.match(line)
+            if match:
+                param = match.group(1)
+                desc = match.group(2)
+                if param == 'returns':
+                    cur_doc.ret = desc
+                else:
+                    cur_doc.add_param(param, desc)
+            else:
+                # must be continuation
+                try:
+                    if param == 'returns':
+                        cur_doc.append_return(line)
+                    else:
+                        cur_doc.append_to_last_param(line)
+                except:
+                    sys.stderr.write('something weird while reading param\n')
+        line = fp.readline()
+
+def parse_dir(dir, doc_dict):
+    for file in os.listdir(dir):
+        if file in ('.', '..'): continue
+        path = os.path.join(dir, file)
+        if os.path.isdir(path):
+            parse_dir(path, doc_dict)
+        if len(file) > 2 and file[-2:] == '.c':
+            parse_file(open(path, 'r'), doc_dict)
+
+def extract(dirs, doc_dict=None):
+    if not doc_dict: doc_dict = {}
+    for dir in dirs:
+        parse_dir(dir, doc_dict)
+    return doc_dict
+
+tmpl_section_pat = re.compile(r'^<!-- ##### (\w+) (\w+) ##### -->$')
+def parse_tmpl(fp, doc_dict):
+    cur_doc = None
+
+    line = fp.readline()
+    while line:
+        match = tmpl_section_pat.match(line)
+        if match:
+            cur_doc = None  # new input shouldn't affect the old doc dict
+            sect_type = match.group(1)
+            sect_name = match.group(2)
+
+            if sect_type == 'FUNCTION':
+                cur_doc = doc_dict.get(sect_name)
+                if not cur_doc:
+                    cur_doc = FunctionDoc()
+                    cur_doc.set_name(sect_name)
+                    doc_dict[sect_name] = cur_doc
+        elif line == '<!-- # Unused Parameters # -->\n':
+            cur_doc = None # don't worry about unused params.
+        elif cur_doc:
+            if line[:10] == '@Returns: ':
+                if string.strip(line[10:]):
+                    cur_doc.append_return(line[10:])
+            elif line[0] == '@':
+                pos = string.find(line, ':')
+                if pos >= 0:
+                    cur_doc.append_to_named_param(line[1:pos], line[pos+1:])
+                else:
+                    cur_doc.append_description(line)
+            else:
+                cur_doc.append_description(line)
+
+        line = fp.readline()
+
+def extract_tmpl(dirs, doc_dict=None):
+    if not doc_dict: doc_dict = {}
+    for dir in dirs:
+        for file in os.listdir(dir):
+            if file in ('.', '..'): continue
+            path = os.path.join(dir, file)
+            if os.path.isdir(path):
+                continue
+            if len(file) > 2 and file[-2:] == '.sgml':
+                parse_tmpl(open(path, 'r'), doc_dict)
+    return doc_dict
diff --git a/codegen/libcodegen/override.py b/codegen/libcodegen/override.py
new file mode 100644
index 0000000..414d1a2
--- /dev/null
+++ b/codegen/libcodegen/override.py
@@ -0,0 +1,285 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+
+# this file contains code for loading up an override file.  The override file
+# provides implementations of functions where the code generator could not
+# do its job correctly.
+
+import fnmatch
+import os
+import re
+from libcodegen.string_compat import string
+import sys
+
+def class2cname(klass, method):
+    c_name = ''
+    for c in klass:
+        if c.isupper():
+            c_name += '_' + c.lower()
+        else:
+            c_name += c
+    return c_name[1:] + '_'  + method
+
+# import python_type as c_name [for arg_type]
+# Last ('for') clause is optional.  If present, the type will be
+# imported only if given 'arg_type' is registered.
+import_pat = re.compile(r'\s*import\s+(\S+)\.([^\s.]+)\s+as\s+(\S+)(\s+for\s+(\S+))?')
+
+class Overrides:
+    def __init__(self, filename=None):
+        self.modulename = None
+        self.ignores = {}
+        self.glob_ignores = []
+        self.type_ignores = {}
+        self.overrides = {}
+        self.overridden = {}
+        self.kwargs = {}
+        self.noargs = {}
+        self.onearg = {}
+        self.staticmethod = {}
+        self.classmethod = {}
+        self.startlines = {}
+        self.override_attrs = {}
+        self.override_slots = {}
+        self.headers = ''
+        self.body = ''
+        self.init = ''
+        self.imports = []
+        self.defines = {}
+        self.functions = {}
+        self.newstyle_constructors = {}
+        self.dynamicnamespace = False
+        if filename:
+            self.handle_file(filename)
+
+    def handle_file(self, filename):
+        oldpath = os.getcwd()
+
+        fp = open(filename, 'r')
+        dirname = os.path.dirname(os.path.abspath(filename))
+
+        if dirname != oldpath:
+            os.chdir(dirname)
+
+        # read all the components of the file ...
+        bufs = []
+        startline = 1
+        lines = []
+        line = fp.readline()
+        linenum = 1
+        while line:
+            if line == '%%\n' or line == '%%':
+                if lines:
+                    bufs.append((string.join(lines, ''), startline))
+                startline = linenum + 1
+                lines = []
+            else:
+                lines.append(line)
+            line = fp.readline()
+            linenum = linenum + 1
+        if lines:
+            bufs.append((string.join(lines, ''), startline))
+        if not bufs: return
+
+        for buf, startline in bufs:
+            self.__parse_override(buf, startline, filename)
+
+        os.chdir(oldpath)
+
+    def __parse_override(self, buffer, startline, filename):
+        pos = string.find(buffer, '\n')
+        if pos >= 0:
+            line = buffer[:pos]
+            rest = buffer[pos+1:]
+        else:
+            line = buffer ; rest = ''
+        words = string.split(line)
+        command = words[0]
+        if (command == 'ignore' or
+            command == 'ignore-' + sys.platform):
+            "ignore/ignore-platform [functions..]"
+            for func in words[1:]:
+                self.ignores[func] = 1
+            for func in string.split(rest):
+                self.ignores[func] = 1
+        elif (command == 'ignore-glob' or
+              command == 'ignore-glob-' + sys.platform):
+            "ignore-glob/ignore-glob-platform [globs..]"
+            for func in words[1:]:
+                self.glob_ignores.append(func)
+            for func in string.split(rest):
+                self.glob_ignores.append(func)
+        elif (command == 'ignore-type' or
+              command == 'ignore-type-' + sys.platform):
+            "ignore-type/ignore-type-platform [typenames..]"
+            for typename in words[1:]:
+                self.type_ignores[typename] = 1
+            for typename in string.split(rest):
+                self.type_ignores[typename] = 1
+        elif command == 'override':
+            "override function/method [kwargs|noargs|onearg] [staticmethod|classmethod]"
+            func = words[1]
+            if 'kwargs' in words[1:]:
+                self.kwargs[func] = 1
+            elif 'noargs' in words[1:]:
+                self.noargs[func] = 1
+            elif 'onearg' in words[1:]:
+                self.onearg[func] = True
+
+            if 'staticmethod' in words[1:]:
+                self.staticmethod[func] = True
+            elif 'classmethod' in words[1:]:
+                self.classmethod[func] = True
+            if func in self.overrides:
+                raise RuntimeError("Function %s is being overridden more than once" % (func,))
+            self.overrides[func] = rest
+            self.startlines[func] = (startline + 1, filename)
+        elif command == 'override-attr':
+            "override-slot Class.attr"
+            attr = words[1]
+            self.override_attrs[attr] = rest
+            self.startlines[attr] = (startline + 1, filename)
+        elif command == 'override-slot':
+            "override-slot Class.slot"
+            slot = words[1]
+            self.override_slots[slot] = rest
+            self.startlines[slot] = (startline + 1, filename)
+        elif command == 'headers':
+            "headers"
+            self.headers = '%s\n#line %d "%s"\n%s' % \
+                           (self.headers, startline + 1, filename, rest)
+        elif command == 'body':
+            "body"
+            self.body = '%s\n#line %d "%s"\n%s' % \
+                           (self.body, startline + 1, filename, rest)
+        elif command == 'init':
+            "init"
+            self.init = '%s\n#line %d "%s"\n%s' % \
+                        (self.init, startline + 1, filename, rest)
+        elif command == 'modulename':
+            "modulename name"
+            self.modulename = words[1]
+        elif command == 'include':
+            "include filename"
+            for filename in words[1:]:
+                self.handle_file(filename)
+            for filename in string.split(rest):
+                self.handle_file(filename)
+        elif command == 'import':
+            "import module1 [\n module2, \n module3 ...]"
+            for line in string.split(buffer, '\n'):
+                match = import_pat.match(line)
+                if match:
+                    module, pyname, cname, conditional, importing_for = match.groups()
+                    self.imports.append((module, pyname, cname, importing_for or None))
+        elif command == 'define':
+            "define funcname [kwargs|noargs|onearg] [classmethod|staticmethod]"
+            "define Class.method [kwargs|noargs|onearg] [classmethod|staticmethod]"
+            func = words[1]
+            klass = None
+            if func.find('.') != -1:
+                klass, func = func.split('.', 1)
+
+                if klass not in self.defines:
+                    self.defines[klass] = {}
+                self.defines[klass][func] = rest
+            else:
+                self.functions[func] = rest
+
+            if 'kwargs' in words[1:]:
+                self.kwargs[func] = 1
+            elif 'noargs' in words[1:]:
+                self.noargs[func] = 1
+            elif 'onearg' in words[1:]:
+                self.onearg[func] = 1
+
+            if 'staticmethod' in words[1:]:
+                self.staticmethod[func] = True
+            elif 'classmethod' in words[1:]:
+                self.classmethod[func] = True
+
+            self.startlines[func] = (startline + 1, filename)
+
+        elif command == 'new-constructor':
+            "new-constructor GType"
+            gtype, = words[1:]
+            self.newstyle_constructors[gtype] = True
+        elif command == 'options':
+            for option in words[1:]:
+                if option == 'dynamicnamespace':
+                    self.dynamicnamespace = True
+
+    def is_ignored(self, name):
+        if name in self.ignores:
+            return 1
+        for glob in self.glob_ignores:
+            if fnmatch.fnmatchcase(name, glob):
+                return 1
+        return 0
+
+    def is_type_ignored(self, name):
+        return name in self.type_ignores
+
+    def is_overriden(self, name):
+        return name in self.overrides
+
+    def is_already_included(self, name):
+        return name in self.overridden
+
+    def override(self, name):
+        self.overridden[name] = 1
+        return self.overrides[name]
+
+    def define(self, klass, name):
+        self.overridden[class2cname(klass, name)] = 1
+        return self.defines[klass][name]
+
+    def function(self, name):
+        return self.functions[name]
+
+    def getstartline(self, name):
+        return self.startlines[name]
+
+    def wants_kwargs(self, name):
+        return name in self.kwargs
+
+    def wants_noargs(self, name):
+        return name in self.noargs
+
+    def wants_onearg(self, name):
+        return name in self.onearg
+
+    def is_staticmethod(self, name):
+        return name in self.staticmethod
+
+    def is_classmethod(self, name):
+        return name in self.classmethod
+
+    def attr_is_overriden(self, attr):
+        return attr in self.override_attrs
+
+    def attr_override(self, attr):
+        return self.override_attrs[attr]
+
+    def slot_is_overriden(self, slot):
+        return slot in self.override_slots
+
+    def slot_override(self, slot):
+        return self.override_slots[slot]
+
+    def get_headers(self):
+        return self.headers
+
+    def get_body(self):
+        return self.body
+
+    def get_init(self):
+        return self.init
+
+    def get_imports(self):
+        return self.imports
+
+    def get_defines_for(self, klass):
+        return self.defines.get(klass, {})
+
+    def get_functions(self):
+        return self.functions
diff --git a/codegen/libcodegen/reversewrapper.py b/codegen/libcodegen/reversewrapper.py
new file mode 100644
index 0000000..5b69c17
--- /dev/null
+++ b/codegen/libcodegen/reversewrapper.py
@@ -0,0 +1,900 @@
+### -*- python -*-
+### Code to generate "Reverse Wrappers", i.e. C->Python wrappers
+### (C) 2004 Gustavo Carneiro <gjc@gnome.org>
+from libcodegen import argtypes
+import os
+
+DEBUG_MODE = ('PYGTK_CODEGEN_DEBUG' in os.environ)
+
+def join_ctype_name(ctype, name):
+    '''Joins a C type and a variable name into a single string'''
+    if ctype[-1] != '*':
+        return " ".join((ctype, name))
+    else:
+        return "".join((ctype, name))
+
+
+class CodeSink(object):
+    def __init__(self):
+        self.indent_level = 0 # current indent level
+        self.indent_stack = [] # previous indent levels
+
+    def _format_code(self, code):
+        assert isinstance(code, str)
+        l = []
+        for line in code.split('\n'):
+            l.append(' '*self.indent_level + line)
+        if l[-1]:
+            l.append('')
+        return '\n'.join(l)
+
+    def writeln(self, line=''):
+        raise NotImplementedError
+
+    def indent(self, level=4):
+        '''Add a certain ammount of indentation to all lines written
+        from now on and until unindent() is called'''
+        self.indent_stack.append(self.indent_level)
+        self.indent_level += level
+
+    def unindent(self):
+        '''Revert indentation level to the value before last indent() call'''
+        self.indent_level = self.indent_stack.pop()
+
+
+class FileCodeSink(CodeSink):
+    def __init__(self, fp):
+        CodeSink.__init__(self)
+        assert isinstance(fp, file)
+        self.fp = fp
+
+    def writeln(self, line=''):
+        self.fp.write(self._format_code(line))
+
+class MemoryCodeSink(CodeSink):
+    def __init__(self):
+        CodeSink.__init__(self)
+        self.lines = []
+
+    def writeln(self, line=''):
+        self.lines.append(self._format_code(line))
+
+    def flush_to(self, sink):
+        assert isinstance(sink, CodeSink)
+        for line in self.lines:
+            sink.writeln(line.rstrip())
+        self.lines = []
+
+    def flush(self):
+        l = []
+        for line in self.lines:
+            l.append(self._format_code(line))
+        self.lines = []
+        return "".join(l)
+
+class ReverseWrapper(object):
+    '''Object that generates a C->Python wrapper'''
+    def __init__(self, cname, is_static=True):
+        assert isinstance(cname, str)
+
+        self.cname = cname
+        ## function object we will call, or object whose method we will call
+        self.called_pyobj = None
+        ## name of method of self.called_pyobj we will call
+        self.method_name = None
+        self.is_static = is_static
+
+        self.parameters = []
+        self.declarations = MemoryCodeSink()
+        self.post_return_code = MemoryCodeSink()
+        self.body = MemoryCodeSink()
+        self.check_exception_code = MemoryCodeSink()
+        self.cleanup_actions = []
+        self.pyargv_items = []
+        self.pyargv_optional_items = []
+        self.pyret_parse_items = [] # list of (format_spec, parameter)
+        self.code_sinks_stack = [self.body]
+
+    def set_call_target(self, called_pyobj, method_name=None):
+        assert called_pyobj is not None
+        assert self.called_pyobj is None
+        self.called_pyobj = called_pyobj
+        self.method_name = method_name
+
+    def set_return_type(self, return_type):
+        assert isinstance(return_type, ReturnType)
+        self.return_type = return_type
+
+    def add_parameter(self, param):
+        assert isinstance(param, Parameter)
+        self.parameters.append(param)
+
+    def add_declaration(self, decl_code):
+        self.declarations.writeln(decl_code)
+
+    def add_pyargv_item(self, variable, optional=False):
+        if optional:
+            self.pyargv_optional_items.append(variable)
+        else:
+            self.pyargv_items.append(variable)
+
+    def add_pyret_parse_item(self, format_specifier, parameter, prepend=False):
+        if prepend:
+            self.pyret_parse_items.insert(0, (format_specifier, parameter))
+        else:
+            self.pyret_parse_items.append((format_specifier, parameter))
+
+
+    def push_code_sink(self, code_sink):
+        self.code_sinks_stack.insert(0, code_sink)
+
+    def pop_code_sink(self):
+        return self.code_sinks_stack.pop(0)
+
+
+    def write_code(self, code,
+                   cleanup=None,
+                   failure_expression=None,
+                   failure_cleanup=None,
+                   failure_exception=None,
+                   code_sink=None):
+        '''Add a chunk of code with cleanup and error handling
+
+        This method is to be used by TypeHandlers when generating code
+
+        Keywork arguments:
+        code -- code to add
+        cleanup -- code to cleanup any dynamic resources created by @code
+                   (except in case of failure) (default None)
+        failure_expression -- C boolean expression to indicate
+                              if anything failed (default None)
+        failure_cleanup -- code to cleanup any dynamic resources
+                           created by @code in case of failure (default None)
+        failure_exception -- code to raise an exception in case of
+                             failure (which will be immediately
+                             printed and cleared), (default None)
+        code_sink -- "code sink" to use; by default,
+                      ReverseWrapper.body is used, which writes the
+                      main body of the wrapper, before calling the
+                      python method.  Alternatively,
+                      ReverseWrapper.after_pyret_parse can be used, to
+                      write code after the PyArg_ParseTuple that
+                      parses the python method return value.
+        '''
+        if code_sink is None:
+            code_sink = self.code_sinks_stack[0]
+        if code is not None:
+            code_sink.writeln(code)
+        if failure_expression is not None:
+            code_sink.writeln("if (%s) {" % (failure_expression,))
+            code_sink.indent()
+            if failure_exception is None:
+                code_sink.writeln("if (PyErr_Occurred())")
+                code_sink.indent()
+                code_sink.writeln("PyErr_Print();")
+                code_sink.unindent()
+            else:
+                code_sink.writeln(failure_exception)
+                code_sink.writeln("PyErr_Print();")
+            if failure_cleanup is not None:
+                code_sink.writeln(failure_cleanup)
+            for cleanup_action in self.cleanup_actions:
+                code_sink.writeln(cleanup_action)
+
+            self.push_code_sink(code_sink)
+            try:
+                self.return_type.write_error_return()
+            finally:
+                self.pop_code_sink()
+
+            code_sink.unindent()
+            code_sink.writeln("}")
+        if cleanup is not None:
+            self.cleanup_actions.insert(0, cleanup)
+
+    def generate(self, sink):
+        '''Generate the code into a CodeSink object'''
+        assert isinstance(sink, CodeSink)
+
+        if DEBUG_MODE:
+            self.declarations.writeln("/* begin declarations */")
+            self.body.writeln("/* begin main body */")
+            self.post_return_code.writeln("/* begin post-return code */")
+
+        self.add_declaration("PyGILState_STATE __py_state;")
+        self.write_code(code="__py_state = pyg_gil_state_ensure();",
+                        cleanup="pyg_gil_state_release(__py_state);")
+
+        for param in self.parameters:
+            param.convert_c2py()
+
+        assert self.called_pyobj is not None,\
+               "Parameters failed to provide a target function or method."
+
+        if self.is_static:
+            sink.writeln('static %s' % self.return_type.get_c_type())
+        else:
+            sink.writeln(self.return_type.get_c_type())
+        c_proto_params = list(map(Parameter.format_for_c_proto, self.parameters))
+        sink.writeln("%s(%s)\n{" % (self.cname, ", ".join(c_proto_params)))
+
+        self.return_type.write_decl()
+        self.add_declaration("PyObject *py_retval;")
+
+        ## Handle number of arguments
+        if self.pyargv_items:
+            self.add_declaration("PyObject *py_args;")
+            py_args = "py_args"
+            if self.pyargv_optional_items:
+                self.add_declaration("int argc = %i;" % len(self.pyargv_items))
+                argc = "argc"
+                for arg in self.pyargv_optional_items:
+                    self.body.writeln("if (%s)" % arg)
+                    self.body.indent()
+                    self.body.writeln("++argc;")
+                    self.body.unindent()
+            else:
+                argc = str(len(self.pyargv_items))
+        else:
+            if self.pyargv_optional_items:
+                self.add_declaration("PyObject *py_args;")
+                py_args = "py_args"
+                self.add_declaration("int argc = 0;")
+                argc = "argc"
+                for arg in self.pyargv_optional_items:
+                    self.body.writeln("if (%s)" % arg)
+                    self.body.indent()
+                    self.body.writeln("++argc;")
+                    self.body.unindent()
+            else:
+                py_args = "NULL"
+                argc = None
+
+        self.body.writeln()
+
+        if py_args != "NULL":
+            self.write_code("py_args = PyTuple_New(%s);" % argc,
+                            cleanup="Py_DECREF(py_args);")
+            pos = 0
+            for arg in self.pyargv_items:
+                try: # try to remove the Py_DECREF cleanup action, if we can
+                    self.cleanup_actions.remove("Py_DECREF(%s);" % arg)
+                except ValueError: # otherwise we have to Py_INCREF..
+                    self.body.writeln("Py_INCREF(%s);" % arg)
+                self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg))
+                pos += 1
+            for arg in self.pyargv_optional_items:
+                self.body.writeln("if (%s) {" % arg)
+                self.body.indent()
+                try: # try to remove the Py_DECREF cleanup action, if we can
+                    self.cleanup_actions.remove("Py_XDECREF(%s);" % arg)
+                except ValueError: # otherwise we have to Py_INCREF..
+                    self.body.writeln("Py_INCREF(%s);" % arg)
+                self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg))
+                self.body.unindent()
+                self.body.writeln("}")
+                pos += 1
+
+        self.body.writeln()
+
+        ## Call the python method
+        if self.method_name is None:
+            self.write_code("py_retval = PyObject_Call(%s, %s);"
+                            % (self.called_pyobj, py_args),
+                            cleanup="Py_XDECREF(py_retval);")
+            self.check_exception_code.flush_to(self.body)
+            self.write_code(None, failure_expression="!py_retval")
+
+        else:
+            self.add_declaration("PyObject *py_method;")
+            self.write_code("py_method = PyObject_GetAttrString(%s, \"%s\");"
+                            % (self.called_pyobj, self.method_name),
+                            cleanup="Py_DECREF(py_method);",
+                            failure_expression="!py_method")
+            self.write_code("py_retval = PyObject_CallObject(py_method, %s);"
+                            % (py_args,),
+                            cleanup="Py_XDECREF(py_retval);")
+            self.check_exception_code.flush_to(self.body)
+            self.write_code(None, failure_expression="!py_retval")
+
+        ## -- Handle the return value --
+
+        ## we need to check if the return_type object is prepared to cooperate with multiple return values
+        len_before = len(self.pyret_parse_items)
+        self.return_type.write_conversion()
+        len_after = len(self.pyret_parse_items)
+        assert (self.return_type.get_c_type() == 'void'
+                or not (len_before == len_after and len_after > 0)),\
+               ("Bug in reverse wrappers: return type handler %s"
+                " is not prepared to cooperate multiple return values") % (type(self.return_type),)
+
+        sink.indent()
+
+        if self.pyret_parse_items == [("", "")]:
+            ## special case when there are no return parameters
+            self.write_code(
+                code=None,
+                failure_expression='py_retval != Py_None',
+                failure_exception=('PyErr_SetString(PyExc_TypeError, '
+                                   '"virtual method should return None");'))
+        else:    
+            if len(self.pyret_parse_items) == 1:
+                ## if retval is one item only, pack it in a tuple so we
+                ## can use PyArg_ParseTuple as usual..
+                self.write_code('py_retval = Py_BuildValue("(N)", py_retval);')
+            if len(self.pyret_parse_items) > 0:
+                ## Parse return values using PyArg_ParseTuple
+                params = ["py_retval",
+                          '"%s"' % "".join([format for format, param in self.pyret_parse_items])]
+                params.extend([param for format, param in self.pyret_parse_items if param])
+                self.write_code(code=None, failure_expression=(
+                    '!PyArg_ParseTuple(%s)' % (', '.join(params),)))
+
+        if DEBUG_MODE:
+            self.declarations.writeln("/* end declarations */")
+        self.declarations.flush_to(sink)
+        sink.writeln()
+        if DEBUG_MODE:
+            self.body.writeln("/* end main body */")
+        self.body.flush_to(sink)
+        sink.writeln()
+        if DEBUG_MODE:
+            self.post_return_code.writeln("/* end post-return code */")
+        self.post_return_code.flush_to(sink)
+        sink.writeln()
+
+        for cleanup_action in self.cleanup_actions:
+            sink.writeln(cleanup_action)
+        if self.return_type.get_c_type() != 'void':
+            sink.writeln()
+            sink.writeln("return retval;")
+        sink.unindent()
+        sink.writeln("}")
+
+class TypeHandler(object):
+    def __init__(self, wrapper, **props):
+        assert isinstance(wrapper, ReverseWrapper)
+        self.wrapper = wrapper
+        self.props = props
+
+class ReturnType(TypeHandler):
+
+    supports_optional = False
+
+    def get_c_type(self):
+        raise NotImplementedError
+
+    def write_decl(self):
+        raise NotImplementedError
+
+    def write_error_return(self):
+        '''Write "return <value>" code in case of error'''
+        raise NotImplementedError
+
+    def write_conversion(self):
+        '''Writes code to convert Python return value in 'py_retval'
+        into C 'retval'.  Returns a string with C boolean expression
+        that determines if anything went wrong. '''
+        raise NotImplementedError
+
+class Parameter(TypeHandler):
+
+    def __init__(self, wrapper, name, **props):
+        TypeHandler.__init__(self, wrapper, **props)
+        self.name = name
+
+    def get_c_type(self):
+        raise NotImplementedError
+
+    def convert_c2py(self):
+        '''Write some code before calling the Python method.'''
+        pass
+
+    def format_for_c_proto(self):
+        return join_ctype_name(self.get_c_type(), self.name)
+
+
+###---
+class StringParam(Parameter):
+
+    def get_c_type(self):
+        return self.props.get('c_type', 'char *').replace('const-', 'const ')
+
+    def convert_c2py(self):
+        if self.props.get('optional', False):
+            self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name)
+            self.wrapper.write_code(code=("if (%s)\n"
+                                          "    py_%s = _PyUnicode_FromString(%s);\n"
+                                          % (self.name, self.name, self.name)),
+                                    cleanup=("Py_XDECREF(py_%s);" % self.name))
+            self.wrapper.add_pyargv_item("py_%s" % self.name, optional=True)
+        else:
+            self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+            self.wrapper.write_code(code=("py_%s = _PyUnicode_FromString(%s);" %
+                                          (self.name, self.name)),
+                                    cleanup=("Py_DECREF(py_%s);" % self.name),
+                                    failure_expression=("!py_%s" % self.name))
+            self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+for ctype in ('char*', 'gchar*', 'const-char*', 'char-const*', 'const-gchar*',
+              'gchar-const*', 'string', 'static_string'):
+    argtypes.matcher.register_reverse(ctype, StringParam)
+del ctype
+
+class StringReturn(ReturnType):
+
+    def get_c_type(self):
+        return self.props.get('c_type', 'char *').replace('const-', 'const ')
+    #return "char *"
+
+    def write_decl(self):
+        self.wrapper.add_declaration("%s retval;" % self.get_c_type())
+        #self.wrapper.add_declaration("char *retval;")
+
+    def write_error_return(self):
+        self.wrapper.write_code("return NULL;")
+
+    def write_conversion(self):
+        self.wrapper.add_pyret_parse_item("s", "&retval", prepend=True)
+        self.wrapper.write_code("retval = g_strdup(retval);", code_sink=self.wrapper.post_return_code)
+
+for ctype in ('char*', 'gchar*', 'const-gchar*'):
+    argtypes.matcher.register_reverse_ret(ctype, StringReturn)
+del ctype
+
+
+class VoidReturn(ReturnType):
+
+    def get_c_type(self):
+        return "void"
+
+    def write_decl(self):
+        pass
+
+    def write_error_return(self):
+        self.wrapper.write_code("return;")
+
+    def write_conversion(self):
+        self.wrapper.add_pyret_parse_item("", "", prepend=True)
+
+argtypes.matcher.register_reverse_ret('void', VoidReturn)
+argtypes.matcher.register_reverse_ret('none', VoidReturn)
+
+class GObjectParam(Parameter):
+
+    def get_c_type(self):
+        return self.props.get('c_type', 'GObject *')
+
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name)
+        self.wrapper.write_code(code=("if (%s)\n"
+                                      "    py_%s = pygobject_new((GObject *) %s);\n"
+                                      "else {\n"
+                                      "    Py_INCREF(Py_None);\n"
+                                      "    py_%s = Py_None;\n"
+                                      "}"
+                                      % (self.name, self.name, self.name, self.name)),
+                                cleanup=("Py_DECREF(py_%s);" % self.name))
+        self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+argtypes.matcher.register_reverse('GObject*', GObjectParam)
+
+class GObjectReturn(ReturnType):
+
+    supports_optional = True
+
+    def get_c_type(self):
+        return self.props.get('c_type', 'GObject *')
+
+    def write_decl(self):
+        if not self.props.get('optional'):
+            self.wrapper.add_declaration("%s retval;" % self.get_c_type())
+        else:
+            self.wrapper.add_declaration("%s retval = NULL;" % self.get_c_type())
+
+    def write_error_return(self):
+        self.wrapper.write_code("return NULL;")
+
+    def write_conversion(self):
+        if not self.props.get('optional'):
+            self.wrapper.write_code(
+                code=None,
+                failure_expression="!PyObject_TypeCheck(py_retval, &PyGObject_Type)",
+                failure_exception='PyErr_SetString(PyExc_TypeError, "retval should be a GObject");')
+            self.wrapper.write_code("retval = (%s) pygobject_get(py_retval);"
+                                    % self.get_c_type())
+            self.wrapper.write_code("g_object_ref((GObject *) retval);")
+        else:
+            self.wrapper.write_code(
+                code=None,
+                failure_expression="py_retval != Py_None && !PyObject_TypeCheck(py_retval, &PyGObject_Type)",
+                failure_exception='PyErr_SetString(PyExc_TypeError, "retval should be None or a GObject");')
+            self.wrapper.write_code("if (py_retval != Py_None) {\n"
+                                    "    retval = (%s) pygobject_get(py_retval);\n"
+                                    "    g_object_ref((GObject *) retval);\n"
+                                    "}\n"
+                                    % self.get_c_type())
+
+argtypes.matcher.register_reverse_ret('GObject*', GObjectReturn)
+
+
+
+class IntParam(Parameter):
+
+    def get_c_type(self):
+        return self.props.get('c_type', 'int')
+
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+        self.wrapper.write_code(code=("py_%s = _PyLong_FromLong(%s);" %
+                                      (self.name, self.name)),
+                                cleanup=("Py_DECREF(py_%s);" % self.name))
+        self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+class IntReturn(ReturnType):
+    def get_c_type(self):
+        return self.props.get('c_type', 'int')
+    def write_decl(self):
+        self.wrapper.add_declaration("%s retval;" % self.get_c_type())
+    def write_error_return(self):
+        self.wrapper.write_code("return -G_MAXINT;")
+    def write_conversion(self):
+        self.wrapper.add_pyret_parse_item("i", "&retval", prepend=True)
+
+for argtype in ('int', 'gint', 'guint', 'short', 'gshort', 'gushort', 'long',
+                'glong', 'gsize', 'gssize', 'guint8', 'gint8', 'guint16',
+                'gint16', 'gint32', 'GTime'):
+    argtypes.matcher.register_reverse(argtype, IntParam)
+    argtypes.matcher.register_reverse_ret(argtype, IntReturn)
+del argtype
+
+class IntPtrParam(Parameter):
+    def __init__(self, wrapper, name, **props):
+        if "direction" not in props:
+            raise argtypes.ArgTypeConfigurationError(
+                "cannot use int* parameter without direction")
+        if props["direction"] not in ("out", "inout"):
+            raise argtypes.ArgTypeConfigurationError(
+                "cannot use int* parameter with direction '%s'"
+                % (props["direction"],))
+        Parameter.__init__(self, wrapper, name, **props)
+    def get_c_type(self):
+        return self.props.get('c_type', 'int*')
+    def convert_c2py(self):
+        if self.props["direction"] == "inout":
+            self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+            self.wrapper.write_code(code=("py_%s = _PyLong_FromLong(*%s);" %
+                                          (self.name, self.name)),
+                                    cleanup=("Py_DECREF(py_%s);" % self.name))
+            self.wrapper.add_pyargv_item("py_%s" % self.name)
+        self.wrapper.add_pyret_parse_item("i", self.name)
+for argtype in ('int*', 'gint*'):
+    argtypes.matcher.register_reverse(argtype, IntPtrParam)
+del argtype
+
+
+class GEnumReturn(IntReturn):
+    def write_conversion(self):
+        self.wrapper.write_code(
+            code=None,
+            failure_expression=(
+            "pyg_enum_get_value(%s, py_retval, (gint *)&retval)"
+            % (self.props['typecode'],)))
+
+argtypes.matcher.register_reverse_ret("GEnum", GEnumReturn)
+
+class GEnumParam(IntParam):
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+        self.wrapper.write_code(code=("py_%s = pyg_enum_from_gtype(%s, %s);" %
+                                (self.name, self.props['typecode'], self.name)),
+                        cleanup=("Py_DECREF(py_%s);" % self.name),
+                        failure_expression=("!py_%s" % self.name))
+        self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+argtypes.matcher.register_reverse("GEnum", GEnumParam)
+
+class GFlagsReturn(IntReturn):
+    def write_conversion(self):
+        self.wrapper.write_code(
+            code=None,
+            failure_expression=(
+            "pyg_flags_get_value(%s, py_retval, (gint *)&retval)" %
+            self.props['typecode']))
+
+argtypes.matcher.register_reverse_ret("GFlags", GFlagsReturn)
+
+class GFlagsParam(IntParam):
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+        self.wrapper.write_code(code=(
+            "py_%s = pyg_flags_from_gtype(%s, %s);" %
+            (self.name, self.props['typecode'], self.name)),
+                                cleanup=("Py_DECREF(py_%s);" % self.name),
+                                failure_expression=("!py_%s" % self.name))
+        self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+argtypes.matcher.register_reverse("GFlags", GFlagsParam)
+
+
+class GtkTreePathParam(IntParam):
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+        self.wrapper.write_code(code=(
+            "py_%s = pygtk_tree_path_to_pyobject(%s);" %
+            (self.name, self.name)),
+                                cleanup=("Py_DECREF(py_%s);" % self.name),
+                                failure_expression=("!py_%s" % self.name))
+        self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+argtypes.matcher.register_reverse("GtkTreePath*", GtkTreePathParam)
+
+
+class GtkTreePathReturn(ReturnType):
+    def get_c_type(self):
+        return self.props.get('c_type', 'GtkTreePath *')
+    def write_decl(self):
+        self.wrapper.add_declaration("GtkTreePath * retval;")
+    def write_error_return(self):
+        self.wrapper.write_code("return NULL;")
+    def write_conversion(self):
+        self.wrapper.write_code(
+            "retval = pygtk_tree_path_from_pyobject(py_retval);\n",
+            failure_expression=('!retval'),
+            failure_exception=(
+    'PyErr_SetString(PyExc_TypeError, "retval should be a GtkTreePath");'))
+
+argtypes.matcher.register_reverse_ret("GtkTreePath*", GtkTreePathReturn)
+
+
+class BooleanReturn(ReturnType):
+    def get_c_type(self):
+        return "gboolean"
+    def write_decl(self):
+        self.wrapper.add_declaration("gboolean retval;")
+        self.wrapper.add_declaration("PyObject *py_main_retval;")
+    def write_error_return(self):
+        self.wrapper.write_code("return FALSE;")
+    def write_conversion(self):
+        self.wrapper.add_pyret_parse_item("O", "&py_main_retval", prepend=True)
+        self.wrapper.write_code(
+            "retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;",
+            code_sink=self.wrapper.post_return_code)
+argtypes.matcher.register_reverse_ret("gboolean", BooleanReturn)
+
+class BooleanParam(Parameter):
+    def get_c_type(self):
+        return "gboolean"
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+        self.wrapper.write_code("py_%s = %s? Py_True : Py_False;"
+                                % (self.name, self.name))
+        self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+argtypes.matcher.register_reverse("gboolean", BooleanParam)
+
+
+class DoubleParam(Parameter):
+    def get_c_type(self):
+        return self.props.get('c_type', 'gdouble')
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+        self.wrapper.write_code(code=("py_%s = PyFloat_FromDouble(%s);" %
+                                      (self.name, self.name)),
+                                cleanup=("Py_DECREF(py_%s);" % self.name))
+        self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+class DoublePtrParam(Parameter):
+    def __init__(self, wrapper, name, **props):
+        if "direction" not in props:
+            raise argtypes.ArgTypeConfigurationError(
+                "cannot use double* parameter without direction")
+        if props["direction"] not in ("out", ): # inout not yet implemented
+            raise argtypes.ArgTypeConfigurationError(
+                "cannot use double* parameter with direction '%s'"
+                % (props["direction"],))
+        Parameter.__init__(self, wrapper, name, **props)
+    def get_c_type(self):
+        return self.props.get('c_type', 'double*')
+    def convert_c2py(self):
+        self.wrapper.add_pyret_parse_item("d", self.name)
+for argtype in ('double*', 'gdouble*'):
+    argtypes.matcher.register_reverse(argtype, DoublePtrParam)
+del argtype
+
+class DoubleReturn(ReturnType):
+    def get_c_type(self):
+        return self.props.get('c_type', 'gdouble')
+    def write_decl(self):
+        self.wrapper.add_declaration("%s retval;" % self.get_c_type())
+    def write_error_return(self):
+        self.wrapper.write_code("return -G_MAXFLOAT;")
+    def write_conversion(self):
+        self.wrapper.add_pyret_parse_item("d", "&retval", prepend=True)
+
+for argtype in ('float', 'double', 'gfloat', 'gdouble'):
+    argtypes.matcher.register_reverse(argtype, DoubleParam)
+    argtypes.matcher.register_reverse_ret(argtype, DoubleReturn)
+
+
+class GBoxedParam(Parameter):
+    def get_c_type(self):
+        return self.props.get('c_type').replace('const-', 'const ')
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+        ctype = self.get_c_type()
+        if ctype.startswith('const '):
+            ctype_no_const = ctype[len('const '):]
+            self.wrapper.write_code(
+                code=('py_%s = pyg_boxed_new(%s, (%s) %s, TRUE, TRUE);' %
+                      (self.name, self.props['typecode'],
+                       ctype_no_const, self.name)),
+                cleanup=("Py_DECREF(py_%s);" % self.name))
+        else:
+            self.wrapper.write_code(
+                code=('py_%s = pyg_boxed_new(%s, %s, FALSE, FALSE);' %
+                      (self.name, self.props['typecode'], self.name)),
+                cleanup=("Py_DECREF(py_%s);" % self.name))
+        self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+argtypes.matcher.register_reverse("GBoxed", GBoxedParam)
+
+
+class GBoxedReturn(ReturnType):
+    def get_c_type(self):
+        return self.props.get('c_type')
+    def write_decl(self):
+        self.wrapper.add_declaration("%s retval;" % self.get_c_type())
+    def write_error_return(self):
+        self.wrapper.write_code("return retval;")
+    def write_conversion(self):
+        self.wrapper.write_code(code = None,
+            failure_expression=("!pyg_boxed_check(py_retval, %s)" %
+                                (self.props['typecode'],)),
+            failure_exception=(
+            'PyErr_SetString(PyExc_TypeError, "retval should be a %s");'
+            % (self.props['typename'],)))
+        self.wrapper.write_code('retval = pyg_boxed_get(py_retval, %s);' %
+                                self.props['typename'])
+
+argtypes.matcher.register_reverse_ret("GBoxed", GBoxedReturn)
+
+
+class GdkRegionPtrReturn(GBoxedReturn):
+    def write_error_return(self):
+        self.wrapper.write_code("return gdk_region_new();")
+    def write_conversion(self):
+        self.props['typecode'] = 'PYGDK_TYPE_REGION'
+        self.props['typename'] = 'GdkRegion'
+        super(GdkRegionPtrReturn, self).write_conversion()
+
+argtypes.matcher.register_reverse_ret("GdkRegion*", GdkRegionPtrReturn)
+
+
+class PangoFontDescriptionReturn(GBoxedReturn):
+    def write_error_return(self):
+        self.wrapper.write_code("return pango_font_description_new();")
+    def write_conversion(self):
+        self.props['typecode'] = 'PANGO_TYPE_FONT_DESCRIPTION'
+        self.props['typename'] = 'PangoFontDescription'
+        super(PangoFontDescriptionReturn, self).write_conversion()
+
+argtypes.matcher.register_reverse_ret("PangoFontDescription*",
+                                      PangoFontDescriptionReturn)
+
+
+class PangoFontMetricsReturn(GBoxedReturn):
+    def write_error_return(self):
+        self.wrapper.write_code("return pango_font_metrics_new();")
+    def write_conversion(self):
+        self.props['typecode'] = 'PANGO_TYPE_FONT_METRICS'
+        self.props['typename'] = 'PangoFontMetrics'
+        super(PangoFontMetricsReturn, self).write_conversion()
+
+argtypes.matcher.register_reverse_ret("PangoFontMetrics*",
+                                      PangoFontMetricsReturn)
+
+
+class PangoLanguageReturn(GBoxedReturn):
+    def write_error_return(self):
+        self.wrapper.write_code("return pango_language_from_string(\"\");")
+    def write_conversion(self):
+        self.props['typecode'] = 'PANGO_TYPE_LANGUAGE'
+        self.props['typename'] = 'PangoLanguage'
+        super(PangoLanguageReturn, self).write_conversion()
+
+argtypes.matcher.register_reverse_ret("PangoLanguage*", PangoLanguageReturn)
+
+
+class GdkRectanglePtrParam(Parameter):
+    def get_c_type(self):
+        return self.props.get('c_type').replace('const-', 'const ')
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+        self.wrapper.write_code(
+            code=('py_%s = pyg_boxed_new(GDK_TYPE_RECTANGLE, %s, TRUE, TRUE);' %
+                  (self.name, self.name)),
+            cleanup=("Py_DECREF(py_%s);" % self.name))
+        self.wrapper.add_pyargv_item("py_%s" % self.name)
+
+argtypes.matcher.register_reverse("GdkRectangle*", GdkRectanglePtrParam)
+argtypes.matcher.register_reverse('GtkAllocation*', GdkRectanglePtrParam)
+
+
+class GErrorParam(Parameter):
+    def get_c_type(self):
+        return self.props.get('c_type').replace('**', ' **')
+    def convert_c2py(self):
+        self.wrapper.write_code(code=None,
+            failure_expression=("pyg_gerror_exception_check(%s)" % self.name),
+                                code_sink=self.wrapper.check_exception_code)
+
+argtypes.matcher.register_reverse('GError**', GErrorParam)
+
+
+class PyGObjectMethodParam(Parameter):
+    def __init__(self, wrapper, name, method_name, **props):
+        Parameter.__init__(self, wrapper, name, **props)
+        self.method_name = method_name
+
+    def get_c_type(self):
+        return self.props.get('c_type', 'GObject *')
+
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
+        self.wrapper.write_code(code=("py_%s = pygobject_new((GObject *) %s);" %
+                                      (self.name, self.name)),
+                                cleanup=("Py_DECREF(py_%s);" % self.name),
+                                failure_expression=("!py_%s" % self.name))
+        self.wrapper.set_call_target("py_%s" % self.name, self.method_name)
+
+
+class CallbackInUserDataParam(Parameter):
+    def __init__(self, wrapper, name, free_it, **props):
+        Parameter.__init__(self, wrapper, name, **props)
+        self.free_it = free_it
+
+    def get_c_type(self):
+        return "gpointer"
+
+    def convert_c2py(self):
+        self.wrapper.add_declaration("PyObject **_user_data;")
+        cleanup = self.free_it and ("g_free(%s);" % self.name) or None
+        self.wrapper.write_code(code=("_real_user_data = (PyObject **) %s;"
+                                      % self.name),
+                                cleanup=cleanup)
+
+        self.wrapper.add_declaration("PyObject *py_func;")
+        cleanup = self.free_it and "Py_DECREF(py_func);" or None
+        self.wrapper.write_code(code="py_func = _user_data[0];",
+                                cleanup=cleanup)
+        self.wrapper.set_call_target("py_func")
+
+        self.wrapper.add_declaration("PyObject *py_user_data;")
+        cleanup = self.free_it and "Py_XDECREF(py_user_data);" or None
+        self.wrapper.write_code(code="py_user_data = _user_data[1];",
+                                cleanup=cleanup)
+        self.wrapper.add_pyargv_item("py_user_data", optional=True)
+
+def _test():
+    import sys
+
+    if 1:
+        wrapper = ReverseWrapper("this_is_the_c_function_name", is_static=True)
+        wrapper.set_return_type(StringReturn(wrapper))
+        wrapper.add_parameter(PyGObjectMethodParam(wrapper, "self", method_name="do_xxx"))
+        wrapper.add_parameter(StringParam(wrapper, "param2", optional=True))
+        wrapper.add_parameter(GObjectParam(wrapper, "param3"))
+        #wrapper.add_parameter(InoutIntParam(wrapper, "param4"))
+        wrapper.generate(FileCodeSink(sys.stderr))
+
+    if 0:
+        wrapper = ReverseWrapper("this_a_callback_wrapper")
+        wrapper.set_return_type(VoidReturn(wrapper))
+        wrapper.add_parameter(StringParam(wrapper, "param1", optional=False))
+        wrapper.add_parameter(GObjectParam(wrapper, "param2"))
+        wrapper.add_parameter(CallbackInUserDataParam(wrapper, "data", free_it=True))
+        wrapper.generate(FileCodeSink(sys.stderr))
+
+if __name__ == '__main__':
+    _test()
diff --git a/codegen/libcodegen/scmexpr.py b/codegen/libcodegen/scmexpr.py
new file mode 100644
index 0000000..65a8f41
--- /dev/null
+++ b/codegen/libcodegen/scmexpr.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+# -*- Mode: Python; py-indent-offset: 4 -*-
+from __future__ import generators
+
+from libcodegen.string_compat import string
+
+try:
+    from io import StringIO
+except ImportError:
+    from cStringIO import StringIO
+
+class error(Exception):
+    def __init__(self, filename, lineno, msg):
+        Exception.__init__(self, msg)
+        self.filename = filename
+        self.lineno = lineno
+        self.msg = msg
+    def __str__(self):
+        return '%s:%d: error: %s' % (self.filename, self.lineno, self.msg)
+
+trans = [' '] * 256
+for i in range(256):
+    if chr(i) in string.letters + string.digits + '_':
+        trans[i] = chr(i)
+    else:
+        trans[i] = '_'
+trans = string.join(trans, '')
+
+def parse(filename):
+    if isinstance(filename, str):
+        fp = open(filename, 'r')
+    else: # if not string, assume it is some kind of iterator
+        fp = filename
+        filename = getattr(fp, 'name', '<unknown>')
+    whitespace = ' \t\n\r\x0b\x0c'
+    nonsymbol = whitespace + '();\'"'
+    stack = []
+    openlines = []
+    lineno = 0
+    for line in fp:
+        pos = 0
+        lineno += 1
+        while pos < len(line):
+            if line[pos] in whitespace: # ignore whitespace
+                pass
+            elif line[pos] == ';': # comment
+                break
+            elif line[pos:pos+2] == "'(":
+                pass # the open parenthesis will be handled next iteration
+            elif line[pos] == '(':
+                stack.append(())
+                openlines.append(lineno)
+            elif line[pos] == ')':
+                if len(stack) == 0:
+                    raise error(filename, lineno, 'close parenthesis found when none open')
+                closed = stack[-1]
+                del stack[-1]
+                del openlines[-1]
+                if stack:
+                    stack[-1] += (closed,)
+                else:
+                    yield closed
+            elif line[pos] == '"': # quoted string
+                if not stack:
+                    raise error(filename, lineno,
+                                'string found outside of s-expression')
+                endpos = pos + 1
+                chars = []
+                while endpos < len(line):
+                    if endpos+1 < len(line) and line[endpos] == '\\':
+                        endpos += 1
+                        if line[endpos] == 'n':
+                            chars.append('\n')
+                        elif line[endpos] == 'r':
+                            chars.append('\r')
+                        elif line[endpos] == 't':
+                            chars.append('\t')
+                        else:
+                            chars.append('\\')
+                            chars.append(line[endpos])
+                    elif line[endpos] == '"':
+                        break
+                    else:
+                        chars.append(line[endpos])
+                    endpos += 1
+                if endpos >= len(line):
+                    raise error(filename, lineno, "unclosed quoted string")
+                pos = endpos
+                stack[-1] += (''.join(chars),)
+            else: # symbol/number
+                if not stack:
+                    raise error(filename, lineno,
+                                'identifier found outside of s-expression')
+                endpos = pos
+                while endpos < len(line) and line[endpos] not in nonsymbol:
+                    endpos += 1
+                symbol = line[pos:endpos]
+                pos = max(pos, endpos-1)
+                try: symbol = int(symbol)
+                except ValueError:
+                    try: symbol = float(symbol)
+                    except ValueError: pass
+                stack[-1] += (symbol,)
+            pos += 1
+    if len(stack) != 0:
+        msg = '%d unclosed parentheses found at end of ' \
+              'file (opened on line(s) %s)' % (len(stack),
+                                               ', '.join(map(str, openlines)))
+        raise error(filename, lineno, msg)
+
+class Parser:
+    def __init__(self, filename):
+        """Argument is either a string, a parse tree, or file object"""
+        self.filename = filename
+    def startParsing(self, filename=None):
+        statements = parse(filename or self.filename)
+        for statement in statements:
+            self.handle(statement)
+    def handle(self, tup):
+        cmd = string.translate(tup[0], trans)
+        if hasattr(self, cmd):
+            getattr(self, cmd)(*tup[1:])
+        else:
+            self.unknown(tup)
+    def unknown(self, tup):
+        pass
+
+_testString = """; a scheme file
+(define-func gdk_font_load    ; a comment at end of line
+  GdkFont
+  ((string name)))
+
+(define-boxed GdkEvent
+  gdk_event_copy
+  gdk_event_free
+  "sizeof(GdkEvent)")
+"""
+
+if __name__ == '__main__':
+    import sys
+    if sys.argv[1:]:
+        fp = open(sys.argv[1])
+    else:
+        fp = StringIO(_testString)
+    statements = parse(fp)
+    for s in statements:
+        sys.stdout.write("%s\n" % repr(s))
diff --git a/codegen/libcodegen/string_compat.py b/codegen/libcodegen/string_compat.py
new file mode 100644
index 0000000..220c900
--- /dev/null
+++ b/codegen/libcodegen/string_compat.py
@@ -0,0 +1,41 @@
+
+import string
+
+try:
+    string.letters
+except AttributeError:
+    string.letters = string.ascii_letters
+    def _join(some_list, sep=""):
+        return sep.join(some_list)
+    string.join = _join
+    del _join
+
+    def _translate(s, table, deletions=""):
+        return s.translate(table)
+    string.translate = _translate
+    del _translate
+
+    def _replace(*args): 
+        return args[0].replace(*args[1:])
+    string.replace = _replace
+    del _replace
+
+    def _find(s, something):
+        return s.find(something)
+    string.find = _find
+    del _find
+    
+    def _split(s, sep=None, maxsplit=-1):
+        return s.split(sep, maxsplit)
+    string.split = _split
+    del _split
+    
+    def _count(s, pattern):
+        return s.count(pattern)
+    string.count = _count
+    del _count
+    
+    def _lower(s):
+        return s.lower()
+    string.lower = _lower
+    del _lower
\ No newline at end of file
diff --git a/codegen/mergedefs.py b/codegen/mergedefs.py
index 773e499..a600200 100755
--- a/codegen/mergedefs.py
+++ b/codegen/mergedefs.py
@@ -3,7 +3,7 @@
 
 import optparse
 
-import defsparser
+from libcodegen import defsparser
 
 parser = optparse.OptionParser(
     usage="usage: %prog [options] generated-defs old-defs")
diff --git a/codegen/missingdefs.py b/codegen/missingdefs.py
index f0017e7..b71963b 100755
--- a/codegen/missingdefs.py
+++ b/codegen/missingdefs.py
@@ -2,7 +2,7 @@
 # -*- Mode: Python; py-indent-offset: 4 -*-
 
 import sys
-import defsparser
+from libcodegen import defsparser
 
 if len(sys.argv) < 3:
     sys.stderr.write("Usage: missingdefs.py generated-defs old-defs\n")
diff --git a/codegen/mkskel.py b/codegen/mkskel.py
index 61f520b..74db062 100755
--- a/codegen/mkskel.py
+++ b/codegen/mkskel.py
@@ -81,9 +81,9 @@ if __name__ == '__main__':
         elif opt in ('-m', '--module'):
             module = arg
         elif opt in ('-h', '--help'):
-            print 'usage: mkskel.py -f fileprefix -p prefix -m module'
+            sys.stdout.write('usage: mkskel.py -f fileprefix -p prefix -m module\n')
             sys.exit(0)
     if not fileprefix or not prefix or not module:
-        print 'usage: mkskel.py -f fileprefix -p prefix -m module'
+        sys.stdout.write('usage: mkskel.py -f fileprefix -p prefix -m module\n')
         sys.exit(1)
     write_skels(fileprefix, prefix, module)
diff --git a/codegen/override.py b/codegen/override.py
deleted file mode 100644
index bba5e42..0000000
--- a/codegen/override.py
+++ /dev/null
@@ -1,285 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-
-# this file contains code for loading up an override file.  The override file
-# provides implementations of functions where the code generator could not
-# do its job correctly.
-
-import fnmatch
-import os
-import re
-import string
-import sys
-
-def class2cname(klass, method):
-    c_name = ''
-    for c in klass:
-        if c.isupper():
-            c_name += '_' + c.lower()
-        else:
-            c_name += c
-    return c_name[1:] + '_'  + method
-
-# import python_type as c_name [for arg_type]
-# Last ('for') clause is optional.  If present, the type will be
-# imported only if given 'arg_type' is registered.
-import_pat = re.compile(r'\s*import\s+(\S+)\.([^\s.]+)\s+as\s+(\S+)(\s+for\s+(\S+))?')
-
-class Overrides:
-    def __init__(self, filename=None):
-        self.modulename = None
-        self.ignores = {}
-        self.glob_ignores = []
-        self.type_ignores = {}
-        self.overrides = {}
-        self.overridden = {}
-        self.kwargs = {}
-        self.noargs = {}
-        self.onearg = {}
-        self.staticmethod = {}
-        self.classmethod = {}
-        self.startlines = {}
-        self.override_attrs = {}
-        self.override_slots = {}
-        self.headers = ''
-        self.body = ''
-        self.init = ''
-        self.imports = []
-        self.defines = {}
-        self.functions = {}
-        self.newstyle_constructors = {}
-        self.dynamicnamespace = False
-        if filename:
-            self.handle_file(filename)
-
-    def handle_file(self, filename):
-        oldpath = os.getcwd()
-
-        fp = open(filename, 'r')
-        dirname = os.path.dirname(os.path.abspath(filename))
-
-        if dirname != oldpath:
-            os.chdir(dirname)
-
-        # read all the components of the file ...
-        bufs = []
-        startline = 1
-        lines = []
-        line = fp.readline()
-        linenum = 1
-        while line:
-            if line == '%%\n' or line == '%%':
-                if lines:
-                    bufs.append((string.join(lines, ''), startline))
-                startline = linenum + 1
-                lines = []
-            else:
-                lines.append(line)
-            line = fp.readline()
-            linenum = linenum + 1
-        if lines:
-            bufs.append((string.join(lines, ''), startline))
-        if not bufs: return
-
-        for buf, startline in bufs:
-            self.__parse_override(buf, startline, filename)
-
-        os.chdir(oldpath)
-
-    def __parse_override(self, buffer, startline, filename):
-        pos = string.find(buffer, '\n')
-        if pos >= 0:
-            line = buffer[:pos]
-            rest = buffer[pos+1:]
-        else:
-            line = buffer ; rest = ''
-        words = string.split(line)
-        command = words[0]
-        if (command == 'ignore' or
-            command == 'ignore-' + sys.platform):
-            "ignore/ignore-platform [functions..]"
-            for func in words[1:]:
-                self.ignores[func] = 1
-            for func in string.split(rest):
-                self.ignores[func] = 1
-        elif (command == 'ignore-glob' or
-              command == 'ignore-glob-' + sys.platform):
-            "ignore-glob/ignore-glob-platform [globs..]"
-            for func in words[1:]:
-                self.glob_ignores.append(func)
-            for func in string.split(rest):
-                self.glob_ignores.append(func)
-        elif (command == 'ignore-type' or
-              command == 'ignore-type-' + sys.platform):
-            "ignore-type/ignore-type-platform [typenames..]"
-            for typename in words[1:]:
-                self.type_ignores[typename] = 1
-            for typename in string.split(rest):
-                self.type_ignores[typename] = 1
-        elif command == 'override':
-            "override function/method [kwargs|noargs|onearg] [staticmethod|classmethod]"
-            func = words[1]
-            if 'kwargs' in words[1:]:
-                self.kwargs[func] = 1
-            elif 'noargs' in words[1:]:
-                self.noargs[func] = 1
-            elif 'onearg' in words[1:]:
-                self.onearg[func] = True
-
-            if 'staticmethod' in words[1:]:
-                self.staticmethod[func] = True
-            elif 'classmethod' in words[1:]:
-                self.classmethod[func] = True
-            if func in self.overrides:
-                raise RuntimeError("Function %s is being overridden more than once" % (func,))
-            self.overrides[func] = rest
-            self.startlines[func] = (startline + 1, filename)
-        elif command == 'override-attr':
-            "override-slot Class.attr"
-            attr = words[1]
-            self.override_attrs[attr] = rest
-            self.startlines[attr] = (startline + 1, filename)
-        elif command == 'override-slot':
-            "override-slot Class.slot"
-            slot = words[1]
-            self.override_slots[slot] = rest
-            self.startlines[slot] = (startline + 1, filename)
-        elif command == 'headers':
-            "headers"
-            self.headers = '%s\n#line %d "%s"\n%s' % \
-                           (self.headers, startline + 1, filename, rest)
-        elif command == 'body':
-            "body"
-            self.body = '%s\n#line %d "%s"\n%s' % \
-                           (self.body, startline + 1, filename, rest)
-        elif command == 'init':
-            "init"
-            self.init = '%s\n#line %d "%s"\n%s' % \
-                        (self.init, startline + 1, filename, rest)
-        elif command == 'modulename':
-            "modulename name"
-            self.modulename = words[1]
-        elif command == 'include':
-            "include filename"
-            for filename in words[1:]:
-                self.handle_file(filename)
-            for filename in string.split(rest):
-                self.handle_file(filename)
-        elif command == 'import':
-            "import module1 [\n module2, \n module3 ...]"
-            for line in string.split(buffer, '\n'):
-                match = import_pat.match(line)
-                if match:
-                    module, pyname, cname, conditional, importing_for = match.groups()
-                    self.imports.append((module, pyname, cname, importing_for or None))
-        elif command == 'define':
-            "define funcname [kwargs|noargs|onearg] [classmethod|staticmethod]"
-            "define Class.method [kwargs|noargs|onearg] [classmethod|staticmethod]"
-            func = words[1]
-            klass = None
-            if func.find('.') != -1:
-                klass, func = func.split('.', 1)
-
-                if not self.defines.has_key(klass):
-                    self.defines[klass] = {}
-                self.defines[klass][func] = rest
-            else:
-                self.functions[func] = rest
-
-            if 'kwargs' in words[1:]:
-                self.kwargs[func] = 1
-            elif 'noargs' in words[1:]:
-                self.noargs[func] = 1
-            elif 'onearg' in words[1:]:
-                self.onearg[func] = 1
-
-            if 'staticmethod' in words[1:]:
-                self.staticmethod[func] = True
-            elif 'classmethod' in words[1:]:
-                self.classmethod[func] = True
-
-            self.startlines[func] = (startline + 1, filename)
-
-        elif command == 'new-constructor':
-            "new-constructor GType"
-            gtype, = words[1:]
-            self.newstyle_constructors[gtype] = True
-        elif command == 'options':
-            for option in words[1:]:
-                if option == 'dynamicnamespace':
-                    self.dynamicnamespace = True
-
-    def is_ignored(self, name):
-        if self.ignores.has_key(name):
-            return 1
-        for glob in self.glob_ignores:
-            if fnmatch.fnmatchcase(name, glob):
-                return 1
-        return 0
-
-    def is_type_ignored(self, name):
-        return name in self.type_ignores
-
-    def is_overriden(self, name):
-        return self.overrides.has_key(name)
-
-    def is_already_included(self, name):
-        return self.overridden.has_key(name)
-
-    def override(self, name):
-        self.overridden[name] = 1
-        return self.overrides[name]
-
-    def define(self, klass, name):
-        self.overridden[class2cname(klass, name)] = 1
-        return self.defines[klass][name]
-
-    def function(self, name):
-        return self.functions[name]
-
-    def getstartline(self, name):
-        return self.startlines[name]
-
-    def wants_kwargs(self, name):
-        return self.kwargs.has_key(name)
-
-    def wants_noargs(self, name):
-        return self.noargs.has_key(name)
-
-    def wants_onearg(self, name):
-        return self.onearg.has_key(name)
-
-    def is_staticmethod(self, name):
-        return self.staticmethod.has_key(name)
-
-    def is_classmethod(self, name):
-        return self.classmethod.has_key(name)
-
-    def attr_is_overriden(self, attr):
-        return self.override_attrs.has_key(attr)
-
-    def attr_override(self, attr):
-        return self.override_attrs[attr]
-
-    def slot_is_overriden(self, slot):
-        return self.override_slots.has_key(slot)
-
-    def slot_override(self, slot):
-        return self.override_slots[slot]
-
-    def get_headers(self):
-        return self.headers
-
-    def get_body(self):
-        return self.body
-
-    def get_init(self):
-        return self.init
-
-    def get_imports(self):
-        return self.imports
-
-    def get_defines_for(self, klass):
-        return self.defines.get(klass, {})
-
-    def get_functions(self):
-        return self.functions
diff --git a/codegen/reversewrapper.py b/codegen/reversewrapper.py
deleted file mode 100644
index ed48629..0000000
--- a/codegen/reversewrapper.py
+++ /dev/null
@@ -1,900 +0,0 @@
-### -*- python -*-
-### Code to generate "Reverse Wrappers", i.e. C->Python wrappers
-### (C) 2004 Gustavo Carneiro <gjc@gnome.org>
-import argtypes
-import os
-
-DEBUG_MODE = ('PYGTK_CODEGEN_DEBUG' in os.environ)
-
-def join_ctype_name(ctype, name):
-    '''Joins a C type and a variable name into a single string'''
-    if ctype[-1] != '*':
-        return " ".join((ctype, name))
-    else:
-        return "".join((ctype, name))
-
-
-class CodeSink(object):
-    def __init__(self):
-        self.indent_level = 0 # current indent level
-        self.indent_stack = [] # previous indent levels
-
-    def _format_code(self, code):
-        assert isinstance(code, str)
-        l = []
-        for line in code.split('\n'):
-            l.append(' '*self.indent_level + line)
-        if l[-1]:
-            l.append('')
-        return '\n'.join(l)
-
-    def writeln(self, line=''):
-        raise NotImplementedError
-
-    def indent(self, level=4):
-        '''Add a certain ammount of indentation to all lines written
-        from now on and until unindent() is called'''
-        self.indent_stack.append(self.indent_level)
-        self.indent_level += level
-
-    def unindent(self):
-        '''Revert indentation level to the value before last indent() call'''
-        self.indent_level = self.indent_stack.pop()
-
-
-class FileCodeSink(CodeSink):
-    def __init__(self, fp):
-        CodeSink.__init__(self)
-        assert isinstance(fp, file)
-        self.fp = fp
-
-    def writeln(self, line=''):
-        self.fp.write(self._format_code(line))
-
-class MemoryCodeSink(CodeSink):
-    def __init__(self):
-        CodeSink.__init__(self)
-        self.lines = []
-
-    def writeln(self, line=''):
-        self.lines.append(self._format_code(line))
-
-    def flush_to(self, sink):
-        assert isinstance(sink, CodeSink)
-        for line in self.lines:
-            sink.writeln(line.rstrip())
-        self.lines = []
-
-    def flush(self):
-        l = []
-        for line in self.lines:
-            l.append(self._format_code(line))
-        self.lines = []
-        return "".join(l)
-
-class ReverseWrapper(object):
-    '''Object that generates a C->Python wrapper'''
-    def __init__(self, cname, is_static=True):
-        assert isinstance(cname, str)
-
-        self.cname = cname
-        ## function object we will call, or object whose method we will call
-        self.called_pyobj = None
-        ## name of method of self.called_pyobj we will call
-        self.method_name = None
-        self.is_static = is_static
-
-        self.parameters = []
-        self.declarations = MemoryCodeSink()
-        self.post_return_code = MemoryCodeSink()
-        self.body = MemoryCodeSink()
-        self.check_exception_code = MemoryCodeSink()
-        self.cleanup_actions = []
-        self.pyargv_items = []
-        self.pyargv_optional_items = []
-        self.pyret_parse_items = [] # list of (format_spec, parameter)
-        self.code_sinks_stack = [self.body]
-
-    def set_call_target(self, called_pyobj, method_name=None):
-        assert called_pyobj is not None
-        assert self.called_pyobj is None
-        self.called_pyobj = called_pyobj
-        self.method_name = method_name
-
-    def set_return_type(self, return_type):
-        assert isinstance(return_type, ReturnType)
-        self.return_type = return_type
-
-    def add_parameter(self, param):
-        assert isinstance(param, Parameter)
-        self.parameters.append(param)
-
-    def add_declaration(self, decl_code):
-        self.declarations.writeln(decl_code)
-
-    def add_pyargv_item(self, variable, optional=False):
-        if optional:
-            self.pyargv_optional_items.append(variable)
-        else:
-            self.pyargv_items.append(variable)
-
-    def add_pyret_parse_item(self, format_specifier, parameter, prepend=False):
-        if prepend:
-            self.pyret_parse_items.insert(0, (format_specifier, parameter))
-        else:
-            self.pyret_parse_items.append((format_specifier, parameter))
-
-
-    def push_code_sink(self, code_sink):
-        self.code_sinks_stack.insert(0, code_sink)
-
-    def pop_code_sink(self):
-        return self.code_sinks_stack.pop(0)
-
-
-    def write_code(self, code,
-                   cleanup=None,
-                   failure_expression=None,
-                   failure_cleanup=None,
-                   failure_exception=None,
-                   code_sink=None):
-        '''Add a chunk of code with cleanup and error handling
-
-        This method is to be used by TypeHandlers when generating code
-
-        Keywork arguments:
-        code -- code to add
-        cleanup -- code to cleanup any dynamic resources created by @code
-                   (except in case of failure) (default None)
-        failure_expression -- C boolean expression to indicate
-                              if anything failed (default None)
-        failure_cleanup -- code to cleanup any dynamic resources
-                           created by @code in case of failure (default None)
-        failure_exception -- code to raise an exception in case of
-                             failure (which will be immediately
-                             printed and cleared), (default None)
-        code_sink -- "code sink" to use; by default,
-                      ReverseWrapper.body is used, which writes the
-                      main body of the wrapper, before calling the
-                      python method.  Alternatively,
-                      ReverseWrapper.after_pyret_parse can be used, to
-                      write code after the PyArg_ParseTuple that
-                      parses the python method return value.
-        '''
-        if code_sink is None:
-            code_sink = self.code_sinks_stack[0]
-        if code is not None:
-            code_sink.writeln(code)
-        if failure_expression is not None:
-            code_sink.writeln("if (%s) {" % (failure_expression,))
-            code_sink.indent()
-            if failure_exception is None:
-                code_sink.writeln("if (PyErr_Occurred())")
-                code_sink.indent()
-                code_sink.writeln("PyErr_Print();")
-                code_sink.unindent()
-            else:
-                code_sink.writeln(failure_exception)
-                code_sink.writeln("PyErr_Print();")
-            if failure_cleanup is not None:
-                code_sink.writeln(failure_cleanup)
-            for cleanup_action in self.cleanup_actions:
-                code_sink.writeln(cleanup_action)
-
-            self.push_code_sink(code_sink)
-            try:
-                self.return_type.write_error_return()
-            finally:
-                self.pop_code_sink()
-
-            code_sink.unindent()
-            code_sink.writeln("}")
-        if cleanup is not None:
-            self.cleanup_actions.insert(0, cleanup)
-
-    def generate(self, sink):
-        '''Generate the code into a CodeSink object'''
-        assert isinstance(sink, CodeSink)
-
-        if DEBUG_MODE:
-            self.declarations.writeln("/* begin declarations */")
-            self.body.writeln("/* begin main body */")
-            self.post_return_code.writeln("/* begin post-return code */")
-
-        self.add_declaration("PyGILState_STATE __py_state;")
-        self.write_code(code="__py_state = pyg_gil_state_ensure();",
-                        cleanup="pyg_gil_state_release(__py_state);")
-
-        for param in self.parameters:
-            param.convert_c2py()
-
-        assert self.called_pyobj is not None,\
-               "Parameters failed to provide a target function or method."
-
-        if self.is_static:
-            sink.writeln('static %s' % self.return_type.get_c_type())
-        else:
-            sink.writeln(self.return_type.get_c_type())
-        c_proto_params = map(Parameter.format_for_c_proto, self.parameters)
-        sink.writeln("%s(%s)\n{" % (self.cname, ", ".join(c_proto_params)))
-
-        self.return_type.write_decl()
-        self.add_declaration("PyObject *py_retval;")
-
-        ## Handle number of arguments
-        if self.pyargv_items:
-            self.add_declaration("PyObject *py_args;")
-            py_args = "py_args"
-            if self.pyargv_optional_items:
-                self.add_declaration("int argc = %i;" % len(self.pyargv_items))
-                argc = "argc"
-                for arg in self.pyargv_optional_items:
-                    self.body.writeln("if (%s)" % arg)
-                    self.body.indent()
-                    self.body.writeln("++argc;")
-                    self.body.unindent()
-            else:
-                argc = str(len(self.pyargv_items))
-        else:
-            if self.pyargv_optional_items:
-                self.add_declaration("PyObject *py_args;")
-                py_args = "py_args"
-                self.add_declaration("int argc = 0;")
-                argc = "argc"
-                for arg in self.pyargv_optional_items:
-                    self.body.writeln("if (%s)" % arg)
-                    self.body.indent()
-                    self.body.writeln("++argc;")
-                    self.body.unindent()
-            else:
-                py_args = "NULL"
-                argc = None
-
-        self.body.writeln()
-
-        if py_args != "NULL":
-            self.write_code("py_args = PyTuple_New(%s);" % argc,
-                            cleanup="Py_DECREF(py_args);")
-            pos = 0
-            for arg in self.pyargv_items:
-                try: # try to remove the Py_DECREF cleanup action, if we can
-                    self.cleanup_actions.remove("Py_DECREF(%s);" % arg)
-                except ValueError: # otherwise we have to Py_INCREF..
-                    self.body.writeln("Py_INCREF(%s);" % arg)
-                self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg))
-                pos += 1
-            for arg in self.pyargv_optional_items:
-                self.body.writeln("if (%s) {" % arg)
-                self.body.indent()
-                try: # try to remove the Py_DECREF cleanup action, if we can
-                    self.cleanup_actions.remove("Py_XDECREF(%s);" % arg)
-                except ValueError: # otherwise we have to Py_INCREF..
-                    self.body.writeln("Py_INCREF(%s);" % arg)
-                self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg))
-                self.body.unindent()
-                self.body.writeln("}")
-                pos += 1
-
-        self.body.writeln()
-
-        ## Call the python method
-        if self.method_name is None:
-            self.write_code("py_retval = PyObject_Call(%s, %s);"
-                            % (self.called_pyobj, py_args),
-                            cleanup="Py_XDECREF(py_retval);")
-            self.check_exception_code.flush_to(self.body)
-            self.write_code(None, failure_expression="!py_retval")
-
-        else:
-            self.add_declaration("PyObject *py_method;")
-            self.write_code("py_method = PyObject_GetAttrString(%s, \"%s\");"
-                            % (self.called_pyobj, self.method_name),
-                            cleanup="Py_DECREF(py_method);",
-                            failure_expression="!py_method")
-            self.write_code("py_retval = PyObject_CallObject(py_method, %s);"
-                            % (py_args,),
-                            cleanup="Py_XDECREF(py_retval);")
-            self.check_exception_code.flush_to(self.body)
-            self.write_code(None, failure_expression="!py_retval")
-
-        ## -- Handle the return value --
-
-        ## we need to check if the return_type object is prepared to cooperate with multiple return values
-        len_before = len(self.pyret_parse_items)
-        self.return_type.write_conversion()
-        len_after = len(self.pyret_parse_items)
-        assert (self.return_type.get_c_type() == 'void'
-                or not (len_before == len_after and len_after > 0)),\
-               ("Bug in reverse wrappers: return type handler %s"
-                " is not prepared to cooperate multiple return values") % (type(self.return_type),)
-
-        sink.indent()
-
-        if self.pyret_parse_items == [("", "")]:
-            ## special case when there are no return parameters
-            self.write_code(
-                code=None,
-                failure_expression='py_retval != Py_None',
-                failure_exception=('PyErr_SetString(PyExc_TypeError, '
-                                   '"virtual method should return None");'))
-        else:    
-            if len(self.pyret_parse_items) == 1:
-                ## if retval is one item only, pack it in a tuple so we
-                ## can use PyArg_ParseTuple as usual..
-                self.write_code('py_retval = Py_BuildValue("(N)", py_retval);')
-            if len(self.pyret_parse_items) > 0:
-                ## Parse return values using PyArg_ParseTuple
-                params = ["py_retval",
-                          '"%s"' % "".join([format for format, param in self.pyret_parse_items])]
-                params.extend([param for format, param in self.pyret_parse_items if param])
-                self.write_code(code=None, failure_expression=(
-                    '!PyArg_ParseTuple(%s)' % (', '.join(params),)))
-
-        if DEBUG_MODE:
-            self.declarations.writeln("/* end declarations */")
-        self.declarations.flush_to(sink)
-        sink.writeln()
-        if DEBUG_MODE:
-            self.body.writeln("/* end main body */")
-        self.body.flush_to(sink)
-        sink.writeln()
-        if DEBUG_MODE:
-            self.post_return_code.writeln("/* end post-return code */")
-        self.post_return_code.flush_to(sink)
-        sink.writeln()
-
-        for cleanup_action in self.cleanup_actions:
-            sink.writeln(cleanup_action)
-        if self.return_type.get_c_type() != 'void':
-            sink.writeln()
-            sink.writeln("return retval;")
-        sink.unindent()
-        sink.writeln("}")
-
-class TypeHandler(object):
-    def __init__(self, wrapper, **props):
-        assert isinstance(wrapper, ReverseWrapper)
-        self.wrapper = wrapper
-        self.props = props
-
-class ReturnType(TypeHandler):
-
-    supports_optional = False
-
-    def get_c_type(self):
-        raise NotImplementedError
-
-    def write_decl(self):
-        raise NotImplementedError
-
-    def write_error_return(self):
-        '''Write "return <value>" code in case of error'''
-        raise NotImplementedError
-
-    def write_conversion(self):
-        '''Writes code to convert Python return value in 'py_retval'
-        into C 'retval'.  Returns a string with C boolean expression
-        that determines if anything went wrong. '''
-        raise NotImplementedError
-
-class Parameter(TypeHandler):
-
-    def __init__(self, wrapper, name, **props):
-        TypeHandler.__init__(self, wrapper, **props)
-        self.name = name
-
-    def get_c_type(self):
-        raise NotImplementedError
-
-    def convert_c2py(self):
-        '''Write some code before calling the Python method.'''
-        pass
-
-    def format_for_c_proto(self):
-        return join_ctype_name(self.get_c_type(), self.name)
-
-
-###---
-class StringParam(Parameter):
-
-    def get_c_type(self):
-        return self.props.get('c_type', 'char *').replace('const-', 'const ')
-
-    def convert_c2py(self):
-        if self.props.get('optional', False):
-            self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name)
-            self.wrapper.write_code(code=("if (%s)\n"
-                                          "    py_%s = PyString_FromString(%s);\n"
-                                          % (self.name, self.name, self.name)),
-                                    cleanup=("Py_XDECREF(py_%s);" % self.name))
-            self.wrapper.add_pyargv_item("py_%s" % self.name, optional=True)
-        else:
-            self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-            self.wrapper.write_code(code=("py_%s = PyString_FromString(%s);" %
-                                          (self.name, self.name)),
-                                    cleanup=("Py_DECREF(py_%s);" % self.name),
-                                    failure_expression=("!py_%s" % self.name))
-            self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-for ctype in ('char*', 'gchar*', 'const-char*', 'char-const*', 'const-gchar*',
-              'gchar-const*', 'string', 'static_string'):
-    argtypes.matcher.register_reverse(ctype, StringParam)
-del ctype
-
-class StringReturn(ReturnType):
-
-    def get_c_type(self):
-        return self.props.get('c_type', 'char *').replace('const-', 'const ')
-    #return "char *"
-
-    def write_decl(self):
-        self.wrapper.add_declaration("%s retval;" % self.get_c_type())
-        #self.wrapper.add_declaration("char *retval;")
-
-    def write_error_return(self):
-        self.wrapper.write_code("return NULL;")
-
-    def write_conversion(self):
-        self.wrapper.add_pyret_parse_item("s", "&retval", prepend=True)
-        self.wrapper.write_code("retval = g_strdup(retval);", code_sink=self.wrapper.post_return_code)
-
-for ctype in ('char*', 'gchar*', 'const-gchar*'):
-    argtypes.matcher.register_reverse_ret(ctype, StringReturn)
-del ctype
-
-
-class VoidReturn(ReturnType):
-
-    def get_c_type(self):
-        return "void"
-
-    def write_decl(self):
-        pass
-
-    def write_error_return(self):
-        self.wrapper.write_code("return;")
-
-    def write_conversion(self):
-        self.wrapper.add_pyret_parse_item("", "", prepend=True)
-
-argtypes.matcher.register_reverse_ret('void', VoidReturn)
-argtypes.matcher.register_reverse_ret('none', VoidReturn)
-
-class GObjectParam(Parameter):
-
-    def get_c_type(self):
-        return self.props.get('c_type', 'GObject *')
-
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name)
-        self.wrapper.write_code(code=("if (%s)\n"
-                                      "    py_%s = pygobject_new((GObject *) %s);\n"
-                                      "else {\n"
-                                      "    Py_INCREF(Py_None);\n"
-                                      "    py_%s = Py_None;\n"
-                                      "}"
-                                      % (self.name, self.name, self.name, self.name)),
-                                cleanup=("Py_DECREF(py_%s);" % self.name))
-        self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-argtypes.matcher.register_reverse('GObject*', GObjectParam)
-
-class GObjectReturn(ReturnType):
-
-    supports_optional = True
-
-    def get_c_type(self):
-        return self.props.get('c_type', 'GObject *')
-
-    def write_decl(self):
-        if not self.props.get('optional'):
-            self.wrapper.add_declaration("%s retval;" % self.get_c_type())
-        else:
-            self.wrapper.add_declaration("%s retval = NULL;" % self.get_c_type())
-
-    def write_error_return(self):
-        self.wrapper.write_code("return NULL;")
-
-    def write_conversion(self):
-        if not self.props.get('optional'):
-            self.wrapper.write_code(
-                code=None,
-                failure_expression="!PyObject_TypeCheck(py_retval, &PyGObject_Type)",
-                failure_exception='PyErr_SetString(PyExc_TypeError, "retval should be a GObject");')
-            self.wrapper.write_code("retval = (%s) pygobject_get(py_retval);"
-                                    % self.get_c_type())
-            self.wrapper.write_code("g_object_ref((GObject *) retval);")
-        else:
-            self.wrapper.write_code(
-                code=None,
-                failure_expression="py_retval != Py_None && !PyObject_TypeCheck(py_retval, &PyGObject_Type)",
-                failure_exception='PyErr_SetString(PyExc_TypeError, "retval should be None or a GObject");')
-            self.wrapper.write_code("if (py_retval != Py_None) {\n"
-                                    "    retval = (%s) pygobject_get(py_retval);\n"
-                                    "    g_object_ref((GObject *) retval);\n"
-                                    "}\n"
-                                    % self.get_c_type())
-
-argtypes.matcher.register_reverse_ret('GObject*', GObjectReturn)
-
-
-
-class IntParam(Parameter):
-
-    def get_c_type(self):
-        return self.props.get('c_type', 'int')
-
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-        self.wrapper.write_code(code=("py_%s = PyInt_FromLong(%s);" %
-                                      (self.name, self.name)),
-                                cleanup=("Py_DECREF(py_%s);" % self.name))
-        self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-class IntReturn(ReturnType):
-    def get_c_type(self):
-        return self.props.get('c_type', 'int')
-    def write_decl(self):
-        self.wrapper.add_declaration("%s retval;" % self.get_c_type())
-    def write_error_return(self):
-        self.wrapper.write_code("return -G_MAXINT;")
-    def write_conversion(self):
-        self.wrapper.add_pyret_parse_item("i", "&retval", prepend=True)
-
-for argtype in ('int', 'gint', 'guint', 'short', 'gshort', 'gushort', 'long',
-                'glong', 'gsize', 'gssize', 'guint8', 'gint8', 'guint16',
-                'gint16', 'gint32', 'GTime'):
-    argtypes.matcher.register_reverse(argtype, IntParam)
-    argtypes.matcher.register_reverse_ret(argtype, IntReturn)
-del argtype
-
-class IntPtrParam(Parameter):
-    def __init__(self, wrapper, name, **props):
-        if "direction" not in props:
-            raise argtypes.ArgTypeConfigurationError(
-                "cannot use int* parameter without direction")
-        if props["direction"] not in ("out", "inout"):
-            raise argtypes.ArgTypeConfigurationError(
-                "cannot use int* parameter with direction '%s'"
-                % (props["direction"],))
-        Parameter.__init__(self, wrapper, name, **props)
-    def get_c_type(self):
-        return self.props.get('c_type', 'int*')
-    def convert_c2py(self):
-        if self.props["direction"] == "inout":
-            self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-            self.wrapper.write_code(code=("py_%s = PyInt_FromLong(*%s);" %
-                                          (self.name, self.name)),
-                                    cleanup=("Py_DECREF(py_%s);" % self.name))
-            self.wrapper.add_pyargv_item("py_%s" % self.name)
-        self.wrapper.add_pyret_parse_item("i", self.name)
-for argtype in ('int*', 'gint*'):
-    argtypes.matcher.register_reverse(argtype, IntPtrParam)
-del argtype
-
-
-class GEnumReturn(IntReturn):
-    def write_conversion(self):
-        self.wrapper.write_code(
-            code=None,
-            failure_expression=(
-            "pyg_enum_get_value(%s, py_retval, (gint *)&retval)"
-            % (self.props['typecode'],)))
-
-argtypes.matcher.register_reverse_ret("GEnum", GEnumReturn)
-
-class GEnumParam(IntParam):
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-        self.wrapper.write_code(code=("py_%s = pyg_enum_from_gtype(%s, %s);" %
-                                (self.name, self.props['typecode'], self.name)),
-                        cleanup=("Py_DECREF(py_%s);" % self.name),
-                        failure_expression=("!py_%s" % self.name))
-        self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-argtypes.matcher.register_reverse("GEnum", GEnumParam)
-
-class GFlagsReturn(IntReturn):
-    def write_conversion(self):
-        self.wrapper.write_code(
-            code=None,
-            failure_expression=(
-            "pyg_flags_get_value(%s, py_retval, (gint *)&retval)" %
-            self.props['typecode']))
-
-argtypes.matcher.register_reverse_ret("GFlags", GFlagsReturn)
-
-class GFlagsParam(IntParam):
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-        self.wrapper.write_code(code=(
-            "py_%s = pyg_flags_from_gtype(%s, %s);" %
-            (self.name, self.props['typecode'], self.name)),
-                                cleanup=("Py_DECREF(py_%s);" % self.name),
-                                failure_expression=("!py_%s" % self.name))
-        self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-argtypes.matcher.register_reverse("GFlags", GFlagsParam)
-
-
-class GtkTreePathParam(IntParam):
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-        self.wrapper.write_code(code=(
-            "py_%s = pygtk_tree_path_to_pyobject(%s);" %
-            (self.name, self.name)),
-                                cleanup=("Py_DECREF(py_%s);" % self.name),
-                                failure_expression=("!py_%s" % self.name))
-        self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-argtypes.matcher.register_reverse("GtkTreePath*", GtkTreePathParam)
-
-
-class GtkTreePathReturn(ReturnType):
-    def get_c_type(self):
-        return self.props.get('c_type', 'GtkTreePath *')
-    def write_decl(self):
-        self.wrapper.add_declaration("GtkTreePath * retval;")
-    def write_error_return(self):
-        self.wrapper.write_code("return NULL;")
-    def write_conversion(self):
-        self.wrapper.write_code(
-            "retval = pygtk_tree_path_from_pyobject(py_retval);\n",
-            failure_expression=('!retval'),
-            failure_exception=(
-    'PyErr_SetString(PyExc_TypeError, "retval should be a GtkTreePath");'))
-
-argtypes.matcher.register_reverse_ret("GtkTreePath*", GtkTreePathReturn)
-
-
-class BooleanReturn(ReturnType):
-    def get_c_type(self):
-        return "gboolean"
-    def write_decl(self):
-        self.wrapper.add_declaration("gboolean retval;")
-        self.wrapper.add_declaration("PyObject *py_main_retval;")
-    def write_error_return(self):
-        self.wrapper.write_code("return FALSE;")
-    def write_conversion(self):
-        self.wrapper.add_pyret_parse_item("O", "&py_main_retval", prepend=True)
-        self.wrapper.write_code(
-            "retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;",
-            code_sink=self.wrapper.post_return_code)
-argtypes.matcher.register_reverse_ret("gboolean", BooleanReturn)
-
-class BooleanParam(Parameter):
-    def get_c_type(self):
-        return "gboolean"
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-        self.wrapper.write_code("py_%s = %s? Py_True : Py_False;"
-                                % (self.name, self.name))
-        self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-argtypes.matcher.register_reverse("gboolean", BooleanParam)
-
-
-class DoubleParam(Parameter):
-    def get_c_type(self):
-        return self.props.get('c_type', 'gdouble')
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-        self.wrapper.write_code(code=("py_%s = PyFloat_FromDouble(%s);" %
-                                      (self.name, self.name)),
-                                cleanup=("Py_DECREF(py_%s);" % self.name))
-        self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-class DoublePtrParam(Parameter):
-    def __init__(self, wrapper, name, **props):
-        if "direction" not in props:
-            raise argtypes.ArgTypeConfigurationError(
-                "cannot use double* parameter without direction")
-        if props["direction"] not in ("out", ): # inout not yet implemented
-            raise argtypes.ArgTypeConfigurationError(
-                "cannot use double* parameter with direction '%s'"
-                % (props["direction"],))
-        Parameter.__init__(self, wrapper, name, **props)
-    def get_c_type(self):
-        return self.props.get('c_type', 'double*')
-    def convert_c2py(self):
-        self.wrapper.add_pyret_parse_item("d", self.name)
-for argtype in ('double*', 'gdouble*'):
-    argtypes.matcher.register_reverse(argtype, DoublePtrParam)
-del argtype
-
-class DoubleReturn(ReturnType):
-    def get_c_type(self):
-        return self.props.get('c_type', 'gdouble')
-    def write_decl(self):
-        self.wrapper.add_declaration("%s retval;" % self.get_c_type())
-    def write_error_return(self):
-        self.wrapper.write_code("return -G_MAXFLOAT;")
-    def write_conversion(self):
-        self.wrapper.add_pyret_parse_item("d", "&retval", prepend=True)
-
-for argtype in ('float', 'double', 'gfloat', 'gdouble'):
-    argtypes.matcher.register_reverse(argtype, DoubleParam)
-    argtypes.matcher.register_reverse_ret(argtype, DoubleReturn)
-
-
-class GBoxedParam(Parameter):
-    def get_c_type(self):
-        return self.props.get('c_type').replace('const-', 'const ')
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-        ctype = self.get_c_type()
-        if ctype.startswith('const '):
-            ctype_no_const = ctype[len('const '):]
-            self.wrapper.write_code(
-                code=('py_%s = pyg_boxed_new(%s, (%s) %s, TRUE, TRUE);' %
-                      (self.name, self.props['typecode'],
-                       ctype_no_const, self.name)),
-                cleanup=("Py_DECREF(py_%s);" % self.name))
-        else:
-            self.wrapper.write_code(
-                code=('py_%s = pyg_boxed_new(%s, %s, FALSE, FALSE);' %
-                      (self.name, self.props['typecode'], self.name)),
-                cleanup=("Py_DECREF(py_%s);" % self.name))
-        self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-argtypes.matcher.register_reverse("GBoxed", GBoxedParam)
-
-
-class GBoxedReturn(ReturnType):
-    def get_c_type(self):
-        return self.props.get('c_type')
-    def write_decl(self):
-        self.wrapper.add_declaration("%s retval;" % self.get_c_type())
-    def write_error_return(self):
-        self.wrapper.write_code("return retval;")
-    def write_conversion(self):
-        self.wrapper.write_code(code = None,
-            failure_expression=("!pyg_boxed_check(py_retval, %s)" %
-                                (self.props['typecode'],)),
-            failure_exception=(
-            'PyErr_SetString(PyExc_TypeError, "retval should be a %s");'
-            % (self.props['typename'],)))
-        self.wrapper.write_code('retval = pyg_boxed_get(py_retval, %s);' %
-                                self.props['typename'])
-
-argtypes.matcher.register_reverse_ret("GBoxed", GBoxedReturn)
-
-
-class GdkRegionPtrReturn(GBoxedReturn):
-    def write_error_return(self):
-        self.wrapper.write_code("return gdk_region_new();")
-    def write_conversion(self):
-        self.props['typecode'] = 'PYGDK_TYPE_REGION'
-        self.props['typename'] = 'GdkRegion'
-        super(GdkRegionPtrReturn, self).write_conversion()
-
-argtypes.matcher.register_reverse_ret("GdkRegion*", GdkRegionPtrReturn)
-
-
-class PangoFontDescriptionReturn(GBoxedReturn):
-    def write_error_return(self):
-        self.wrapper.write_code("return pango_font_description_new();")
-    def write_conversion(self):
-        self.props['typecode'] = 'PANGO_TYPE_FONT_DESCRIPTION'
-        self.props['typename'] = 'PangoFontDescription'
-        super(PangoFontDescriptionReturn, self).write_conversion()
-
-argtypes.matcher.register_reverse_ret("PangoFontDescription*",
-                                      PangoFontDescriptionReturn)
-
-
-class PangoFontMetricsReturn(GBoxedReturn):
-    def write_error_return(self):
-        self.wrapper.write_code("return pango_font_metrics_new();")
-    def write_conversion(self):
-        self.props['typecode'] = 'PANGO_TYPE_FONT_METRICS'
-        self.props['typename'] = 'PangoFontMetrics'
-        super(PangoFontMetricsReturn, self).write_conversion()
-
-argtypes.matcher.register_reverse_ret("PangoFontMetrics*",
-                                      PangoFontMetricsReturn)
-
-
-class PangoLanguageReturn(GBoxedReturn):
-    def write_error_return(self):
-        self.wrapper.write_code("return pango_language_from_string(\"\");")
-    def write_conversion(self):
-        self.props['typecode'] = 'PANGO_TYPE_LANGUAGE'
-        self.props['typename'] = 'PangoLanguage'
-        super(PangoLanguageReturn, self).write_conversion()
-
-argtypes.matcher.register_reverse_ret("PangoLanguage*", PangoLanguageReturn)
-
-
-class GdkRectanglePtrParam(Parameter):
-    def get_c_type(self):
-        return self.props.get('c_type').replace('const-', 'const ')
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-        self.wrapper.write_code(
-            code=('py_%s = pyg_boxed_new(GDK_TYPE_RECTANGLE, %s, TRUE, TRUE);' %
-                  (self.name, self.name)),
-            cleanup=("Py_DECREF(py_%s);" % self.name))
-        self.wrapper.add_pyargv_item("py_%s" % self.name)
-
-argtypes.matcher.register_reverse("GdkRectangle*", GdkRectanglePtrParam)
-argtypes.matcher.register_reverse('GtkAllocation*', GdkRectanglePtrParam)
-
-
-class GErrorParam(Parameter):
-    def get_c_type(self):
-        return self.props.get('c_type').replace('**', ' **')
-    def convert_c2py(self):
-        self.wrapper.write_code(code=None,
-            failure_expression=("pyg_gerror_exception_check(%s)" % self.name),
-                                code_sink=self.wrapper.check_exception_code)
-
-argtypes.matcher.register_reverse('GError**', GErrorParam)
-
-
-class PyGObjectMethodParam(Parameter):
-    def __init__(self, wrapper, name, method_name, **props):
-        Parameter.__init__(self, wrapper, name, **props)
-        self.method_name = method_name
-
-    def get_c_type(self):
-        return self.props.get('c_type', 'GObject *')
-
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
-        self.wrapper.write_code(code=("py_%s = pygobject_new((GObject *) %s);" %
-                                      (self.name, self.name)),
-                                cleanup=("Py_DECREF(py_%s);" % self.name),
-                                failure_expression=("!py_%s" % self.name))
-        self.wrapper.set_call_target("py_%s" % self.name, self.method_name)
-
-
-class CallbackInUserDataParam(Parameter):
-    def __init__(self, wrapper, name, free_it, **props):
-        Parameter.__init__(self, wrapper, name, **props)
-        self.free_it = free_it
-
-    def get_c_type(self):
-        return "gpointer"
-
-    def convert_c2py(self):
-        self.wrapper.add_declaration("PyObject **_user_data;")
-        cleanup = self.free_it and ("g_free(%s);" % self.name) or None
-        self.wrapper.write_code(code=("_real_user_data = (PyObject **) %s;"
-                                      % self.name),
-                                cleanup=cleanup)
-
-        self.wrapper.add_declaration("PyObject *py_func;")
-        cleanup = self.free_it and "Py_DECREF(py_func);" or None
-        self.wrapper.write_code(code="py_func = _user_data[0];",
-                                cleanup=cleanup)
-        self.wrapper.set_call_target("py_func")
-
-        self.wrapper.add_declaration("PyObject *py_user_data;")
-        cleanup = self.free_it and "Py_XDECREF(py_user_data);" or None
-        self.wrapper.write_code(code="py_user_data = _user_data[1];",
-                                cleanup=cleanup)
-        self.wrapper.add_pyargv_item("py_user_data", optional=True)
-
-def _test():
-    import sys
-
-    if 1:
-        wrapper = ReverseWrapper("this_is_the_c_function_name", is_static=True)
-        wrapper.set_return_type(StringReturn(wrapper))
-        wrapper.add_parameter(PyGObjectMethodParam(wrapper, "self", method_name="do_xxx"))
-        wrapper.add_parameter(StringParam(wrapper, "param2", optional=True))
-        wrapper.add_parameter(GObjectParam(wrapper, "param3"))
-        #wrapper.add_parameter(InoutIntParam(wrapper, "param4"))
-        wrapper.generate(FileCodeSink(sys.stderr))
-
-    if 0:
-        wrapper = ReverseWrapper("this_a_callback_wrapper")
-        wrapper.set_return_type(VoidReturn(wrapper))
-        wrapper.add_parameter(StringParam(wrapper, "param1", optional=False))
-        wrapper.add_parameter(GObjectParam(wrapper, "param2"))
-        wrapper.add_parameter(CallbackInUserDataParam(wrapper, "data", free_it=True))
-        wrapper.generate(FileCodeSink(sys.stderr))
-
-if __name__ == '__main__':
-    _test()
diff --git a/codegen/scanvirtuals.py b/codegen/scanvirtuals.py
index c108737..3fb1843 100755
--- a/codegen/scanvirtuals.py
+++ b/codegen/scanvirtuals.py
@@ -21,7 +21,7 @@ def main():
                 continue
             params = []
             if not m[2]:
-                print >> sys.stderr, repr(m)
+                sys.stderr.write("%s\n" % repr(m))
                 continue
             for param in map(str.strip, m[2].split(',')):
                 if '*' in param:
@@ -31,7 +31,7 @@ def main():
                 else:
                     if param == 'void':
                         continue
-                    ptype, pname = map(str.strip, param.split())
+                    ptype, pname = list(map(str.strip, param.split()))
                 ptype = ptype.replace('const ', 'const-')
                 while '[]' in pname:
                     pname = pname.replace('[]', '')
@@ -40,15 +40,15 @@ def main():
             if not params:
                 continue
             objname = params[0][0].replace('*', '')
-            print '(define-virtual', virtual_name
-            print '  (of-object "%s")' % objname
-            print '  (return-type "%s")' % return_type
+            sys.stdout.write('(define-virtual %s\n' % virtual_name)
+            sys.stdout.write('  (of-object "%s")\n' % objname)
+            sys.stdout.write('  (return-type "%s")\n' % return_type)
             if len(params) > 1:
-                print '  (parameters'
+                sys.stdout.write('  (parameters\n')
                 for param in params[1:]:
-                    print '    \'("%s" "%s")' % param
-                print '  )'
-            print ')'
+                    sys.stdout.write('    \'("%s" "%s")\n' % param)
+                sys.stdout.write('  )\n')
+            sys.stdout.write(')\n')
 
 if __name__ == '__main__':
     main()
diff --git a/codegen/scmexpr.py b/codegen/scmexpr.py
deleted file mode 100644
index 02f2e4b..0000000
--- a/codegen/scmexpr.py
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/env python
-# -*- Mode: Python; py-indent-offset: 4 -*-
-from __future__ import generators
-
-import string
-from cStringIO import StringIO
-
-class error(Exception):
-    def __init__(self, filename, lineno, msg):
-        Exception.__init__(self, msg)
-        self.filename = filename
-        self.lineno = lineno
-        self.msg = msg
-    def __str__(self):
-        return '%s:%d: error: %s' % (self.filename, self.lineno, self.msg)
-
-trans = [' '] * 256
-for i in range(256):
-    if chr(i) in string.letters + string.digits + '_':
-        trans[i] = chr(i)
-    else:
-        trans[i] = '_'
-trans = string.join(trans, '')
-
-def parse(filename):
-    if isinstance(filename, str):
-        fp = open(filename, 'r')
-    else: # if not string, assume it is some kind of iterator
-        fp = filename
-        filename = getattr(fp, 'name', '<unknown>')
-    whitespace = ' \t\n\r\x0b\x0c'
-    nonsymbol = whitespace + '();\'"'
-    stack = []
-    openlines = []
-    lineno = 0
-    for line in fp:
-        pos = 0
-        lineno += 1
-        while pos < len(line):
-            if line[pos] in whitespace: # ignore whitespace
-                pass
-            elif line[pos] == ';': # comment
-                break
-            elif line[pos:pos+2] == "'(":
-                pass # the open parenthesis will be handled next iteration
-            elif line[pos] == '(':
-                stack.append(())
-                openlines.append(lineno)
-            elif line[pos] == ')':
-                if len(stack) == 0:
-                    raise error(filename, lineno, 'close parenthesis found when none open')
-                closed = stack[-1]
-                del stack[-1]
-                del openlines[-1]
-                if stack:
-                    stack[-1] += (closed,)
-                else:
-                    yield closed
-            elif line[pos] == '"': # quoted string
-                if not stack:
-                    raise error(filename, lineno,
-                                'string found outside of s-expression')
-                endpos = pos + 1
-                chars = []
-                while endpos < len(line):
-                    if endpos+1 < len(line) and line[endpos] == '\\':
-                        endpos += 1
-                        if line[endpos] == 'n':
-                            chars.append('\n')
-                        elif line[endpos] == 'r':
-                            chars.append('\r')
-                        elif line[endpos] == 't':
-                            chars.append('\t')
-                        else:
-                            chars.append('\\')
-                            chars.append(line[endpos])
-                    elif line[endpos] == '"':
-                        break
-                    else:
-                        chars.append(line[endpos])
-                    endpos += 1
-                if endpos >= len(line):
-                    raise error(filename, lineno, "unclosed quoted string")
-                pos = endpos
-                stack[-1] += (''.join(chars),)
-            else: # symbol/number
-                if not stack:
-                    raise error(filename, lineno,
-                                'identifier found outside of s-expression')
-                endpos = pos
-                while endpos < len(line) and line[endpos] not in nonsymbol:
-                    endpos += 1
-                symbol = line[pos:endpos]
-                pos = max(pos, endpos-1)
-                try: symbol = int(symbol)
-                except ValueError:
-                    try: symbol = float(symbol)
-                    except ValueError: pass
-                stack[-1] += (symbol,)
-            pos += 1
-    if len(stack) != 0:
-        msg = '%d unclosed parentheses found at end of ' \
-              'file (opened on line(s) %s)' % (len(stack),
-                                               ', '.join(map(str, openlines)))
-        raise error(filename, lineno, msg)
-
-class Parser:
-    def __init__(self, filename):
-        """Argument is either a string, a parse tree, or file object"""
-        self.filename = filename
-    def startParsing(self, filename=None):
-        statements = parse(filename or self.filename)
-        for statement in statements:
-            self.handle(statement)
-    def handle(self, tup):
-        cmd = string.translate(tup[0], trans)
-        if hasattr(self, cmd):
-            getattr(self, cmd)(*tup[1:])
-        else:
-            self.unknown(tup)
-    def unknown(self, tup):
-        pass
-
-_testString = """; a scheme file
-(define-func gdk_font_load    ; a comment at end of line
-  GdkFont
-  ((string name)))
-
-(define-boxed GdkEvent
-  gdk_event_copy
-  gdk_event_free
-  "sizeof(GdkEvent)")
-"""
-
-if __name__ == '__main__':
-    import sys
-    if sys.argv[1:]:
-        fp = open(sys.argv[1])
-    else:
-        fp = StringIO(_testString)
-    statements = parse(fp)
-    for s in statements:
-        print `s`
