diff -r b758351d191f -r cc9b7e14412b web/lib/arch/osx/jcc/python.py --- /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(%s->this$).wrap(NULL)' + elif fieldType.isPrimitive(): + result = '%s->wrap()' + elif fieldType.getName() == 'java.lang.String': + result = 'JArray(%s->this$).wrap()' + else: + parts = rpartition(typename(fieldType, cls, False), '::') + result = 'JArray(%%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(%s.this$).wrap(NULL);' %(value) + elif returnType.isPrimitive(): + return 'return %s.wrap();' %(value) + elif returnType.getName() == 'java.lang.String': + return 'return JArray(%s.this$).wrap();' %(value) + + ns, sep, n = rpartition(typename(returnType, cls, False), '::') + return 'return JArray(%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(%%s).wrap()' %(param.getName()) + elif param.isArray(): + code = 'JArray(%s).wrap(NULL)' + elif param.getName() == 'java.lang.String': + code = 'JArray(%s).wrap()' + else: + parts = rpartition(typename(param, cls, False), '::') + code = 'JArray(%%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 ') + 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)' %(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)' %(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)' %(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)' %(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 ') + line(out, 0, '#include ') + 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 ') + 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)