web/lib/arch/osx/jcc/python.py
changeset 29 cc9b7e14412b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/arch/osx/jcc/python.py	Tue May 25 02:43:45 2010 +0200
@@ -0,0 +1,1625 @@
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+
+import os, sys, platform, shutil, _jcc
+
+from cpp import PRIMITIVES, INDENT, HALF_INDENT
+from cpp import cppname, cppnames, typename
+from cpp import line, signature, find_method, split_pkg, sort
+from cpp import Modifier, Class, Method
+from _jcc import findClass
+from config import INCLUDES, CFLAGS, DEBUG_CFLAGS, LFLAGS, SHARED
+
+try:
+    from cpp import ParameterizedType, TypeVariable
+except ImportError:
+    pass
+
+python_ver = '%d.%d.%d' %(sys.version_info[0:3])
+if python_ver < '2.4':
+    from sets import Set as set
+
+
+RESULTS = { 'boolean': 'Py_RETURN_BOOL(%s);',
+            'byte': 'return PyInt_FromLong(%s);',
+            'char': 'return PyUnicode_FromUnicode((Py_UNICODE *) &%s, 1);',
+            'double': 'return PyFloat_FromDouble((double) %s);',
+            'float': 'return PyFloat_FromDouble((double) %s);',
+            'int': 'return PyInt_FromLong((long) %s);',
+            'long': 'return PyLong_FromLongLong((PY_LONG_LONG) %s);',
+            'short': 'return PyInt_FromLong((long) %s);',
+            'java.lang.String': 'return j2p(%s);' }
+
+CALLARGS = { 'boolean': ('O', '(%s ? Py_True : Py_False)', False),
+             'byte': ('O', 'PyInt_FromLong(%s)', True),
+             'char': ('O', 'PyUnicode_FromUnicode((Py_UNICODE *) &%s, 1)', True),
+             'double': ('d', '(double) %s', False),
+             'float': ('f', '(float) %s', False),
+             'int': ('i', '(int) %s', False),
+             'long': ('L', '(long long) %s', False),
+             'short': ('i', '(int) %s', False),
+             'java.lang.String': ('O', 'env->fromJString((jstring) %s, 0)', True) }
+
+
+def parseArgs(params, current, generics):
+
+    def signature(cls):
+        array = ''
+        while cls.isArray():
+            array += '['
+            cls = cls.getComponentType()
+        clsName = cls.getName()
+        if cls.isPrimitive():
+            return array + PRIMITIVES[clsName]
+        if clsName == 'java.lang.String':
+            return array + 's'
+        if clsName == 'java.lang.Object':
+            return array + 'o'
+        if generics and cls.getTypeParameters():
+            return array + 'K'
+        else:
+            return array + 'k'
+
+    def checkarg(cls):
+        while cls.isArray():
+            cls = cls.getComponentType()
+        if (cls.isPrimitive() or
+            cls.getName() in ('java.lang.String', 'java.lang.Object')):
+            return ''
+        return ', %s::initializeClass' %(typename(cls, current, False))
+
+    def callarg(cls, i):
+        if generics:
+            while cls.isArray():
+                cls = cls.getComponentType()
+            if cls.getTypeParameters():
+                ns, sep, n = rpartition(typename(cls, current, False), '::')
+                return ', &a%d, &p%d, %s%st_%s::parameters_' %(i, i, ns, sep, n)
+        return ', &a%d' %(i)
+
+    return (''.join([signature(param) for param in params]),
+            ''.join([checkarg(param) for param in params]),
+            ''.join([callarg(params[i], i) for i in xrange(len(params))]))
+
+
+def declareVars(out, indent, params, current, generics, typeParams):
+
+    for i in xrange(len(params)):
+        param = params[i]
+        line(out, indent, '%s a%d%s;',
+             typename(param, current, False), i,
+             not param.isPrimitive() and '((jobject) NULL)' or '')
+        if generics:
+            while param.isArray():
+                param = param.getComponentType()
+            if param.getTypeParameters():
+                line(out, indent, 'PyTypeObject **p%d;', i)
+                typeParams.add(i)
+    
+
+def construct(out, indent, cls, inCase, constructor, names, generics):
+
+    if inCase:
+        line(out, indent, '{')
+        indent += 1
+
+    params = constructor.getParameterTypes()
+    if generics:
+        typeParams = set()
+    else:
+        typeParams = None
+
+    count = len(params)
+
+    declareVars(out, indent, params, cls, generics, typeParams)
+    line(out, indent, '%s object((jobject) NULL);', cppname(names[-1]))
+
+    line(out)
+    if count:
+        line(out, indent, 'if (!parseArgs(args, "%s"%s%s))',
+             *parseArgs(params, cls, generics))
+        line(out, indent, '{')
+        indent += 1
+
+    line(out, indent, 'INT_CALL(object = %s(%s));',
+         cppname(names[-1]), ', '.join(['a%d' %(i) for i in xrange(count)]))
+    line(out, indent, 'self->object = object;')
+    if inCase:
+        line(out, indent, 'break;')
+
+    if count:
+        indent -= 1
+        line(out, indent, '}')
+
+    if inCase:
+        indent -= 1
+        line(out, indent, '}')
+
+
+def rpartition(string, sep):
+
+    if python_ver >= '2.5.0':
+        return string.rpartition(sep)
+    else:
+        parts = split_pkg(string, sep)
+        if len(parts) == 1:
+            return ('', '', parts[0])
+        return (parts[0], sep, parts[1])
+
+
+def fieldValue(cls, value, fieldType):
+
+    if fieldType.isArray():
+        fieldType = fieldType.getComponentType()
+        if fieldType.isArray():
+            result = 'JArray<jobject>(%s->this$).wrap(NULL)'
+        elif fieldType.isPrimitive():
+            result = '%s->wrap()'
+        elif fieldType.getName() == 'java.lang.String':
+            result = 'JArray<jstring>(%s->this$).wrap()'
+        else:
+            parts = rpartition(typename(fieldType, cls, False), '::')
+            result = 'JArray<jobject>(%%s->this$).wrap(%s%st_%s::wrap_jobject)' %(parts)
+
+    elif fieldType.getName() == 'java.lang.String':
+        result = 'j2p(*%s)'
+
+    elif not fieldType.isPrimitive():
+        parts = rpartition(typename(fieldType, cls, False), '::')
+        result = '%s%st_%s::wrap_Object(*%%s)' %(parts)
+
+    else:
+        return value
+
+    return result %(value)
+
+
+def returnValue(cls, returnType, value, genericRT=None, typeParams=None):
+
+    result = RESULTS.get(returnType.getName())
+    if result:
+        return result %(value)
+
+    if returnType.isArray():
+        returnType = returnType.getComponentType()
+        depth = 1
+        while returnType.isArray():
+            returnType = returnType.getComponentType()
+            depth += 1
+        if depth > 1:
+            return 'return JArray<jobject>(%s.this$).wrap(NULL);' %(value)
+        elif returnType.isPrimitive():
+            return 'return %s.wrap();' %(value)
+        elif returnType.getName() == 'java.lang.String':
+            return 'return JArray<jstring>(%s.this$).wrap();' %(value)
+
+        ns, sep, n = rpartition(typename(returnType, cls, False), '::')
+        return 'return JArray<jobject>(%s.this$).wrap(%s%st_%s::wrap_jobject);' %(value, ns, sep, n)
+
+    ns, sep, n = rpartition(typename(returnType, cls, False), '::')
+    if genericRT is not None:
+        if ParameterizedType.instance_(genericRT):
+            genericRT = ParameterizedType.cast_(genericRT)
+            clsArgs = []
+            for clsArg in genericRT.getActualTypeArguments():
+                if Class.instance_(clsArg):
+                    clsNames = Class.cast_(clsArg).getName().split('.')
+                    clsArg = '&%s::%s$$Type' %('::'.join(cppnames(clsNames[:-1])), cppname(clsNames[-1]))
+                    clsArgs.append(clsArg)
+                elif TypeVariable.instance_(clsArg):
+                    gd = TypeVariable.cast_(clsArg).getGenericDeclaration()
+                    if Class.instance_(gd):
+                        i = 0
+                        for clsParam in gd.getTypeParameters():
+                            if clsArg == clsParam:
+                                clsArgs.append('self->parameters[%d]' %(i))
+                                break
+                            i += 1
+                        else:
+                            break
+                    else:
+                        break
+                else:
+                    break
+            else:
+                return 'return %s%st_%s::wrap_Object(%s, %s);' %(ns, sep, n, value, ', '.join(clsArgs))
+        elif TypeVariable.instance_(genericRT):
+            gd = TypeVariable.cast_(genericRT).getGenericDeclaration()
+            i = 0
+            if Class.instance_(gd):
+                for clsParam in gd.getTypeParameters():
+                    if genericRT == clsParam:
+                        return 'return self->parameters[%d] != NULL ? wrapType(self->parameters[%d], %s.this$) : %s%st_%s::wrap_Object(%s);' %(i, i, value, ns, sep, n, value)
+                    i += 1
+            elif Method.instance_(gd):
+                for clsParam in gd.getTypeParameters():
+                    if genericRT == clsParam and i in typeParams:
+                        return 'return p%d != NULL && p%d[0] != NULL ? wrapType(p%d[0], %s.this$) : %s%st_%s::wrap_Object(%s);' %(i, i, i, value, ns, sep, n, value)
+                    i += 1
+
+    return 'return %s%st_%s::wrap_Object(%s);' %(ns, sep, n, value)
+
+
+def call(out, indent, cls, inCase, method, names, cardinality, isExtension,
+         generics):
+
+    if inCase:
+        line(out, indent, '{')
+        indent += 1
+
+    name = method.getName()
+    modifiers = method.getModifiers()
+    params = method.getParameterTypes()
+    returnType = method.getReturnType()
+    if generics:
+        genericRT = method.getGenericReturnType()
+        typeParams = set()
+    else:
+        genericRT = None
+        typeParams = None
+    count = len(params)
+
+    declareVars(out, indent, params, cls, generics, typeParams)
+
+    returnName = returnType.getName()
+    if returnName != 'void':
+        line(out, indent, '%s result%s;',
+             typename(returnType, cls, False),
+             not returnType.isPrimitive() and '((jobject) NULL)' or '')
+        result = 'result = '
+    else:
+        result = ''
+
+    if cardinality and (count or not inCase):
+        s = cardinality > 1 and 's' or ''
+        line(out)
+        if isExtension and name == 'clone' and Modifier.isNative(modifiers):
+            line(out, indent, 'if (arg)')
+        else:
+            line(out, indent, 'if (!parseArg%s(arg%s, "%s"%s%s))',
+                 s, s, *parseArgs(params, cls, generics))
+        line(out, indent, '{')
+        indent += 1
+
+    name = cppname(name)
+    if Modifier.isStatic(modifiers):
+        line(out, indent, 'OBJ_CALL(%s%s::%s(%s));',
+             result, '::'.join(cppnames(names)), name,
+             ', '.join(['a%d' %(i) for i in xrange(count)]))
+    else:
+        line(out, indent, 'OBJ_CALL(%sself->object.%s(%s));',
+             result, name, ', '.join(['a%d' %(i) for i in xrange(count)]))
+
+    if isExtension and name == 'clone' and Modifier.isNative(modifiers):
+        line(out)
+        line(out, indent, '%s object(result.this$);', typename(cls, cls, False))
+        line(out, indent, 'if (PyObject_TypeCheck(arg, &FinalizerProxy$$Type) &&')
+        line(out, indent, '    PyObject_TypeCheck(((t_fp *) arg)->object, self->ob_type))')
+        line(out, indent, '{')
+        line(out, indent + 1, 'PyObject *_arg = ((t_fp *) arg)->object;')
+        line(out, indent + 1, '((t_JObject *) _arg)->object = object;')
+        line(out, indent + 1, 'Py_INCREF(_arg);')
+        line(out, indent + 1, 'object.pythonExtension((jlong) (Py_intptr_t) (void *) _arg);')
+        line(out, indent + 1, 'Py_INCREF(arg);')
+        line(out, indent + 1, 'return arg;')
+        line(out, indent, '}')
+        line(out, indent, 'return PyErr_SetArgsError("%s", arg);' %(name))
+    elif returnName != 'void':
+        line(out, indent, returnValue(cls, returnType, 'result',
+                                      genericRT, typeParams))
+    else:
+        line(out, indent, 'Py_RETURN_NONE;')
+    if cardinality and (count or not inCase):
+        indent -= 1
+        line(out, indent, '}')
+
+    if inCase:
+        indent -= 1
+        line(out, indent, '}')
+
+
+def methodargs(methods, superMethods):
+        
+    if len(methods) == 1 and methods[0].getName() not in superMethods:
+        count = len(methods[0].getParameterTypes())
+        if count == 0:
+            return '', '', 0
+        elif count == 1:
+            return ', PyObject *arg', ', arg', 1
+
+    return ', PyObject *args', ', args', 2
+
+
+def jniname(cls):
+    
+    if cls.isPrimitive():
+        name = cls.getName()
+        if name != 'void':
+            name = 'j' + name
+    else:
+        name = 'jobject'
+
+    return name
+
+
+def jniargs(params):
+
+    count = len(params)
+    decls = ', '.join(['%s a%d' %(jniname(params[i]), i)
+                       for i in xrange(count)])
+    if decls:
+        return ', ' + decls
+
+    return ''
+
+
+def extension(env, out, indent, cls, names, name, count, method, generics):
+
+    line(out, indent, 'jlong ptr = jenv->CallLongMethod(jobj, %s::mids$[%s::mid_pythonExtension_%s]);',
+         cppname(names[-1]), cppname(names[-1]), env.strhash('()J'))
+    line(out, indent, 'PyObject *obj = (PyObject *) (Py_intptr_t) ptr;')
+
+    if name == 'pythonDecRef':
+        line(out)
+        line(out, indent, 'if (obj != NULL)')
+        line(out, indent, '{')
+        line(out, indent + 1, 'jenv->CallVoidMethod(jobj, %s::mids$[%s::mid_pythonExtension_%s], (jlong) 0);',
+             cppname(names[-1]), cppname(names[-1]), env.strhash('(J)V'))
+        line(out, indent + 1, 'env->finalizeObject(jenv, obj);')
+        line(out, indent, '}')
+        return
+
+    line(out, indent, 'PythonGIL gil(jenv);')
+
+    returnType = method.getReturnType()
+    returnName = returnType.getName()
+    if returnName != 'void':
+        line(out, indent, '%s value%s;',
+             typename(returnType, cls, False),
+             not returnType.isPrimitive() and '((jobject) NULL)' or '')
+
+    sigs = []
+    decrefs = []
+    args = []
+    i = 0
+    for param in method.getParameterTypes():
+        typeName = param.getName()
+        if typeName in CALLARGS:
+            sig, code, decref = CALLARGS[typeName]
+        elif param.isArray():
+            param = param.getComponentType()
+            if param.isPrimitive():
+                code = 'JArray<j%s>(%%s).wrap()' %(param.getName())
+            elif param.isArray():
+                code = 'JArray<jobject>(%s).wrap(NULL)'
+            elif param.getName() == 'java.lang.String':
+                code = 'JArray<jstring>(%s).wrap()'
+            else:
+                parts = rpartition(typename(param, cls, False), '::')
+                code = 'JArray<jobject>(%%s).wrap(%s%st_%s::wrap_jobject)' %(parts)
+            sig, decref = 'O', True
+        elif param.getName() == 'java.lang.String':
+            sig, code, decref = 'O', 'j2p(%%s))', True
+        else:
+            parts = rpartition(typename(param, cls, False), '::')
+            sig, code, decref = 'O', '%s%st_%s::wrap_Object(%s%s%s(%%s))' %(parts*2), True
+        if sig == 'O':
+            line(out, indent, 'PyObject *o%d = %s;', i, code %('a%d' %(i)))
+            args.append('o%d' %(i))
+        else:
+            args.append(code %('a%d' %(i)))
+        sigs.append(sig)
+        decrefs.append(decref)
+        i += 1
+
+    args = ', '.join(args)
+    if args:
+        args = ', ' + args
+    line(out, indent, 'PyObject *result = PyObject_CallMethod(obj, "%s", "%s"%s);',
+         name, ''.join(sigs), args)
+    i = 0
+    for decref in decrefs:
+        if decref:
+            line(out, indent, 'Py_DECREF(o%d);', i)
+        i += 1
+    line(out, indent, 'if (!result)')
+    line(out, indent + 1, 'throwPythonError();')
+    if returnName == 'void':
+        line(out, indent, 'else')
+        line(out, indent + 1, 'Py_DECREF(result);')
+    else:
+        signature, check, x = parseArgs([returnType], cls, False)
+        line(out, indent, 'else if (parseArg(result, "%s"%s, &value))',
+             signature, check)
+        line(out, indent, '{')
+        line(out, indent + 1, 'throwTypeError("%s", result);', name)
+        line(out, indent + 1, 'Py_DECREF(result);')
+        line(out, indent, '}')
+        line(out, indent, 'else')
+        line(out, indent, '{')
+        if not returnType.isPrimitive():
+            line(out, indent + 1, 'jobj = jenv->NewLocalRef(value.this$);')
+        line(out, indent + 1, 'Py_DECREF(result);')
+        if returnType.isPrimitive():
+            line(out, indent + 1, 'return value;')
+        else:
+            line(out, indent + 1, 'return jobj;')
+        line(out, indent, '}')
+        line(out)
+        if returnType.isPrimitive():
+            line(out, indent, 'return (j%s) 0;', returnName)
+        else:
+            line(out, indent, 'return (jobject) NULL;')
+
+
+def python(env, out_h, out, cls, superCls, names, superNames,
+           constructors, methods, protectedMethods, fields, instanceFields,
+           mapping, sequence, rename, declares, typeset, moduleName, generics):
+
+    line(out_h)
+    line(out_h, 0, '#include <Python.h>')
+    line(out_h)
+
+    indent = 0
+    for name in names[:-1]:
+        line(out_h, indent, 'namespace %s {', cppname(name))
+        indent += 1
+    line(out_h, indent, 'extern PyTypeObject %s$$Type;', names[-1])
+
+    if generics:
+        clsParams = cls.getTypeParameters()
+    else:
+        clsParams = None
+
+    line(out_h)
+    line(out_h, indent, 'class t_%s {', names[-1])
+    line(out_h, indent, 'public:')
+    line(out_h, indent + 1, 'PyObject_HEAD')
+    line(out_h, indent + 1, '%s object;', cppname(names[-1]))
+    if clsParams:
+        line(out_h, indent + 1, 'PyTypeObject *parameters[%d];', len(clsParams))
+        line(out_h, indent + 1, 'static PyTypeObject **parameters_(t_%s *self)',
+             cppname(names[-1]))
+        line(out_h, indent + 1, '{')
+        line(out_h, indent + 2, 'return (PyTypeObject **) &(self->parameters);')
+        line(out_h, indent + 1, '}')
+
+    line(out_h, indent + 1, 'static PyObject *wrap_Object(const %s&);',
+         cppname(names[-1]))
+    if clsParams:
+        line(out_h, indent + 1, 'static PyObject *wrap_Object(const %s&, %s);',
+             cppname(names[-1]),
+             ', '.join(['PyTypeObject *'] * len(clsParams)))
+    line(out_h, indent + 1, 'static PyObject *wrap_jobject(const jobject&);')
+    line(out_h, indent + 1, 'static void install(PyObject *module);')
+    line(out_h, indent + 1, 'static void initialize(PyObject *module);')
+    line(out_h, indent, '};')
+
+    iterator = findClass('java/util/Iterator')
+    enumeration = findClass('java/util/Enumeration')
+
+    while indent:
+        indent -= 1
+        line(out_h, indent, '}')
+
+    line(out)
+    line(out, 0, '#include "structmember.h"')
+    line(out, 0, '#include "functions.h"')
+    line(out, 0, '#include "macros.h"')
+
+    for inner in cls.getDeclaredClasses():
+        if inner in typeset and not inner in declares:
+            if Modifier.isStatic(inner.getModifiers()):
+                line(out, 0, '#include "%s.h"',
+                     inner.getName().replace('.', '/'))
+
+    for method in methods:
+        if method.getName() == 'pythonExtension':
+            isExtension = True
+            break
+    else:
+        isExtension = False
+                
+    line(out)
+    indent = 0
+    for name in names[:-1]:
+        line(out, indent, 'namespace %s {', cppname(name))
+        indent += 1
+
+    line(out, indent, 'static PyObject *t_%s_cast_(PyTypeObject *type, PyObject *arg);', names[-1])
+    line(out, indent, 'static PyObject *t_%s_instance_(PyTypeObject *type, PyObject *arg);', names[-1])
+
+    if constructors:
+        line(out, indent, 'static int t_%s_init_(t_%s *self, PyObject *args, PyObject *kwds);', names[-1], names[-1])
+        constructorName = 't_%s_init_' %(names[-1])
+    else:
+        constructorName = 'abstract_init'
+
+    if superCls:
+        superMethods = set([method.getName()
+                            for method in superCls.getMethods()])
+    else:
+        superMethods = ()
+
+    allMethods = {}
+    extMethods = {}
+    propMethods = {}
+
+    if methods:
+        for method in methods:
+            modifiers = method.getModifiers()
+            name = method.getName()
+            params = method.getParameterTypes()
+            superMethod = None
+            isNative = Modifier.isNative(modifiers)
+            isStatic = Modifier.isStatic(modifiers)
+
+            if (isExtension and not isStatic and superCls and isNative):
+                superMethod = find_method(superCls, name, params)
+
+            if isExtension and isNative and not isStatic:
+                extMethods.setdefault(name, []).append(method)
+
+            if superMethod or not (isExtension and isNative and not isStatic):
+                if isStatic:
+                    if name in allMethods:
+                        if Modifier.isStatic(allMethods[name][0].getModifiers()):
+                            allMethods[name].append(method)
+                        elif name + '_' in allMethods:
+                            allMethods[name + '_'].append(method)
+                        else:
+                            print >>sys.stderr, "  Warning: renaming static method '%s' on class %s to '%s_' since it is shadowed by non-static method of same name." %(name, '.'.join(names), name)
+                            allMethods[name + '_'] = [method]
+                    else:
+                        allMethods[name] = [method]
+                else:
+                    if name in allMethods:
+                        if Modifier.isStatic(allMethods[name][0].getModifiers()):
+                            print >>sys.stderr, "  Warning: renaming static method '%s' on class %s to '%s_' since it is shadowed by non-static method of same name." %(name, '.'.join(names), name)
+                            allMethods[name + '_'] = allMethods[name]
+                            allMethods[name] = [method]
+                        else:
+                            allMethods[name].append(method)
+                    else:
+                        allMethods[name] = [method]
+
+            if not (isExtension and isNative):
+                nameLen = len(name)
+                paramsLen = len(params)
+                if nameLen > 3 and paramsLen == 0 and name.startswith('get'):
+                    propMethods.setdefault(name[3].lower() + name[4:],
+                                           []).append(method)
+                elif nameLen > 3 and paramsLen == 1 and name.startswith('set'):
+                    propMethods.setdefault(name[3].lower() + name[4:],
+                                           []).append(method)
+                elif nameLen > 2 and paramsLen == 0 and name.startswith('is'):
+                    propMethods.setdefault(name[2].lower() + name[3:],
+                                           []).append(method)
+
+    properties = set([name for name in propMethods.iterkeys()
+                      if name not in allMethods])
+    propMethods = [(name, propMethods[name]) for name in properties]
+    sort(propMethods, key=lambda x: x[0])
+
+    extMethods = extMethods.items()
+    sort(extMethods, key=lambda x: x[0])
+    allMethods = allMethods.items()
+    sort(allMethods, key=lambda x: x[0])
+
+    iteratorMethod = None
+    iteratorExt = False
+    nextMethod = None
+    nextExt = False
+    nextElementMethod = None
+    nextElementExt = False
+
+    mappingMethod = None
+    if mapping:
+        mappingName, mappingSig = mapping.split(':')
+
+    sequenceLenMethod = None
+    sequenceGetMethod = None
+    if sequence:
+        sequenceLenName, sequenceLenSig = sequence[0].split(':')
+        sequenceGetName, sequenceGetSig = sequence[1].split(':')
+
+    for name, methods in allMethods:
+        args, x, cardinality = methodargs(methods, superMethods)
+        sort(methods, key=lambda x: len(x.getParameterTypes()))
+        method = methods[0]
+        modifiers = method.getModifiers()
+        if name == 'iterator' and iteratorMethod is None:
+            if (not method.getParameterTypes() and
+                iterator.isAssignableFrom(method.getReturnType())):
+                iteratorMethod = method
+        elif name == 'next' and nextMethod is None:
+            if (not method.getParameterTypes() and
+                not method.getReturnType().isPrimitive()):
+                nextMethod = method
+        elif name == 'nextElement' and nextElementMethod is None:
+            if (not method.getParameterTypes() and
+                not method.getReturnType().isPrimitive()):
+                nextElementMethod = method
+        elif mapping and name == mappingName and mappingMethod is None:
+            if signature(method) == mappingSig:
+                mappingMethod = (method, cardinality)
+        elif sequence and name == sequenceLenName and sequenceLenMethod is None:
+            if signature(method) == sequenceLenSig:
+                sequenceLenMethod = (method, cardinality)
+        elif sequence and name == sequenceGetName and sequenceGetMethod is None:
+            if signature(method) == sequenceGetSig:
+                sequenceGetMethod = (method, cardinality)
+        elif isExtension and name == 'clone' and Modifier.isNative(modifiers):
+            args, x, cardinality = ', PyObject *arg', ', arg', 1
+
+        if Modifier.isStatic(modifiers):
+            line(out, indent, 'static PyObject *t_%s_%s(PyTypeObject *type%s);',
+                 names[-1], name, args)
+        else:
+            line(out, indent, 'static PyObject *t_%s_%s(t_%s *self%s);',
+                 names[-1], name, names[-1], args)
+
+    for name, methods in extMethods:
+        args, x, cardinality = methodargs(methods, superMethods)
+        sort(methods, key=lambda x: len(x.getParameterTypes()))
+        method = methods[0]
+        modifiers = method.getModifiers()
+        if name == 'iterator' and iteratorMethod is None:
+            if (not method.getParameterTypes() and
+                iterator.isAssignableFrom(method.getReturnType())):
+                iteratorMethod = method
+                iteratorExt = True
+        elif name == 'next' and nextMethod is None:
+            if (not method.getParameterTypes() and
+                not method.getReturnType().isPrimitive()):
+                nextMethod = method
+                nextExt = True
+        elif name == 'nextElement' and nextElementMethod is None:
+            if (not method.getParameterTypes() and
+                not method.getReturnType().isPrimitive()):
+                nextElementMethod = method
+                nextElementExt = True
+
+    if isExtension:
+        count = 0
+        for name, methods in extMethods:
+            for method in methods:
+                line(out, indent,
+                     'static %s JNICALL t_%s_%s%d(JNIEnv *jenv, jobject jobj%s);',
+                     jniname(method.getReturnType()), names[-1], name, count,
+                     jniargs(method.getParameterTypes()))
+                count += 1
+        line(out, indent, 'static PyObject *t_%s_get__self(t_%s *self, void *data);', names[-1], names[-1])
+
+    if instanceFields:
+        for field in instanceFields:
+            fieldName = field.getName()
+            if fieldName not in properties:
+                line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data);',
+                     names[-1], fieldName, names[-1])
+                if not Modifier.isFinal(field.getModifiers()):
+                    line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data);',
+                         names[-1], field.getName(), names[-1])
+        line(out)
+
+    for fieldName, methods in propMethods:
+        getter = False
+        setter = False
+        for method in methods:
+            methodName = method.getName()
+            if not getter and (methodName.startswith('get') or
+                               methodName.startswith('is')):
+                getter = True
+                line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data);',
+                     names[-1], fieldName, names[-1])
+            elif not setter and methodName.startswith('set'):
+                setter = True
+                line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data);',
+                     names[-1], fieldName, names[-1])
+    if clsParams:
+        line(out, indent, 'static PyObject *t_%s_get__parameters_(t_%s *self, void *data);', names[-1], names[-1])
+
+    if instanceFields or propMethods or isExtension or clsParams:
+        line(out, indent, 'static PyGetSetDef t_%s__fields_[] = {', names[-1])
+        for field in instanceFields:
+            fieldName = field.getName()
+            if fieldName not in properties:
+                if Modifier.isFinal(field.getModifiers()):
+                    line(out, indent + 1, 'DECLARE_GET_FIELD(t_%s, %s),',
+                         names[-1], fieldName)
+                else:
+                    line(out, indent + 1, 'DECLARE_GETSET_FIELD(t_%s, %s),',
+                         names[-1], fieldName)
+        for fieldName, methods in propMethods:
+            getter = False
+            setter = False
+            for method in methods:
+                methodName = method.getName()
+                if not getter and (methodName.startswith('get') or
+                                   methodName.startswith('is')):
+                    getter = True
+                elif not setter and methodName.startswith('set'):
+                    setter = True
+                if getter and setter:
+                    op = 'GETSET'
+                elif getter:
+                    op = 'GET'
+                elif setter:
+                    op = 'SET'
+            line(out, indent + 1, 'DECLARE_%s_FIELD(t_%s, %s),',
+                 op, names[-1], fieldName)
+        if isExtension:
+            line(out, indent + 1, 'DECLARE_GET_FIELD(t_%s, self),', names[-1])
+        if clsParams:
+            line(out, indent + 1, 'DECLARE_GET_FIELD(t_%s, parameters_),',
+                 names[-1])
+            
+        line(out, indent + 1, '{ NULL, NULL, NULL, NULL, NULL }')
+        line(out, indent, '};')
+
+    line(out)
+    line(out, indent, 'static PyMethodDef t_%s__methods_[] = {', names[-1])
+
+    line(out, indent + 1,
+         'DECLARE_METHOD(t_%s, cast_, METH_O | METH_CLASS),', names[-1])
+    line(out, indent + 1,
+         'DECLARE_METHOD(t_%s, instance_, METH_O | METH_CLASS),', names[-1])
+
+    for name, methods in allMethods:
+        modifiers = methods[0].getModifiers()
+        if len(methods) == 1 and not name in superMethods:
+            count = len(methods[0].getParameterTypes())
+            if count == 0:
+                args = 'METH_NOARGS'
+            elif count == 1:
+                args = 'METH_O'
+            else:
+                args = 'METH_VARARGS'
+        elif isExtension and name == 'clone' and Modifier.isNative(modifiers):
+            args = 'METH_O'
+        else:
+            args = 'METH_VARARGS'
+        if Modifier.isStatic(modifiers):
+            args += ' | METH_CLASS'
+
+        line(out, indent + 1, 'DECLARE_METHOD(t_%s, %s, %s),',
+             names[-1], name, args)
+    line(out, indent + 1, '{ NULL, NULL, 0, NULL }')
+    line(out, indent, '};')
+
+    if instanceFields or propMethods or isExtension or clsParams:
+        tp_getset = 't_%s__fields_' %(names[-1])
+    else:
+        tp_getset = '0'
+
+    if iteratorMethod:
+        if iteratorExt:
+            tp_iter = 'get_extension_iterator'
+        else:
+            tp_iter = '((PyObject *(*)(t_%s *)) get_%siterator<t_%s>)' %(names[-1], clsParams and 'generic_' or '', names[-1])
+        tp_iternext = '0'
+    elif nextMethod and iterator.isAssignableFrom(cls):
+        tp_iter = 'PyObject_SelfIter'
+        returnName = typename(nextMethod.getReturnType(), cls, False)
+        ns, sep, n = rpartition(returnName, '::')
+        if nextExt:
+            tp_iternext = 'get_extension_next'
+        else:
+            tp_iternext = '((PyObject *(*)(java::util::t_Iterator *)) get_%siterator_next<java::util::t_Iterator,%s%st_%s>)' %(clsParams and 'generic_' or '', ns, sep, n)
+    elif nextElementMethod and enumeration.isAssignableFrom(cls):
+        tp_iter = 'PyObject_SelfIter'
+        returnName = typename(nextElementMethod.getReturnType(), cls, False)
+        ns, sep, n = rpartition(returnName, '::')
+        if nextElementExt:
+            tp_iternext = 'get_extension_nextElement'
+        else:
+            tp_iternext = '((PyObject *(*)(java::util::t_Enumeration *)) get_%senumeration_next<java::util::t_Enumeration,%s%st_%s>)' %(clsParams and 'generic_' or '', ns, sep, n)
+    elif nextMethod:
+        tp_iter = 'PyObject_SelfIter'
+        returnName = typename(nextMethod.getReturnType(), cls, False)
+        ns, sep, n = rpartition(returnName, '::')
+        if nextExt:
+            tp_iternext = 'get_extension_next'
+        else:
+            tp_iternext = '((PyObject *(*)(t_%s *)) get_%snext<t_%s,%s%st_%s,%s>)' %(names[-1], clsParams and 'generic_' or '', names[-1], ns, sep, n, returnName)
+    else:
+        tp_iter = '0'
+        tp_iternext = '0'
+
+    if mappingMethod:
+        method, cardinality = mappingMethod
+        if cardinality > 1:
+            getName = 't_%s_%s_map_' %(names[-1], method.getName())
+            line(out, indent, 'static PyObject *%s(t_%s *self, PyObject *key);',
+                 getName, names[-1])
+        else:
+            getName = 't_%s_%s' %(names[-1], method.getName())
+        line(out)
+        line(out, indent, 'static PyMappingMethods t_%s_as_mapping = {',
+             names[-1])
+        line(out, indent + 1, '0,')
+        line(out, indent + 1, '(binaryfunc) %s,', getName)
+        line(out, indent + 1, '0,')
+        line(out, indent, '};')
+        tp_as_mapping = '&t_%s_as_mapping' %(names[-1])
+    else:
+        tp_as_mapping = '0'
+
+    if sequenceLenMethod or sequenceGetMethod:
+        if sequenceLenMethod:
+            method, cardinality = sequenceLenMethod
+            lenName = 't_%s_%s_seq_' %(names[-1], method.getName())
+            line(out, indent, 'static int %s(t_%s *self);', lenName, names[-1])
+        else:
+            lenName = '0'
+
+        if sequenceGetMethod:
+            method, cardinality = sequenceGetMethod
+            getName = 't_%s_%s_seq_' %(names[-1], method.getName())
+            line(out, indent, 'static PyObject *%s(t_%s *self, int n);',
+                 getName, names[-1])
+        else:
+            getName = '0'
+
+        line(out)
+        line(out, indent, 'static PySequenceMethods t_%s_as_sequence = {',
+             names[-1])
+        if python_ver < '2.5.0':
+            line(out, indent + 1, '(inquiry) %s,', lenName)
+            line(out, indent + 1, '0,')
+            line(out, indent + 1, '0,')
+            line(out, indent + 1, '(intargfunc) %s', getName)
+            line(out, indent, '};')
+        else:
+            line(out, indent + 1, '(lenfunc) %s,', lenName)
+            line(out, indent + 1, '0,')
+            line(out, indent + 1, '0,')
+            line(out, indent + 1, '(ssizeargfunc) %s', getName)
+            line(out, indent, '};')
+        tp_as_sequence = '&t_%s_as_sequence' %(names[-1])
+    else:
+        tp_as_sequence = '0'
+
+    if len(superNames) > 1:
+        base = '::'.join(('::'.join(cppnames(superNames[:-1])), superNames[-1]))
+    else:
+        base = superNames[-1]
+    line(out)
+    line(out, indent, 'DECLARE_TYPE(%s, t_%s, %s, %s, %s, %s, %s, %s, %s, %s);',
+         names[-1], names[-1], base, cppname(names[-1]), constructorName,
+         tp_iter, tp_iternext, tp_getset, tp_as_mapping, tp_as_sequence)
+
+    if clsParams:
+        clsArgs = []
+        for clsParam in clsParams:
+            clsArgs.append("PyTypeObject *%s" %(clsParam.getName()))
+        line(out, indent, 
+             "PyObject *t_%s::wrap_Object(const %s& object, %s)",
+             cppname(names[-1]), names[-1], ', '.join(clsArgs))
+        line(out, indent, "{")
+        line(out, indent + 1, "PyObject *obj = t_%s::wrap_Object(object);",
+             names[-1])
+        line(out, indent + 1, "if (obj != Py_None)")
+        line(out, indent + 1, "{")
+        line(out, indent + 2, "t_%s *self = (t_%s *) obj;",
+             names[-1], names[-1])
+        i = 0;
+        for clsParam in clsParams:
+            line(out, indent + 2, "self->parameters[%d] = %s;",
+                 i, clsParam.getName())
+        line(out, indent + 1, "}")
+        line(out, indent + 1, "return obj;");
+        line(out, indent, "}")
+
+    line(out)
+    line(out, indent, 'void t_%s::install(PyObject *module)', names[-1])
+    line(out, indent, '{')
+    line(out, indent + 1, 'installType(&%s$$Type, module, "%s", %d);',
+         names[-1], rename or names[-1], isExtension and 1 or 0)
+    for inner in cls.getDeclaredClasses():
+        if inner in typeset:
+            if Modifier.isStatic(inner.getModifiers()):
+                innerName = inner.getName().split('.')[-1]
+                line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "%s", make_descriptor(&%s$$Type));',
+                     names[-1], innerName[len(names[-1])+1:], innerName)
+    line(out, indent, '}')
+
+    line(out)
+    line(out, indent, 'void t_%s::initialize(PyObject *module)', names[-1])
+    line(out, indent, '{')
+    line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "class_", make_descriptor(%s::initializeClass, %s));',
+         names[-1], cppname(names[-1]), generics and 1 or 0)
+    line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "wrapfn_", make_descriptor(t_%s::wrap_jobject));',
+         names[-1], names[-1])
+
+    if isExtension:
+        line(out, indent + 1, 'jclass cls = %s::initializeClass();',
+             cppname(names[-1]))
+    elif fields:
+        line(out, indent + 1, '%s::initializeClass();', cppname(names[-1]))
+
+    if isExtension:
+        count = 0
+        line(out, indent + 1, 'JNINativeMethod methods[] = {')
+        for name, methods in extMethods:
+            for method in methods:
+                line(out, indent + 2, '{ "%s", "%s", (void *) t_%s_%s%d },',
+                     name, signature(method), names[-1], name, count)
+                count += 1
+        line(out, indent + 1, '};')
+        line(out, indent + 1, 'env->registerNatives(cls, methods, %d);',
+             count)
+
+    for field in fields:
+        fieldType = field.getType()
+        fieldName = field.getName()
+        value = '%s::%s' %(cppname(names[-1]), cppname(fieldName))
+        value = fieldValue(cls, value, fieldType)
+        line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "%s", make_descriptor(%s));',
+             names[-1], fieldName, value)
+    line(out, indent, '}')
+
+    line(out)
+    line(out, indent, 'static PyObject *t_%s_cast_(PyTypeObject *type, PyObject *arg)', names[-1])
+    line(out, indent, '{')
+    line(out, indent + 1, 'if (!(arg = castCheck(arg, %s::initializeClass, 1)))', cppname(names[-1]))
+    line(out, indent + 2, 'return NULL;')
+    line(out, indent + 1, 'return t_%s::wrap_Object(%s(((t_%s *) arg)->object.this$));', names[-1], cppname(names[-1]), names[-1])
+    line(out, indent, '}')
+
+    line(out, indent, 'static PyObject *t_%s_instance_(PyTypeObject *type, PyObject *arg)', names[-1])
+    line(out, indent, '{')
+    line(out, indent + 1, 'if (!castCheck(arg, %s::initializeClass, 0))', cppname(names[-1]))
+    line(out, indent + 2, 'Py_RETURN_FALSE;')
+    line(out, indent + 1, 'Py_RETURN_TRUE;')
+    line(out, indent, '}')
+
+    if constructors:
+        line(out)
+        line(out, indent, 'static int t_%s_init_(t_%s *self, PyObject *args, PyObject *kwds)', names[-1], names[-1])
+        line(out, indent, '{')
+        if len(constructors) > 1:
+            currLen = -1
+            line(out, indent + 1, 'switch (PyTuple_GET_SIZE(args)) {')
+            withErr = False
+            for constructor in constructors:
+                params = constructor.getParameterTypes()
+                if len(params) != currLen:
+                    if currLen >= 0:
+                        withErr = True
+                        line(out, indent + 2, 'goto err;')
+                    currLen = len(params)
+                    line(out, indent + 1, '%scase %d:', HALF_INDENT, currLen)
+                construct(out, indent + 2, cls, True, constructor, names,
+                          generics)
+            line(out, indent + 1, '%sdefault:', HALF_INDENT)
+            if withErr:
+                line(out, indent + 1, '%serr:', HALF_INDENT)
+            line(out, indent + 2, 'PyErr_SetArgsError((PyObject *) self, "__init__", args);')
+            line(out, indent + 2, 'return -1;')
+            line(out, indent + 1, '}')
+        else:
+            construct(out, indent + 1, cls, False, constructors[0], names,
+                      generics)
+            if constructors[0].getParameterTypes():
+                line(out, indent + 1, 'else')
+                line(out, indent + 1, '{')
+                line(out, indent + 2, 'PyErr_SetArgsError((PyObject *) self, "__init__", args);')
+                line(out, indent + 2, 'return -1;')
+                line(out, indent + 1, '}')
+
+        if isExtension:
+            line(out)
+            line(out, indent + 1, 'Py_INCREF((PyObject *) self);')
+            line(out, indent + 1, 'self->object.pythonExtension((jlong) (Py_intptr_t) (void *) self);')
+
+        line(out)
+        line(out, indent + 1, 'return 0;')
+        line(out, indent , '}')
+
+    for name, methods in allMethods:
+        line(out)
+        modifiers = methods[0].getModifiers()
+
+        if isExtension and name == 'clone' and Modifier.isNative(modifiers):
+            declargs, args, cardinality = ', PyObject *arg', ', arg', 1
+        else:
+            declargs, args, cardinality = methodargs(methods, superMethods)
+
+        static = Modifier.isStatic(modifiers)
+        if static:
+            line(out, indent, 'static PyObject *t_%s_%s(PyTypeObject *type%s)',
+                 names[-1], name, declargs)
+        else:
+            line(out, indent, 'static PyObject *t_%s_%s(t_%s *self%s)',
+                 names[-1], name, names[-1], declargs)
+
+        line(out, indent, '{')
+        if len(methods) > 1:
+            currLen = -1
+            line(out, indent + 1, 'switch (PyTuple_GET_SIZE(args)) {')
+            for method in methods:
+                params = method.getParameterTypes()
+                if len(params) != currLen:
+                    if currLen >= 0:
+                        line(out, indent + 2, 'break;')
+                    currLen = len(params)
+                    line(out, indent + 1, '%scase %d:', HALF_INDENT, currLen)
+                call(out, indent + 2, cls, True, method, names, cardinality,
+                     isExtension, generics)
+            line(out, indent + 1, '}')
+        else:
+            call(out, indent + 1, cls, False, methods[0], names, cardinality,
+                 isExtension, generics)
+
+        if args:
+            line(out)
+            if name in superMethods:
+                if static:
+                    line(out, indent + 1, 'return callSuper(type, "%s"%s, %d);',
+                         name, args, cardinality)
+                else:
+                    line(out, indent + 1, 'return callSuper(&%s$$Type, (PyObject *) self, "%s"%s, %d);',
+                         names[-1], name, args, cardinality)
+            else:
+                line(out, indent + 1, 'PyErr_SetArgsError(%s, "%s"%s);',
+                     static and 'type' or '(PyObject *) self', name, args)
+                line(out, indent + 1, 'return NULL;')
+
+        line(out, indent, '}')
+
+    if isExtension:
+        count = 0
+        for name, methods in extMethods:
+            for method in methods:
+                line(out)
+                line(out, indent,
+                     'static %s JNICALL t_%s_%s%d(JNIEnv *jenv, jobject jobj%s)',
+                     jniname(method.getReturnType()), names[-1], name, count,
+                     jniargs(method.getParameterTypes()))
+                count += 1
+                line(out, indent, '{')
+                extension(env, out, indent + 1, cls, names, name, count, method,
+                          generics)
+                line(out, indent, '}')
+        line(out)
+        line(out, indent, 'static PyObject *t_%s_get__self(t_%s *self, void *data)',
+             names[-1], names[-1])
+        line(out, indent, '{')
+        indent += 1
+        line(out, indent, 'jlong ptr;')
+        line(out, indent, 'OBJ_CALL(ptr = self->object.pythonExtension());')
+        line(out, indent, 'PyObject *obj = (PyObject *) (Py_intptr_t) ptr;')
+        line(out)
+        line(out, indent, 'if (obj != NULL)')
+        line(out, indent, '{')
+        line(out, indent + 1, 'Py_INCREF(obj);')
+        line(out, indent + 1, 'return obj;')
+        line(out, indent, '}')
+        line(out, indent, 'else')
+        line(out, indent + 1, 'Py_RETURN_NONE;')
+        indent -= 1
+        line(out, indent, '}')
+
+    if clsParams:
+        line(out, indent, 'static PyObject *t_%s_get__parameters_(t_%s *self, void *data)', names[-1], names[-1])
+        line(out, indent, '{')
+        line(out, indent + 1, 'return typeParameters(self->parameters, sizeof(self->parameters));')
+        line(out, indent, '}')
+
+    if instanceFields:
+        for field in instanceFields:
+            fieldName = field.getName()
+            if fieldName not in properties:
+                line(out)
+                fieldType = field.getType()
+                typeName = typename(fieldType, cls, False)
+                line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data)',
+                     names[-1], fieldName, names[-1])
+                line(out, indent, '{')
+                line(out, indent + 1, '%s value%s;', typeName,
+                     not fieldType.isPrimitive() and '((jobject) NULL)' or '')
+                line(out, indent + 1, 'OBJ_CALL(value = self->object._get_%s());',
+                     fieldName)
+                line(out, indent + 1, returnValue(cls, fieldType, 'value'))
+                line(out, indent, '}')
+
+                if not Modifier.isFinal(field.getModifiers()):
+                    line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data)',
+                         names[-1], fieldName, names[-1])
+                    line(out, indent, '{')
+                    line(out, indent + 1, '%s value%s;', typeName,
+                         not fieldType.isPrimitive() and '((jobject) NULL)' or '')
+                    sig, check, x = parseArgs([fieldType], cls, False)
+                    line(out, indent + 1, 'if (!parseArg(arg, "%s"%s, &value))',
+                         sig, check)
+                    line(out, indent + 1, '{')
+                    line(out, indent + 2, 'INT_CALL(self->object._set_%s(value));',
+                         fieldName)
+                    line(out, indent + 2, 'return 0;')
+                    line(out, indent + 1, '}')
+                    line(out, indent + 1, 'PyErr_SetArgsError((PyObject *) self, "%s", arg);',
+                         fieldName)
+                    line(out, indent + 1, 'return -1;')
+                    line(out, indent, '}')
+
+    if propMethods:
+        for fieldName, methods in propMethods:
+            line(out)
+            getter = None
+            setters = []
+            sort(methods, key=lambda x: x.getName())
+            for method in methods:
+                methodName = method.getName()
+                if not getter and (methodName.startswith('get') or
+                                   methodName.startswith('is')):
+                    getter = method
+                elif methodName.startswith('set'):
+                    setters.append(method)
+
+            if getter:
+                methodName = getter.getName()
+                returnType = getter.getReturnType()
+                typeName = typename(returnType, cls, False)
+                line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data)',
+                     names[-1], fieldName, names[-1])
+                line(out, indent, '{')
+                line(out, indent + 1, '%s value%s;', typeName,
+                     not returnType.isPrimitive() and '((jobject) NULL)' or '')
+                line(out, indent + 1, 'OBJ_CALL(value = self->object.%s());',
+                     methodName)
+                line(out, indent + 1, returnValue(cls, returnType, 'value'))
+                line(out, indent, '}')
+
+            if setters:
+                line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data)',
+                     names[-1], fieldName, names[-1])
+                line(out, indent, '{')
+                methodName = setters[0].getName()
+                for method in setters:
+                    argType = method.getParameterTypes()[0]
+                    typeName = typename(argType, cls, False)
+                    line(out, indent + 1, '{')
+                    line(out, indent + 2, '%s value%s;', typeName,
+                         not argType.isPrimitive() and '((jobject) NULL)' or '')
+                    sig, check, x = parseArgs([argType], cls, False)
+                    line(out, indent + 2, 'if (!parseArg(arg, "%s"%s, &value))',
+                         sig, check)
+                    line(out, indent + 2, '{')
+                    line(out, indent + 3, 'INT_CALL(self->object.%s(value));',
+                         methodName)
+                    line(out, indent + 3, 'return 0;')
+                    line(out, indent + 2, '}')
+                    line(out, indent + 1, '}')
+                line(out, indent + 1, 'PyErr_SetArgsError((PyObject *) self, "%s", arg);',
+                     fieldName)
+                line(out, indent + 1, 'return -1;')
+                line(out, indent, '}')
+
+    if mappingMethod:
+        method, cardinality = mappingMethod
+        if cardinality > 1:
+            methodName = method.getName()
+            getName = 't_%s_%s_map_' %(names[-1], methodName)
+            line(out)
+            line(out, indent, 'static PyObject *%s(t_%s *self, PyObject *arg)',
+                 getName, names[-1])
+            line(out, indent, '{')
+            call(out, indent + 1, cls, False, method, names, 1, isExtension,
+                 generics)
+            line(out)
+            line(out, indent + 1, 'PyErr_SetArgsError((PyObject *) self, "%s", arg);',
+                 methodName)
+            line(out, indent + 1, 'return NULL;')
+            line(out, indent, '}')
+
+    if sequenceLenMethod:
+        method, cardinality = sequenceLenMethod
+        methodName = method.getName()
+        lenName = 't_%s_%s_seq_' %(names[-1], methodName)
+        line(out)
+        line(out, indent, 'static int %s(t_%s *self)', lenName, names[-1])
+        line(out, indent, '{')
+        line(out, indent + 1, '%s len;',
+             typename(method.getReturnType(), cls, False))
+        line(out, indent + 1, 'INT_CALL(len = self->object.%s());', methodName)
+        line(out, indent + 1, 'return (int) len;')
+        line(out, indent, '}')
+
+    if sequenceGetMethod:
+        method, cardinality = sequenceGetMethod
+        methodName = method.getName()
+        returnType = method.getReturnType()
+        getName = 't_%s_%s_seq_' %(names[-1], methodName)
+        line(out)
+        line(out, indent, 'static PyObject *%s(t_%s *self, int n)', getName, names[-1])
+        line(out, indent, '{')
+        line(out, indent + 1, '%s result%s;',
+             typename(returnType, cls, False),
+             not returnType.isPrimitive() and '((jobject) NULL)' or '')
+        line(out, indent + 1, 'OBJ_CALL(result = self->object.%s((%s) n));',
+             methodName, typename(method.getParameterTypes()[0], cls, False))
+        line(out, indent + 1, returnValue(cls, returnType, 'result'))
+        line(out, indent, '}')
+
+    while indent:
+        indent -= 1
+        line(out, indent, '}')
+
+
+def package(out, allInOne, cppdir, namespace, names):
+
+    if not allInOne:
+        out = file(os.path.join(os.path.join(cppdir, *names),
+                                '__init__.cpp'), 'w')
+
+    if allInOne and not names or not allInOne:
+        line(out, 0, '#include <jni.h>')
+        line(out, 0, '#include <Python.h>')
+        line(out, 0, '#include "JCCEnv.h"')
+        line(out, 0, '#include "functions.h"')
+
+    if not names:
+        line(out)
+        line(out, 0, 'PyObject *initVM(PyObject *module, PyObject *args, PyObject *kwds);')
+
+    packages = []
+    types = []
+
+    namespaces = namespace.items()
+    sort(namespaces, key=lambda x: x[0])
+    for name, entries in namespaces:
+        if entries is True:
+            if names:
+                line(out, 0, '#include "%s/%s.h"', '/'.join(names), name)
+            else:
+                line(out, 0, '#include "%s.h"', name)
+            types.append(name)
+        else:
+            packages.append((name, entries))
+
+    indent = 0
+    if names:
+        line(out)
+        for name in names:
+            line(out, indent, 'namespace %s {', cppname(name))
+            indent += 1
+
+    line(out);
+    for name, entries in packages:
+        line(out, indent, 'namespace %s {', cppname(name))
+        line(out, indent + 1, 'void __install__(PyObject *module);')
+        line(out, indent + 1, 'void __initialize__(PyObject *module);')
+        line(out, indent, '}')
+
+    line(out)
+    line(out, indent, 'void __install__(PyObject *module)')
+    line(out, indent, '{')
+    for name in types:
+        line(out, indent + 1, 't_%s::install(module);', name)
+    for name, entries in packages:
+        line(out, indent + 1, '%s::__install__(module);', cppname(name))
+    line(out, indent, '}')
+
+    line(out)
+    if not names:
+        line(out, indent, 'PyObject *__initialize__(PyObject *module, PyObject *args, PyObject *kwds)')
+        line(out, indent, '{')
+        line(out, indent + 1, 'PyObject *env = initVM(module, args, kwds);')
+        line(out)
+        line(out, indent + 1, 'if (env == NULL)')
+        line(out, indent + 2, 'return NULL;')
+        line(out)
+        line(out, indent + 1, 'try {');
+        indent += 1
+    else:
+        line(out, indent, 'void __initialize__(PyObject *module)')
+        line(out, indent, '{')
+    for name in types:
+        line(out, indent + 1, 't_%s::initialize(module);', name)
+    for name, entries in packages:
+        line(out, indent + 1, '%s::__initialize__(module);', cppname(name))
+    if not names:
+        line(out, indent + 1, 'return env;')
+        indent -= 1
+        line(out, indent + 1, '} catch (JCCEnv::exception e) {')
+        line(out, indent + 2, 'PyErr_SetJavaError(e.throwable);')
+        line(out, indent + 2, 'return NULL;')
+        line(out, indent + 1, '}')
+
+    line(out, indent, '}')
+
+    while indent:
+        indent -= 1
+        line(out, indent, '}')
+
+    if not allInOne:
+        out.close()
+    else:
+        line(out)
+
+    for name, entries in packages:
+        package(out, allInOne, cppdir, entries, names + (name,))
+
+
+def module(out, allInOne, classes, cppdir, moduleName, shared, generics):
+
+    extname = '_%s' %(moduleName)
+    line(out, 0, '#include <Python.h>')
+    line(out, 0, '#include "macros.h"')
+    line(out, 0, '#include "jccfuncs.h"')
+
+    if allInOne:
+        out_init = file(os.path.join(cppdir, '__init__.cpp'), 'w')
+    namespaces = {}
+    for cls in classes:
+        namespace = namespaces
+        classNames = cls.getName().split('.')
+        for className in classNames[:-1]:
+            namespace = namespace.setdefault(className, {})
+        namespace[classNames[-1]] = True
+    if allInOne:
+        package(out_init, True, cppdir, namespaces, ())
+        out_init.close()
+    else:
+        package(None, False, cppdir, namespaces, ())
+
+    line(out)
+    line(out, 0, 'PyObject *initJCC(PyObject *module);')
+    line(out, 0, 'void __install__(PyObject *module);')
+    line(out, 0, 'extern PyTypeObject JObject$$Type, ConstVariableDescriptor$$Type, FinalizerClass$$Type, FinalizerProxy$$Type;')
+    line(out, 0, 'extern void _install_jarray(PyObject *);')
+    line(out)
+    line(out, 0, 'extern "C" {')
+
+    line(out)
+    line(out, 1, 'void init%s(void)', extname)
+    line(out, 1, '{')
+    line(out, 2, 'PyObject *module = Py_InitModule3("%s", jcc_funcs, "");',
+         extname);
+    line(out)
+    line(out, 2, 'initJCC(module);')
+    line(out)
+    line(out, 2, 'INSTALL_TYPE(JObject, module);')
+    line(out, 2, 'INSTALL_TYPE(ConstVariableDescriptor, module);')
+    line(out, 2, 'INSTALL_TYPE(FinalizerClass, module);')
+    line(out, 2, 'INSTALL_TYPE(FinalizerProxy, module);')
+    line(out, 2, '_install_jarray(module);')
+    line(out, 2, '__install__(module);')
+    line(out, 1, '}')
+    line(out, 0, '}')
+
+
+def compile(env, jccPath, output, moduleName, install, dist, debug, jars,
+            version, prefix, root, install_dir, home_dir, use_distutils,
+            shared, compiler, modules, wininst, arch, generics):
+
+    try:
+        if use_distutils:
+            raise ImportError
+        from setuptools import setup, Extension
+        with_setuptools = True
+        if shared and not SHARED:
+            raise NotImplementedError, "JCC was not built with --shared mode support, see JCC's INSTALL file for more information"
+    except ImportError:
+        if python_ver < '2.4':
+            raise ImportError, 'setuptools is required when using Python 2.3'
+        if shared:
+            raise ImportError, 'setuptools is required when using --shared'
+        from distutils.core import setup, Extension
+        with_setuptools = False
+
+    extname = '_%s' %(moduleName)
+
+    modulePath = os.path.join(output, moduleName)
+    if not os.path.isdir(modulePath):
+        os.makedirs(modulePath)
+
+    out = file(os.path.join(modulePath, '__init__.py'), 'w')
+    line(out)
+    if shared:
+        line(out, 0, "import os, sys")
+        line(out)
+        line(out, 0, "if sys.platform == 'win32':")
+        line(out, 1, "import jcc, %s", extname)
+        line(out, 0, "else:")
+        line(out, 1, "import %s", extname)
+    else:
+        line(out, 0, 'import os, %s', extname)
+    line(out)
+    line(out, 0, '__dir__ = os.path.abspath(os.path.dirname(__file__))')
+
+    package_data = []
+    for jar in jars:
+        shutil.copy2(jar, modulePath)
+        package_data.append(os.path.basename(jar))
+
+    packages = [moduleName]
+    if modules:
+        for module in modules:
+            if os.path.isdir(module):
+                def copytree(src, dst, is_package):
+                    if is_package:
+                        packages.append('.'.join((moduleName, src.replace(os.path.sep, '.'))))
+                    if not os.path.exists(dst):
+                        os.mkdir(dst)
+                    for name in os.listdir(src):
+                        if name.startswith('.'):
+                            continue
+                        _src = os.path.join(src, name)
+                        if os.path.islink(_src):
+                            continue
+                        _dst = os.path.join(dst, name)
+                        if os.path.isdir(_src):
+                            copytree(_src, _dst, os.path.exists(os.path.join(_src, '__init__.py')))
+                        elif not is_package or name.endswith('.py'):
+                            shutil.copy2(_src, _dst)
+                dst = modulePath
+                if os.path.exists(os.path.join(module, '__init__.py')):
+                    dst = os.path.join(modulePath, os.path.basename(module))
+                    copytree(module, dst, True)
+                else:
+                    copytree(module, dst, False)
+            else:
+                shutil.copy2(module.split('.')[0] + '.py', modulePath)
+
+    line(out)
+    line(out, 0, 'class JavaError(Exception):')
+    line(out, 1, 'def getJavaException(self):')
+    line(out, 2, 'return self.args[0]')
+    line(out, 1, 'def __str__(self):')
+    line(out, 2, 'writer = %s.StringWriter()', extname)
+    line(out, 2, 'self.getJavaException().printStackTrace(%s.PrintWriter(writer))', extname)
+    line(out, 2, 'return "\\n".join((super(JavaError, self).__str__(), "    Java stacktrace:", str(writer)))')
+    line(out)
+    line(out, 0, 'class InvalidArgsError(Exception):')
+    line(out, 1, 'pass')
+    line(out)
+    line(out, 0, '%s._set_exception_types(JavaError, InvalidArgsError)',
+         extname)
+
+    if version:
+        line(out)
+        line(out, 0, 'VERSION = "%s"', version)
+        
+    line(out, 0, 'CLASSPATH = [%s]' %(', '.join(['os.path.join(__dir__, "%s")' %(os.path.basename(jar)) for jar in jars])))
+    line(out, 0, 'CLASSPATH = os.pathsep.join(CLASSPATH)')
+    line(out, 0, '%s.CLASSPATH = CLASSPATH', extname)
+    line(out, 0, '%s._set_function_self(%s.initVM, %s)',
+         extname, extname, extname)
+
+    line(out)
+    line(out, 0, 'from %s import *', extname)
+    out.close()
+
+    includes = [os.path.join(output, extname),
+                os.path.join(jccPath, 'sources')]
+
+    sources = ['JObject.cpp', 'JArray.cpp', 'functions.cpp', 'types.cpp']
+    if not shared:
+        sources.append('jcc.cpp')
+        sources.append('JCCEnv.cpp')
+    for source in sources:
+	shutil.copy2(os.path.join(jccPath, 'sources', source),
+                     os.path.join(output, extname))
+
+    sources = []
+    for path, dirs, names in os.walk(os.path.join(output, extname)):
+        for name in names:
+            if name.endswith('.cpp'):
+                sources.append(os.path.join(path, name))
+
+    script_args = ['build_ext']
+
+    includes[0:0] = INCLUDES
+    compile_args = CFLAGS
+    link_args = LFLAGS
+    defines=['PYTHON']
+
+    if compiler:
+        script_args.append('--compiler=%s' %(compiler))
+
+    if shared:
+        defines.append('_jcc_shared')
+    script_args.append('--define=%s' %(','.join(defines)))
+
+    if debug:
+        script_args.append('--debug')
+        compile_args += DEBUG_CFLAGS
+    elif sys.platform == 'win32':
+        pass
+    elif sys.platform == 'sunos5':
+        link_args.append('-Wl,-s')
+    else:
+        link_args.append('-Wl,-S')
+
+    if install:
+        script_args.append('install')
+    if prefix:
+        script_args.append('--prefix=%s' % prefix)
+    if root:
+        script_args.append('--root=%s' % root)
+    if install_dir:
+        script_args.append('--install-lib=%s' % install_dir)
+    if home_dir:
+        script_args.append('--home=%s' % home_dir)
+
+    if dist:
+        if wininst:
+            script_args.append('bdist_wininst')
+        elif with_setuptools:
+            script_args.append('bdist_egg')
+        else:
+            script_args.append('bdist')
+
+    args = {
+        'extra_compile_args': compile_args,
+        'extra_link_args': link_args,
+        'include_dirs': includes,
+        'sources': sources
+    }
+
+    if generics:
+        args['define_macros'] = [('_java_generics', None)]
+
+    if shared:
+        shlibdir = os.path.dirname(os.path.dirname(_jcc.__file__))
+        if sys.platform == 'darwin':   # distutils no good with -R
+            machine = platform.machine()
+            if machine.startswith('iPod') or machine.startswith('iPhone'):
+                args['extra_link_args'] += ['-L' + shlibdir]
+            else:
+                args['extra_link_args'] += ['-Wl,-rpath', shlibdir]
+            args['library_dirs'] = [shlibdir]
+            args['libraries'] = ['jcc']
+        elif sys.platform == 'linux2': # distutils no good with -R
+            args['extra_link_args'] += ['-Wl,-rpath', shlibdir]
+            args['library_dirs'] = [shlibdir]
+            args['libraries'] = ['jcc']
+        elif sys.platform == 'win32':
+            jcclib = 'jcc%s.lib' %(debug and '_d' or '')
+            args['extra_link_args'] += [os.path.join(shlibdir, 'jcc', jcclib)]
+        else:
+            raise NotImplementedError, "shared mode on %s" %(sys.platform)
+
+    if arch and sys.platform == 'darwin':
+        from distutils import sysconfig
+
+        config_vars = sysconfig.get_config_vars()
+        cflags = config_vars['CFLAGS'].split(' ')
+        count = len(cflags)
+        i = 0
+        while i < count - 1:
+            if cflags[i] == '-arch' and cflags[i + 1] not in arch:
+                del cflags[i:i+2]
+                count -= 2
+            else:
+                i += 1
+        config_vars['CFLAGS'] = ' '.join(cflags)
+
+    extensions = [Extension('.'.join([moduleName, extname]), **args)]
+
+    args = {
+        'name': moduleName,
+        'packages': packages,
+        'package_dir': {moduleName: modulePath},
+        'package_data': {moduleName: package_data},
+        'version': version,
+        'ext_modules': extensions,
+        'script_args': script_args
+    }
+    if with_setuptools:
+        args['zip_safe'] = False
+
+    setup(**args)