web/lib/arch/osx/jcc/python.py
changeset 29 cc9b7e14412b
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
       
     1 #
       
     2 #   Licensed under the Apache License, Version 2.0 (the "License");
       
     3 #   you may not use this file except in compliance with the License.
       
     4 #   You may obtain a copy of the License at
       
     5 #
       
     6 #       http://www.apache.org/licenses/LICENSE-2.0
       
     7 #
       
     8 #   Unless required by applicable law or agreed to in writing, software
       
     9 #   distributed under the License is distributed on an "AS IS" BASIS,
       
    10 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    11 #   See the License for the specific language governing permissions and
       
    12 #   limitations under the License.
       
    13 #
       
    14 
       
    15 import os, sys, platform, shutil, _jcc
       
    16 
       
    17 from cpp import PRIMITIVES, INDENT, HALF_INDENT
       
    18 from cpp import cppname, cppnames, typename
       
    19 from cpp import line, signature, find_method, split_pkg, sort
       
    20 from cpp import Modifier, Class, Method
       
    21 from _jcc import findClass
       
    22 from config import INCLUDES, CFLAGS, DEBUG_CFLAGS, LFLAGS, SHARED
       
    23 
       
    24 try:
       
    25     from cpp import ParameterizedType, TypeVariable
       
    26 except ImportError:
       
    27     pass
       
    28 
       
    29 python_ver = '%d.%d.%d' %(sys.version_info[0:3])
       
    30 if python_ver < '2.4':
       
    31     from sets import Set as set
       
    32 
       
    33 
       
    34 RESULTS = { 'boolean': 'Py_RETURN_BOOL(%s);',
       
    35             'byte': 'return PyInt_FromLong(%s);',
       
    36             'char': 'return PyUnicode_FromUnicode((Py_UNICODE *) &%s, 1);',
       
    37             'double': 'return PyFloat_FromDouble((double) %s);',
       
    38             'float': 'return PyFloat_FromDouble((double) %s);',
       
    39             'int': 'return PyInt_FromLong((long) %s);',
       
    40             'long': 'return PyLong_FromLongLong((PY_LONG_LONG) %s);',
       
    41             'short': 'return PyInt_FromLong((long) %s);',
       
    42             'java.lang.String': 'return j2p(%s);' }
       
    43 
       
    44 CALLARGS = { 'boolean': ('O', '(%s ? Py_True : Py_False)', False),
       
    45              'byte': ('O', 'PyInt_FromLong(%s)', True),
       
    46              'char': ('O', 'PyUnicode_FromUnicode((Py_UNICODE *) &%s, 1)', True),
       
    47              'double': ('d', '(double) %s', False),
       
    48              'float': ('f', '(float) %s', False),
       
    49              'int': ('i', '(int) %s', False),
       
    50              'long': ('L', '(long long) %s', False),
       
    51              'short': ('i', '(int) %s', False),
       
    52              'java.lang.String': ('O', 'env->fromJString((jstring) %s, 0)', True) }
       
    53 
       
    54 
       
    55 def parseArgs(params, current, generics):
       
    56 
       
    57     def signature(cls):
       
    58         array = ''
       
    59         while cls.isArray():
       
    60             array += '['
       
    61             cls = cls.getComponentType()
       
    62         clsName = cls.getName()
       
    63         if cls.isPrimitive():
       
    64             return array + PRIMITIVES[clsName]
       
    65         if clsName == 'java.lang.String':
       
    66             return array + 's'
       
    67         if clsName == 'java.lang.Object':
       
    68             return array + 'o'
       
    69         if generics and cls.getTypeParameters():
       
    70             return array + 'K'
       
    71         else:
       
    72             return array + 'k'
       
    73 
       
    74     def checkarg(cls):
       
    75         while cls.isArray():
       
    76             cls = cls.getComponentType()
       
    77         if (cls.isPrimitive() or
       
    78             cls.getName() in ('java.lang.String', 'java.lang.Object')):
       
    79             return ''
       
    80         return ', %s::initializeClass' %(typename(cls, current, False))
       
    81 
       
    82     def callarg(cls, i):
       
    83         if generics:
       
    84             while cls.isArray():
       
    85                 cls = cls.getComponentType()
       
    86             if cls.getTypeParameters():
       
    87                 ns, sep, n = rpartition(typename(cls, current, False), '::')
       
    88                 return ', &a%d, &p%d, %s%st_%s::parameters_' %(i, i, ns, sep, n)
       
    89         return ', &a%d' %(i)
       
    90 
       
    91     return (''.join([signature(param) for param in params]),
       
    92             ''.join([checkarg(param) for param in params]),
       
    93             ''.join([callarg(params[i], i) for i in xrange(len(params))]))
       
    94 
       
    95 
       
    96 def declareVars(out, indent, params, current, generics, typeParams):
       
    97 
       
    98     for i in xrange(len(params)):
       
    99         param = params[i]
       
   100         line(out, indent, '%s a%d%s;',
       
   101              typename(param, current, False), i,
       
   102              not param.isPrimitive() and '((jobject) NULL)' or '')
       
   103         if generics:
       
   104             while param.isArray():
       
   105                 param = param.getComponentType()
       
   106             if param.getTypeParameters():
       
   107                 line(out, indent, 'PyTypeObject **p%d;', i)
       
   108                 typeParams.add(i)
       
   109     
       
   110 
       
   111 def construct(out, indent, cls, inCase, constructor, names, generics):
       
   112 
       
   113     if inCase:
       
   114         line(out, indent, '{')
       
   115         indent += 1
       
   116 
       
   117     params = constructor.getParameterTypes()
       
   118     if generics:
       
   119         typeParams = set()
       
   120     else:
       
   121         typeParams = None
       
   122 
       
   123     count = len(params)
       
   124 
       
   125     declareVars(out, indent, params, cls, generics, typeParams)
       
   126     line(out, indent, '%s object((jobject) NULL);', cppname(names[-1]))
       
   127 
       
   128     line(out)
       
   129     if count:
       
   130         line(out, indent, 'if (!parseArgs(args, "%s"%s%s))',
       
   131              *parseArgs(params, cls, generics))
       
   132         line(out, indent, '{')
       
   133         indent += 1
       
   134 
       
   135     line(out, indent, 'INT_CALL(object = %s(%s));',
       
   136          cppname(names[-1]), ', '.join(['a%d' %(i) for i in xrange(count)]))
       
   137     line(out, indent, 'self->object = object;')
       
   138     if inCase:
       
   139         line(out, indent, 'break;')
       
   140 
       
   141     if count:
       
   142         indent -= 1
       
   143         line(out, indent, '}')
       
   144 
       
   145     if inCase:
       
   146         indent -= 1
       
   147         line(out, indent, '}')
       
   148 
       
   149 
       
   150 def rpartition(string, sep):
       
   151 
       
   152     if python_ver >= '2.5.0':
       
   153         return string.rpartition(sep)
       
   154     else:
       
   155         parts = split_pkg(string, sep)
       
   156         if len(parts) == 1:
       
   157             return ('', '', parts[0])
       
   158         return (parts[0], sep, parts[1])
       
   159 
       
   160 
       
   161 def fieldValue(cls, value, fieldType):
       
   162 
       
   163     if fieldType.isArray():
       
   164         fieldType = fieldType.getComponentType()
       
   165         if fieldType.isArray():
       
   166             result = 'JArray<jobject>(%s->this$).wrap(NULL)'
       
   167         elif fieldType.isPrimitive():
       
   168             result = '%s->wrap()'
       
   169         elif fieldType.getName() == 'java.lang.String':
       
   170             result = 'JArray<jstring>(%s->this$).wrap()'
       
   171         else:
       
   172             parts = rpartition(typename(fieldType, cls, False), '::')
       
   173             result = 'JArray<jobject>(%%s->this$).wrap(%s%st_%s::wrap_jobject)' %(parts)
       
   174 
       
   175     elif fieldType.getName() == 'java.lang.String':
       
   176         result = 'j2p(*%s)'
       
   177 
       
   178     elif not fieldType.isPrimitive():
       
   179         parts = rpartition(typename(fieldType, cls, False), '::')
       
   180         result = '%s%st_%s::wrap_Object(*%%s)' %(parts)
       
   181 
       
   182     else:
       
   183         return value
       
   184 
       
   185     return result %(value)
       
   186 
       
   187 
       
   188 def returnValue(cls, returnType, value, genericRT=None, typeParams=None):
       
   189 
       
   190     result = RESULTS.get(returnType.getName())
       
   191     if result:
       
   192         return result %(value)
       
   193 
       
   194     if returnType.isArray():
       
   195         returnType = returnType.getComponentType()
       
   196         depth = 1
       
   197         while returnType.isArray():
       
   198             returnType = returnType.getComponentType()
       
   199             depth += 1
       
   200         if depth > 1:
       
   201             return 'return JArray<jobject>(%s.this$).wrap(NULL);' %(value)
       
   202         elif returnType.isPrimitive():
       
   203             return 'return %s.wrap();' %(value)
       
   204         elif returnType.getName() == 'java.lang.String':
       
   205             return 'return JArray<jstring>(%s.this$).wrap();' %(value)
       
   206 
       
   207         ns, sep, n = rpartition(typename(returnType, cls, False), '::')
       
   208         return 'return JArray<jobject>(%s.this$).wrap(%s%st_%s::wrap_jobject);' %(value, ns, sep, n)
       
   209 
       
   210     ns, sep, n = rpartition(typename(returnType, cls, False), '::')
       
   211     if genericRT is not None:
       
   212         if ParameterizedType.instance_(genericRT):
       
   213             genericRT = ParameterizedType.cast_(genericRT)
       
   214             clsArgs = []
       
   215             for clsArg in genericRT.getActualTypeArguments():
       
   216                 if Class.instance_(clsArg):
       
   217                     clsNames = Class.cast_(clsArg).getName().split('.')
       
   218                     clsArg = '&%s::%s$$Type' %('::'.join(cppnames(clsNames[:-1])), cppname(clsNames[-1]))
       
   219                     clsArgs.append(clsArg)
       
   220                 elif TypeVariable.instance_(clsArg):
       
   221                     gd = TypeVariable.cast_(clsArg).getGenericDeclaration()
       
   222                     if Class.instance_(gd):
       
   223                         i = 0
       
   224                         for clsParam in gd.getTypeParameters():
       
   225                             if clsArg == clsParam:
       
   226                                 clsArgs.append('self->parameters[%d]' %(i))
       
   227                                 break
       
   228                             i += 1
       
   229                         else:
       
   230                             break
       
   231                     else:
       
   232                         break
       
   233                 else:
       
   234                     break
       
   235             else:
       
   236                 return 'return %s%st_%s::wrap_Object(%s, %s);' %(ns, sep, n, value, ', '.join(clsArgs))
       
   237         elif TypeVariable.instance_(genericRT):
       
   238             gd = TypeVariable.cast_(genericRT).getGenericDeclaration()
       
   239             i = 0
       
   240             if Class.instance_(gd):
       
   241                 for clsParam in gd.getTypeParameters():
       
   242                     if genericRT == clsParam:
       
   243                         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)
       
   244                     i += 1
       
   245             elif Method.instance_(gd):
       
   246                 for clsParam in gd.getTypeParameters():
       
   247                     if genericRT == clsParam and i in typeParams:
       
   248                         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)
       
   249                     i += 1
       
   250 
       
   251     return 'return %s%st_%s::wrap_Object(%s);' %(ns, sep, n, value)
       
   252 
       
   253 
       
   254 def call(out, indent, cls, inCase, method, names, cardinality, isExtension,
       
   255          generics):
       
   256 
       
   257     if inCase:
       
   258         line(out, indent, '{')
       
   259         indent += 1
       
   260 
       
   261     name = method.getName()
       
   262     modifiers = method.getModifiers()
       
   263     params = method.getParameterTypes()
       
   264     returnType = method.getReturnType()
       
   265     if generics:
       
   266         genericRT = method.getGenericReturnType()
       
   267         typeParams = set()
       
   268     else:
       
   269         genericRT = None
       
   270         typeParams = None
       
   271     count = len(params)
       
   272 
       
   273     declareVars(out, indent, params, cls, generics, typeParams)
       
   274 
       
   275     returnName = returnType.getName()
       
   276     if returnName != 'void':
       
   277         line(out, indent, '%s result%s;',
       
   278              typename(returnType, cls, False),
       
   279              not returnType.isPrimitive() and '((jobject) NULL)' or '')
       
   280         result = 'result = '
       
   281     else:
       
   282         result = ''
       
   283 
       
   284     if cardinality and (count or not inCase):
       
   285         s = cardinality > 1 and 's' or ''
       
   286         line(out)
       
   287         if isExtension and name == 'clone' and Modifier.isNative(modifiers):
       
   288             line(out, indent, 'if (arg)')
       
   289         else:
       
   290             line(out, indent, 'if (!parseArg%s(arg%s, "%s"%s%s))',
       
   291                  s, s, *parseArgs(params, cls, generics))
       
   292         line(out, indent, '{')
       
   293         indent += 1
       
   294 
       
   295     name = cppname(name)
       
   296     if Modifier.isStatic(modifiers):
       
   297         line(out, indent, 'OBJ_CALL(%s%s::%s(%s));',
       
   298              result, '::'.join(cppnames(names)), name,
       
   299              ', '.join(['a%d' %(i) for i in xrange(count)]))
       
   300     else:
       
   301         line(out, indent, 'OBJ_CALL(%sself->object.%s(%s));',
       
   302              result, name, ', '.join(['a%d' %(i) for i in xrange(count)]))
       
   303 
       
   304     if isExtension and name == 'clone' and Modifier.isNative(modifiers):
       
   305         line(out)
       
   306         line(out, indent, '%s object(result.this$);', typename(cls, cls, False))
       
   307         line(out, indent, 'if (PyObject_TypeCheck(arg, &FinalizerProxy$$Type) &&')
       
   308         line(out, indent, '    PyObject_TypeCheck(((t_fp *) arg)->object, self->ob_type))')
       
   309         line(out, indent, '{')
       
   310         line(out, indent + 1, 'PyObject *_arg = ((t_fp *) arg)->object;')
       
   311         line(out, indent + 1, '((t_JObject *) _arg)->object = object;')
       
   312         line(out, indent + 1, 'Py_INCREF(_arg);')
       
   313         line(out, indent + 1, 'object.pythonExtension((jlong) (Py_intptr_t) (void *) _arg);')
       
   314         line(out, indent + 1, 'Py_INCREF(arg);')
       
   315         line(out, indent + 1, 'return arg;')
       
   316         line(out, indent, '}')
       
   317         line(out, indent, 'return PyErr_SetArgsError("%s", arg);' %(name))
       
   318     elif returnName != 'void':
       
   319         line(out, indent, returnValue(cls, returnType, 'result',
       
   320                                       genericRT, typeParams))
       
   321     else:
       
   322         line(out, indent, 'Py_RETURN_NONE;')
       
   323     if cardinality and (count or not inCase):
       
   324         indent -= 1
       
   325         line(out, indent, '}')
       
   326 
       
   327     if inCase:
       
   328         indent -= 1
       
   329         line(out, indent, '}')
       
   330 
       
   331 
       
   332 def methodargs(methods, superMethods):
       
   333         
       
   334     if len(methods) == 1 and methods[0].getName() not in superMethods:
       
   335         count = len(methods[0].getParameterTypes())
       
   336         if count == 0:
       
   337             return '', '', 0
       
   338         elif count == 1:
       
   339             return ', PyObject *arg', ', arg', 1
       
   340 
       
   341     return ', PyObject *args', ', args', 2
       
   342 
       
   343 
       
   344 def jniname(cls):
       
   345     
       
   346     if cls.isPrimitive():
       
   347         name = cls.getName()
       
   348         if name != 'void':
       
   349             name = 'j' + name
       
   350     else:
       
   351         name = 'jobject'
       
   352 
       
   353     return name
       
   354 
       
   355 
       
   356 def jniargs(params):
       
   357 
       
   358     count = len(params)
       
   359     decls = ', '.join(['%s a%d' %(jniname(params[i]), i)
       
   360                        for i in xrange(count)])
       
   361     if decls:
       
   362         return ', ' + decls
       
   363 
       
   364     return ''
       
   365 
       
   366 
       
   367 def extension(env, out, indent, cls, names, name, count, method, generics):
       
   368 
       
   369     line(out, indent, 'jlong ptr = jenv->CallLongMethod(jobj, %s::mids$[%s::mid_pythonExtension_%s]);',
       
   370          cppname(names[-1]), cppname(names[-1]), env.strhash('()J'))
       
   371     line(out, indent, 'PyObject *obj = (PyObject *) (Py_intptr_t) ptr;')
       
   372 
       
   373     if name == 'pythonDecRef':
       
   374         line(out)
       
   375         line(out, indent, 'if (obj != NULL)')
       
   376         line(out, indent, '{')
       
   377         line(out, indent + 1, 'jenv->CallVoidMethod(jobj, %s::mids$[%s::mid_pythonExtension_%s], (jlong) 0);',
       
   378              cppname(names[-1]), cppname(names[-1]), env.strhash('(J)V'))
       
   379         line(out, indent + 1, 'env->finalizeObject(jenv, obj);')
       
   380         line(out, indent, '}')
       
   381         return
       
   382 
       
   383     line(out, indent, 'PythonGIL gil(jenv);')
       
   384 
       
   385     returnType = method.getReturnType()
       
   386     returnName = returnType.getName()
       
   387     if returnName != 'void':
       
   388         line(out, indent, '%s value%s;',
       
   389              typename(returnType, cls, False),
       
   390              not returnType.isPrimitive() and '((jobject) NULL)' or '')
       
   391 
       
   392     sigs = []
       
   393     decrefs = []
       
   394     args = []
       
   395     i = 0
       
   396     for param in method.getParameterTypes():
       
   397         typeName = param.getName()
       
   398         if typeName in CALLARGS:
       
   399             sig, code, decref = CALLARGS[typeName]
       
   400         elif param.isArray():
       
   401             param = param.getComponentType()
       
   402             if param.isPrimitive():
       
   403                 code = 'JArray<j%s>(%%s).wrap()' %(param.getName())
       
   404             elif param.isArray():
       
   405                 code = 'JArray<jobject>(%s).wrap(NULL)'
       
   406             elif param.getName() == 'java.lang.String':
       
   407                 code = 'JArray<jstring>(%s).wrap()'
       
   408             else:
       
   409                 parts = rpartition(typename(param, cls, False), '::')
       
   410                 code = 'JArray<jobject>(%%s).wrap(%s%st_%s::wrap_jobject)' %(parts)
       
   411             sig, decref = 'O', True
       
   412         elif param.getName() == 'java.lang.String':
       
   413             sig, code, decref = 'O', 'j2p(%%s))', True
       
   414         else:
       
   415             parts = rpartition(typename(param, cls, False), '::')
       
   416             sig, code, decref = 'O', '%s%st_%s::wrap_Object(%s%s%s(%%s))' %(parts*2), True
       
   417         if sig == 'O':
       
   418             line(out, indent, 'PyObject *o%d = %s;', i, code %('a%d' %(i)))
       
   419             args.append('o%d' %(i))
       
   420         else:
       
   421             args.append(code %('a%d' %(i)))
       
   422         sigs.append(sig)
       
   423         decrefs.append(decref)
       
   424         i += 1
       
   425 
       
   426     args = ', '.join(args)
       
   427     if args:
       
   428         args = ', ' + args
       
   429     line(out, indent, 'PyObject *result = PyObject_CallMethod(obj, "%s", "%s"%s);',
       
   430          name, ''.join(sigs), args)
       
   431     i = 0
       
   432     for decref in decrefs:
       
   433         if decref:
       
   434             line(out, indent, 'Py_DECREF(o%d);', i)
       
   435         i += 1
       
   436     line(out, indent, 'if (!result)')
       
   437     line(out, indent + 1, 'throwPythonError();')
       
   438     if returnName == 'void':
       
   439         line(out, indent, 'else')
       
   440         line(out, indent + 1, 'Py_DECREF(result);')
       
   441     else:
       
   442         signature, check, x = parseArgs([returnType], cls, False)
       
   443         line(out, indent, 'else if (parseArg(result, "%s"%s, &value))',
       
   444              signature, check)
       
   445         line(out, indent, '{')
       
   446         line(out, indent + 1, 'throwTypeError("%s", result);', name)
       
   447         line(out, indent + 1, 'Py_DECREF(result);')
       
   448         line(out, indent, '}')
       
   449         line(out, indent, 'else')
       
   450         line(out, indent, '{')
       
   451         if not returnType.isPrimitive():
       
   452             line(out, indent + 1, 'jobj = jenv->NewLocalRef(value.this$);')
       
   453         line(out, indent + 1, 'Py_DECREF(result);')
       
   454         if returnType.isPrimitive():
       
   455             line(out, indent + 1, 'return value;')
       
   456         else:
       
   457             line(out, indent + 1, 'return jobj;')
       
   458         line(out, indent, '}')
       
   459         line(out)
       
   460         if returnType.isPrimitive():
       
   461             line(out, indent, 'return (j%s) 0;', returnName)
       
   462         else:
       
   463             line(out, indent, 'return (jobject) NULL;')
       
   464 
       
   465 
       
   466 def python(env, out_h, out, cls, superCls, names, superNames,
       
   467            constructors, methods, protectedMethods, fields, instanceFields,
       
   468            mapping, sequence, rename, declares, typeset, moduleName, generics):
       
   469 
       
   470     line(out_h)
       
   471     line(out_h, 0, '#include <Python.h>')
       
   472     line(out_h)
       
   473 
       
   474     indent = 0
       
   475     for name in names[:-1]:
       
   476         line(out_h, indent, 'namespace %s {', cppname(name))
       
   477         indent += 1
       
   478     line(out_h, indent, 'extern PyTypeObject %s$$Type;', names[-1])
       
   479 
       
   480     if generics:
       
   481         clsParams = cls.getTypeParameters()
       
   482     else:
       
   483         clsParams = None
       
   484 
       
   485     line(out_h)
       
   486     line(out_h, indent, 'class t_%s {', names[-1])
       
   487     line(out_h, indent, 'public:')
       
   488     line(out_h, indent + 1, 'PyObject_HEAD')
       
   489     line(out_h, indent + 1, '%s object;', cppname(names[-1]))
       
   490     if clsParams:
       
   491         line(out_h, indent + 1, 'PyTypeObject *parameters[%d];', len(clsParams))
       
   492         line(out_h, indent + 1, 'static PyTypeObject **parameters_(t_%s *self)',
       
   493              cppname(names[-1]))
       
   494         line(out_h, indent + 1, '{')
       
   495         line(out_h, indent + 2, 'return (PyTypeObject **) &(self->parameters);')
       
   496         line(out_h, indent + 1, '}')
       
   497 
       
   498     line(out_h, indent + 1, 'static PyObject *wrap_Object(const %s&);',
       
   499          cppname(names[-1]))
       
   500     if clsParams:
       
   501         line(out_h, indent + 1, 'static PyObject *wrap_Object(const %s&, %s);',
       
   502              cppname(names[-1]),
       
   503              ', '.join(['PyTypeObject *'] * len(clsParams)))
       
   504     line(out_h, indent + 1, 'static PyObject *wrap_jobject(const jobject&);')
       
   505     line(out_h, indent + 1, 'static void install(PyObject *module);')
       
   506     line(out_h, indent + 1, 'static void initialize(PyObject *module);')
       
   507     line(out_h, indent, '};')
       
   508 
       
   509     iterator = findClass('java/util/Iterator')
       
   510     enumeration = findClass('java/util/Enumeration')
       
   511 
       
   512     while indent:
       
   513         indent -= 1
       
   514         line(out_h, indent, '}')
       
   515 
       
   516     line(out)
       
   517     line(out, 0, '#include "structmember.h"')
       
   518     line(out, 0, '#include "functions.h"')
       
   519     line(out, 0, '#include "macros.h"')
       
   520 
       
   521     for inner in cls.getDeclaredClasses():
       
   522         if inner in typeset and not inner in declares:
       
   523             if Modifier.isStatic(inner.getModifiers()):
       
   524                 line(out, 0, '#include "%s.h"',
       
   525                      inner.getName().replace('.', '/'))
       
   526 
       
   527     for method in methods:
       
   528         if method.getName() == 'pythonExtension':
       
   529             isExtension = True
       
   530             break
       
   531     else:
       
   532         isExtension = False
       
   533                 
       
   534     line(out)
       
   535     indent = 0
       
   536     for name in names[:-1]:
       
   537         line(out, indent, 'namespace %s {', cppname(name))
       
   538         indent += 1
       
   539 
       
   540     line(out, indent, 'static PyObject *t_%s_cast_(PyTypeObject *type, PyObject *arg);', names[-1])
       
   541     line(out, indent, 'static PyObject *t_%s_instance_(PyTypeObject *type, PyObject *arg);', names[-1])
       
   542 
       
   543     if constructors:
       
   544         line(out, indent, 'static int t_%s_init_(t_%s *self, PyObject *args, PyObject *kwds);', names[-1], names[-1])
       
   545         constructorName = 't_%s_init_' %(names[-1])
       
   546     else:
       
   547         constructorName = 'abstract_init'
       
   548 
       
   549     if superCls:
       
   550         superMethods = set([method.getName()
       
   551                             for method in superCls.getMethods()])
       
   552     else:
       
   553         superMethods = ()
       
   554 
       
   555     allMethods = {}
       
   556     extMethods = {}
       
   557     propMethods = {}
       
   558 
       
   559     if methods:
       
   560         for method in methods:
       
   561             modifiers = method.getModifiers()
       
   562             name = method.getName()
       
   563             params = method.getParameterTypes()
       
   564             superMethod = None
       
   565             isNative = Modifier.isNative(modifiers)
       
   566             isStatic = Modifier.isStatic(modifiers)
       
   567 
       
   568             if (isExtension and not isStatic and superCls and isNative):
       
   569                 superMethod = find_method(superCls, name, params)
       
   570 
       
   571             if isExtension and isNative and not isStatic:
       
   572                 extMethods.setdefault(name, []).append(method)
       
   573 
       
   574             if superMethod or not (isExtension and isNative and not isStatic):
       
   575                 if isStatic:
       
   576                     if name in allMethods:
       
   577                         if Modifier.isStatic(allMethods[name][0].getModifiers()):
       
   578                             allMethods[name].append(method)
       
   579                         elif name + '_' in allMethods:
       
   580                             allMethods[name + '_'].append(method)
       
   581                         else:
       
   582                             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)
       
   583                             allMethods[name + '_'] = [method]
       
   584                     else:
       
   585                         allMethods[name] = [method]
       
   586                 else:
       
   587                     if name in allMethods:
       
   588                         if Modifier.isStatic(allMethods[name][0].getModifiers()):
       
   589                             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)
       
   590                             allMethods[name + '_'] = allMethods[name]
       
   591                             allMethods[name] = [method]
       
   592                         else:
       
   593                             allMethods[name].append(method)
       
   594                     else:
       
   595                         allMethods[name] = [method]
       
   596 
       
   597             if not (isExtension and isNative):
       
   598                 nameLen = len(name)
       
   599                 paramsLen = len(params)
       
   600                 if nameLen > 3 and paramsLen == 0 and name.startswith('get'):
       
   601                     propMethods.setdefault(name[3].lower() + name[4:],
       
   602                                            []).append(method)
       
   603                 elif nameLen > 3 and paramsLen == 1 and name.startswith('set'):
       
   604                     propMethods.setdefault(name[3].lower() + name[4:],
       
   605                                            []).append(method)
       
   606                 elif nameLen > 2 and paramsLen == 0 and name.startswith('is'):
       
   607                     propMethods.setdefault(name[2].lower() + name[3:],
       
   608                                            []).append(method)
       
   609 
       
   610     properties = set([name for name in propMethods.iterkeys()
       
   611                       if name not in allMethods])
       
   612     propMethods = [(name, propMethods[name]) for name in properties]
       
   613     sort(propMethods, key=lambda x: x[0])
       
   614 
       
   615     extMethods = extMethods.items()
       
   616     sort(extMethods, key=lambda x: x[0])
       
   617     allMethods = allMethods.items()
       
   618     sort(allMethods, key=lambda x: x[0])
       
   619 
       
   620     iteratorMethod = None
       
   621     iteratorExt = False
       
   622     nextMethod = None
       
   623     nextExt = False
       
   624     nextElementMethod = None
       
   625     nextElementExt = False
       
   626 
       
   627     mappingMethod = None
       
   628     if mapping:
       
   629         mappingName, mappingSig = mapping.split(':')
       
   630 
       
   631     sequenceLenMethod = None
       
   632     sequenceGetMethod = None
       
   633     if sequence:
       
   634         sequenceLenName, sequenceLenSig = sequence[0].split(':')
       
   635         sequenceGetName, sequenceGetSig = sequence[1].split(':')
       
   636 
       
   637     for name, methods in allMethods:
       
   638         args, x, cardinality = methodargs(methods, superMethods)
       
   639         sort(methods, key=lambda x: len(x.getParameterTypes()))
       
   640         method = methods[0]
       
   641         modifiers = method.getModifiers()
       
   642         if name == 'iterator' and iteratorMethod is None:
       
   643             if (not method.getParameterTypes() and
       
   644                 iterator.isAssignableFrom(method.getReturnType())):
       
   645                 iteratorMethod = method
       
   646         elif name == 'next' and nextMethod is None:
       
   647             if (not method.getParameterTypes() and
       
   648                 not method.getReturnType().isPrimitive()):
       
   649                 nextMethod = method
       
   650         elif name == 'nextElement' and nextElementMethod is None:
       
   651             if (not method.getParameterTypes() and
       
   652                 not method.getReturnType().isPrimitive()):
       
   653                 nextElementMethod = method
       
   654         elif mapping and name == mappingName and mappingMethod is None:
       
   655             if signature(method) == mappingSig:
       
   656                 mappingMethod = (method, cardinality)
       
   657         elif sequence and name == sequenceLenName and sequenceLenMethod is None:
       
   658             if signature(method) == sequenceLenSig:
       
   659                 sequenceLenMethod = (method, cardinality)
       
   660         elif sequence and name == sequenceGetName and sequenceGetMethod is None:
       
   661             if signature(method) == sequenceGetSig:
       
   662                 sequenceGetMethod = (method, cardinality)
       
   663         elif isExtension and name == 'clone' and Modifier.isNative(modifiers):
       
   664             args, x, cardinality = ', PyObject *arg', ', arg', 1
       
   665 
       
   666         if Modifier.isStatic(modifiers):
       
   667             line(out, indent, 'static PyObject *t_%s_%s(PyTypeObject *type%s);',
       
   668                  names[-1], name, args)
       
   669         else:
       
   670             line(out, indent, 'static PyObject *t_%s_%s(t_%s *self%s);',
       
   671                  names[-1], name, names[-1], args)
       
   672 
       
   673     for name, methods in extMethods:
       
   674         args, x, cardinality = methodargs(methods, superMethods)
       
   675         sort(methods, key=lambda x: len(x.getParameterTypes()))
       
   676         method = methods[0]
       
   677         modifiers = method.getModifiers()
       
   678         if name == 'iterator' and iteratorMethod is None:
       
   679             if (not method.getParameterTypes() and
       
   680                 iterator.isAssignableFrom(method.getReturnType())):
       
   681                 iteratorMethod = method
       
   682                 iteratorExt = True
       
   683         elif name == 'next' and nextMethod is None:
       
   684             if (not method.getParameterTypes() and
       
   685                 not method.getReturnType().isPrimitive()):
       
   686                 nextMethod = method
       
   687                 nextExt = True
       
   688         elif name == 'nextElement' and nextElementMethod is None:
       
   689             if (not method.getParameterTypes() and
       
   690                 not method.getReturnType().isPrimitive()):
       
   691                 nextElementMethod = method
       
   692                 nextElementExt = True
       
   693 
       
   694     if isExtension:
       
   695         count = 0
       
   696         for name, methods in extMethods:
       
   697             for method in methods:
       
   698                 line(out, indent,
       
   699                      'static %s JNICALL t_%s_%s%d(JNIEnv *jenv, jobject jobj%s);',
       
   700                      jniname(method.getReturnType()), names[-1], name, count,
       
   701                      jniargs(method.getParameterTypes()))
       
   702                 count += 1
       
   703         line(out, indent, 'static PyObject *t_%s_get__self(t_%s *self, void *data);', names[-1], names[-1])
       
   704 
       
   705     if instanceFields:
       
   706         for field in instanceFields:
       
   707             fieldName = field.getName()
       
   708             if fieldName not in properties:
       
   709                 line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data);',
       
   710                      names[-1], fieldName, names[-1])
       
   711                 if not Modifier.isFinal(field.getModifiers()):
       
   712                     line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data);',
       
   713                          names[-1], field.getName(), names[-1])
       
   714         line(out)
       
   715 
       
   716     for fieldName, methods in propMethods:
       
   717         getter = False
       
   718         setter = False
       
   719         for method in methods:
       
   720             methodName = method.getName()
       
   721             if not getter and (methodName.startswith('get') or
       
   722                                methodName.startswith('is')):
       
   723                 getter = True
       
   724                 line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data);',
       
   725                      names[-1], fieldName, names[-1])
       
   726             elif not setter and methodName.startswith('set'):
       
   727                 setter = True
       
   728                 line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data);',
       
   729                      names[-1], fieldName, names[-1])
       
   730     if clsParams:
       
   731         line(out, indent, 'static PyObject *t_%s_get__parameters_(t_%s *self, void *data);', names[-1], names[-1])
       
   732 
       
   733     if instanceFields or propMethods or isExtension or clsParams:
       
   734         line(out, indent, 'static PyGetSetDef t_%s__fields_[] = {', names[-1])
       
   735         for field in instanceFields:
       
   736             fieldName = field.getName()
       
   737             if fieldName not in properties:
       
   738                 if Modifier.isFinal(field.getModifiers()):
       
   739                     line(out, indent + 1, 'DECLARE_GET_FIELD(t_%s, %s),',
       
   740                          names[-1], fieldName)
       
   741                 else:
       
   742                     line(out, indent + 1, 'DECLARE_GETSET_FIELD(t_%s, %s),',
       
   743                          names[-1], fieldName)
       
   744         for fieldName, methods in propMethods:
       
   745             getter = False
       
   746             setter = False
       
   747             for method in methods:
       
   748                 methodName = method.getName()
       
   749                 if not getter and (methodName.startswith('get') or
       
   750                                    methodName.startswith('is')):
       
   751                     getter = True
       
   752                 elif not setter and methodName.startswith('set'):
       
   753                     setter = True
       
   754                 if getter and setter:
       
   755                     op = 'GETSET'
       
   756                 elif getter:
       
   757                     op = 'GET'
       
   758                 elif setter:
       
   759                     op = 'SET'
       
   760             line(out, indent + 1, 'DECLARE_%s_FIELD(t_%s, %s),',
       
   761                  op, names[-1], fieldName)
       
   762         if isExtension:
       
   763             line(out, indent + 1, 'DECLARE_GET_FIELD(t_%s, self),', names[-1])
       
   764         if clsParams:
       
   765             line(out, indent + 1, 'DECLARE_GET_FIELD(t_%s, parameters_),',
       
   766                  names[-1])
       
   767             
       
   768         line(out, indent + 1, '{ NULL, NULL, NULL, NULL, NULL }')
       
   769         line(out, indent, '};')
       
   770 
       
   771     line(out)
       
   772     line(out, indent, 'static PyMethodDef t_%s__methods_[] = {', names[-1])
       
   773 
       
   774     line(out, indent + 1,
       
   775          'DECLARE_METHOD(t_%s, cast_, METH_O | METH_CLASS),', names[-1])
       
   776     line(out, indent + 1,
       
   777          'DECLARE_METHOD(t_%s, instance_, METH_O | METH_CLASS),', names[-1])
       
   778 
       
   779     for name, methods in allMethods:
       
   780         modifiers = methods[0].getModifiers()
       
   781         if len(methods) == 1 and not name in superMethods:
       
   782             count = len(methods[0].getParameterTypes())
       
   783             if count == 0:
       
   784                 args = 'METH_NOARGS'
       
   785             elif count == 1:
       
   786                 args = 'METH_O'
       
   787             else:
       
   788                 args = 'METH_VARARGS'
       
   789         elif isExtension and name == 'clone' and Modifier.isNative(modifiers):
       
   790             args = 'METH_O'
       
   791         else:
       
   792             args = 'METH_VARARGS'
       
   793         if Modifier.isStatic(modifiers):
       
   794             args += ' | METH_CLASS'
       
   795 
       
   796         line(out, indent + 1, 'DECLARE_METHOD(t_%s, %s, %s),',
       
   797              names[-1], name, args)
       
   798     line(out, indent + 1, '{ NULL, NULL, 0, NULL }')
       
   799     line(out, indent, '};')
       
   800 
       
   801     if instanceFields or propMethods or isExtension or clsParams:
       
   802         tp_getset = 't_%s__fields_' %(names[-1])
       
   803     else:
       
   804         tp_getset = '0'
       
   805 
       
   806     if iteratorMethod:
       
   807         if iteratorExt:
       
   808             tp_iter = 'get_extension_iterator'
       
   809         else:
       
   810             tp_iter = '((PyObject *(*)(t_%s *)) get_%siterator<t_%s>)' %(names[-1], clsParams and 'generic_' or '', names[-1])
       
   811         tp_iternext = '0'
       
   812     elif nextMethod and iterator.isAssignableFrom(cls):
       
   813         tp_iter = 'PyObject_SelfIter'
       
   814         returnName = typename(nextMethod.getReturnType(), cls, False)
       
   815         ns, sep, n = rpartition(returnName, '::')
       
   816         if nextExt:
       
   817             tp_iternext = 'get_extension_next'
       
   818         else:
       
   819             tp_iternext = '((PyObject *(*)(java::util::t_Iterator *)) get_%siterator_next<java::util::t_Iterator,%s%st_%s>)' %(clsParams and 'generic_' or '', ns, sep, n)
       
   820     elif nextElementMethod and enumeration.isAssignableFrom(cls):
       
   821         tp_iter = 'PyObject_SelfIter'
       
   822         returnName = typename(nextElementMethod.getReturnType(), cls, False)
       
   823         ns, sep, n = rpartition(returnName, '::')
       
   824         if nextElementExt:
       
   825             tp_iternext = 'get_extension_nextElement'
       
   826         else:
       
   827             tp_iternext = '((PyObject *(*)(java::util::t_Enumeration *)) get_%senumeration_next<java::util::t_Enumeration,%s%st_%s>)' %(clsParams and 'generic_' or '', ns, sep, n)
       
   828     elif nextMethod:
       
   829         tp_iter = 'PyObject_SelfIter'
       
   830         returnName = typename(nextMethod.getReturnType(), cls, False)
       
   831         ns, sep, n = rpartition(returnName, '::')
       
   832         if nextExt:
       
   833             tp_iternext = 'get_extension_next'
       
   834         else:
       
   835             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)
       
   836     else:
       
   837         tp_iter = '0'
       
   838         tp_iternext = '0'
       
   839 
       
   840     if mappingMethod:
       
   841         method, cardinality = mappingMethod
       
   842         if cardinality > 1:
       
   843             getName = 't_%s_%s_map_' %(names[-1], method.getName())
       
   844             line(out, indent, 'static PyObject *%s(t_%s *self, PyObject *key);',
       
   845                  getName, names[-1])
       
   846         else:
       
   847             getName = 't_%s_%s' %(names[-1], method.getName())
       
   848         line(out)
       
   849         line(out, indent, 'static PyMappingMethods t_%s_as_mapping = {',
       
   850              names[-1])
       
   851         line(out, indent + 1, '0,')
       
   852         line(out, indent + 1, '(binaryfunc) %s,', getName)
       
   853         line(out, indent + 1, '0,')
       
   854         line(out, indent, '};')
       
   855         tp_as_mapping = '&t_%s_as_mapping' %(names[-1])
       
   856     else:
       
   857         tp_as_mapping = '0'
       
   858 
       
   859     if sequenceLenMethod or sequenceGetMethod:
       
   860         if sequenceLenMethod:
       
   861             method, cardinality = sequenceLenMethod
       
   862             lenName = 't_%s_%s_seq_' %(names[-1], method.getName())
       
   863             line(out, indent, 'static int %s(t_%s *self);', lenName, names[-1])
       
   864         else:
       
   865             lenName = '0'
       
   866 
       
   867         if sequenceGetMethod:
       
   868             method, cardinality = sequenceGetMethod
       
   869             getName = 't_%s_%s_seq_' %(names[-1], method.getName())
       
   870             line(out, indent, 'static PyObject *%s(t_%s *self, int n);',
       
   871                  getName, names[-1])
       
   872         else:
       
   873             getName = '0'
       
   874 
       
   875         line(out)
       
   876         line(out, indent, 'static PySequenceMethods t_%s_as_sequence = {',
       
   877              names[-1])
       
   878         if python_ver < '2.5.0':
       
   879             line(out, indent + 1, '(inquiry) %s,', lenName)
       
   880             line(out, indent + 1, '0,')
       
   881             line(out, indent + 1, '0,')
       
   882             line(out, indent + 1, '(intargfunc) %s', getName)
       
   883             line(out, indent, '};')
       
   884         else:
       
   885             line(out, indent + 1, '(lenfunc) %s,', lenName)
       
   886             line(out, indent + 1, '0,')
       
   887             line(out, indent + 1, '0,')
       
   888             line(out, indent + 1, '(ssizeargfunc) %s', getName)
       
   889             line(out, indent, '};')
       
   890         tp_as_sequence = '&t_%s_as_sequence' %(names[-1])
       
   891     else:
       
   892         tp_as_sequence = '0'
       
   893 
       
   894     if len(superNames) > 1:
       
   895         base = '::'.join(('::'.join(cppnames(superNames[:-1])), superNames[-1]))
       
   896     else:
       
   897         base = superNames[-1]
       
   898     line(out)
       
   899     line(out, indent, 'DECLARE_TYPE(%s, t_%s, %s, %s, %s, %s, %s, %s, %s, %s);',
       
   900          names[-1], names[-1], base, cppname(names[-1]), constructorName,
       
   901          tp_iter, tp_iternext, tp_getset, tp_as_mapping, tp_as_sequence)
       
   902 
       
   903     if clsParams:
       
   904         clsArgs = []
       
   905         for clsParam in clsParams:
       
   906             clsArgs.append("PyTypeObject *%s" %(clsParam.getName()))
       
   907         line(out, indent, 
       
   908              "PyObject *t_%s::wrap_Object(const %s& object, %s)",
       
   909              cppname(names[-1]), names[-1], ', '.join(clsArgs))
       
   910         line(out, indent, "{")
       
   911         line(out, indent + 1, "PyObject *obj = t_%s::wrap_Object(object);",
       
   912              names[-1])
       
   913         line(out, indent + 1, "if (obj != Py_None)")
       
   914         line(out, indent + 1, "{")
       
   915         line(out, indent + 2, "t_%s *self = (t_%s *) obj;",
       
   916              names[-1], names[-1])
       
   917         i = 0;
       
   918         for clsParam in clsParams:
       
   919             line(out, indent + 2, "self->parameters[%d] = %s;",
       
   920                  i, clsParam.getName())
       
   921         line(out, indent + 1, "}")
       
   922         line(out, indent + 1, "return obj;");
       
   923         line(out, indent, "}")
       
   924 
       
   925     line(out)
       
   926     line(out, indent, 'void t_%s::install(PyObject *module)', names[-1])
       
   927     line(out, indent, '{')
       
   928     line(out, indent + 1, 'installType(&%s$$Type, module, "%s", %d);',
       
   929          names[-1], rename or names[-1], isExtension and 1 or 0)
       
   930     for inner in cls.getDeclaredClasses():
       
   931         if inner in typeset:
       
   932             if Modifier.isStatic(inner.getModifiers()):
       
   933                 innerName = inner.getName().split('.')[-1]
       
   934                 line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "%s", make_descriptor(&%s$$Type));',
       
   935                      names[-1], innerName[len(names[-1])+1:], innerName)
       
   936     line(out, indent, '}')
       
   937 
       
   938     line(out)
       
   939     line(out, indent, 'void t_%s::initialize(PyObject *module)', names[-1])
       
   940     line(out, indent, '{')
       
   941     line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "class_", make_descriptor(%s::initializeClass, %s));',
       
   942          names[-1], cppname(names[-1]), generics and 1 or 0)
       
   943     line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "wrapfn_", make_descriptor(t_%s::wrap_jobject));',
       
   944          names[-1], names[-1])
       
   945 
       
   946     if isExtension:
       
   947         line(out, indent + 1, 'jclass cls = %s::initializeClass();',
       
   948              cppname(names[-1]))
       
   949     elif fields:
       
   950         line(out, indent + 1, '%s::initializeClass();', cppname(names[-1]))
       
   951 
       
   952     if isExtension:
       
   953         count = 0
       
   954         line(out, indent + 1, 'JNINativeMethod methods[] = {')
       
   955         for name, methods in extMethods:
       
   956             for method in methods:
       
   957                 line(out, indent + 2, '{ "%s", "%s", (void *) t_%s_%s%d },',
       
   958                      name, signature(method), names[-1], name, count)
       
   959                 count += 1
       
   960         line(out, indent + 1, '};')
       
   961         line(out, indent + 1, 'env->registerNatives(cls, methods, %d);',
       
   962              count)
       
   963 
       
   964     for field in fields:
       
   965         fieldType = field.getType()
       
   966         fieldName = field.getName()
       
   967         value = '%s::%s' %(cppname(names[-1]), cppname(fieldName))
       
   968         value = fieldValue(cls, value, fieldType)
       
   969         line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "%s", make_descriptor(%s));',
       
   970              names[-1], fieldName, value)
       
   971     line(out, indent, '}')
       
   972 
       
   973     line(out)
       
   974     line(out, indent, 'static PyObject *t_%s_cast_(PyTypeObject *type, PyObject *arg)', names[-1])
       
   975     line(out, indent, '{')
       
   976     line(out, indent + 1, 'if (!(arg = castCheck(arg, %s::initializeClass, 1)))', cppname(names[-1]))
       
   977     line(out, indent + 2, 'return NULL;')
       
   978     line(out, indent + 1, 'return t_%s::wrap_Object(%s(((t_%s *) arg)->object.this$));', names[-1], cppname(names[-1]), names[-1])
       
   979     line(out, indent, '}')
       
   980 
       
   981     line(out, indent, 'static PyObject *t_%s_instance_(PyTypeObject *type, PyObject *arg)', names[-1])
       
   982     line(out, indent, '{')
       
   983     line(out, indent + 1, 'if (!castCheck(arg, %s::initializeClass, 0))', cppname(names[-1]))
       
   984     line(out, indent + 2, 'Py_RETURN_FALSE;')
       
   985     line(out, indent + 1, 'Py_RETURN_TRUE;')
       
   986     line(out, indent, '}')
       
   987 
       
   988     if constructors:
       
   989         line(out)
       
   990         line(out, indent, 'static int t_%s_init_(t_%s *self, PyObject *args, PyObject *kwds)', names[-1], names[-1])
       
   991         line(out, indent, '{')
       
   992         if len(constructors) > 1:
       
   993             currLen = -1
       
   994             line(out, indent + 1, 'switch (PyTuple_GET_SIZE(args)) {')
       
   995             withErr = False
       
   996             for constructor in constructors:
       
   997                 params = constructor.getParameterTypes()
       
   998                 if len(params) != currLen:
       
   999                     if currLen >= 0:
       
  1000                         withErr = True
       
  1001                         line(out, indent + 2, 'goto err;')
       
  1002                     currLen = len(params)
       
  1003                     line(out, indent + 1, '%scase %d:', HALF_INDENT, currLen)
       
  1004                 construct(out, indent + 2, cls, True, constructor, names,
       
  1005                           generics)
       
  1006             line(out, indent + 1, '%sdefault:', HALF_INDENT)
       
  1007             if withErr:
       
  1008                 line(out, indent + 1, '%serr:', HALF_INDENT)
       
  1009             line(out, indent + 2, 'PyErr_SetArgsError((PyObject *) self, "__init__", args);')
       
  1010             line(out, indent + 2, 'return -1;')
       
  1011             line(out, indent + 1, '}')
       
  1012         else:
       
  1013             construct(out, indent + 1, cls, False, constructors[0], names,
       
  1014                       generics)
       
  1015             if constructors[0].getParameterTypes():
       
  1016                 line(out, indent + 1, 'else')
       
  1017                 line(out, indent + 1, '{')
       
  1018                 line(out, indent + 2, 'PyErr_SetArgsError((PyObject *) self, "__init__", args);')
       
  1019                 line(out, indent + 2, 'return -1;')
       
  1020                 line(out, indent + 1, '}')
       
  1021 
       
  1022         if isExtension:
       
  1023             line(out)
       
  1024             line(out, indent + 1, 'Py_INCREF((PyObject *) self);')
       
  1025             line(out, indent + 1, 'self->object.pythonExtension((jlong) (Py_intptr_t) (void *) self);')
       
  1026 
       
  1027         line(out)
       
  1028         line(out, indent + 1, 'return 0;')
       
  1029         line(out, indent , '}')
       
  1030 
       
  1031     for name, methods in allMethods:
       
  1032         line(out)
       
  1033         modifiers = methods[0].getModifiers()
       
  1034 
       
  1035         if isExtension and name == 'clone' and Modifier.isNative(modifiers):
       
  1036             declargs, args, cardinality = ', PyObject *arg', ', arg', 1
       
  1037         else:
       
  1038             declargs, args, cardinality = methodargs(methods, superMethods)
       
  1039 
       
  1040         static = Modifier.isStatic(modifiers)
       
  1041         if static:
       
  1042             line(out, indent, 'static PyObject *t_%s_%s(PyTypeObject *type%s)',
       
  1043                  names[-1], name, declargs)
       
  1044         else:
       
  1045             line(out, indent, 'static PyObject *t_%s_%s(t_%s *self%s)',
       
  1046                  names[-1], name, names[-1], declargs)
       
  1047 
       
  1048         line(out, indent, '{')
       
  1049         if len(methods) > 1:
       
  1050             currLen = -1
       
  1051             line(out, indent + 1, 'switch (PyTuple_GET_SIZE(args)) {')
       
  1052             for method in methods:
       
  1053                 params = method.getParameterTypes()
       
  1054                 if len(params) != currLen:
       
  1055                     if currLen >= 0:
       
  1056                         line(out, indent + 2, 'break;')
       
  1057                     currLen = len(params)
       
  1058                     line(out, indent + 1, '%scase %d:', HALF_INDENT, currLen)
       
  1059                 call(out, indent + 2, cls, True, method, names, cardinality,
       
  1060                      isExtension, generics)
       
  1061             line(out, indent + 1, '}')
       
  1062         else:
       
  1063             call(out, indent + 1, cls, False, methods[0], names, cardinality,
       
  1064                  isExtension, generics)
       
  1065 
       
  1066         if args:
       
  1067             line(out)
       
  1068             if name in superMethods:
       
  1069                 if static:
       
  1070                     line(out, indent + 1, 'return callSuper(type, "%s"%s, %d);',
       
  1071                          name, args, cardinality)
       
  1072                 else:
       
  1073                     line(out, indent + 1, 'return callSuper(&%s$$Type, (PyObject *) self, "%s"%s, %d);',
       
  1074                          names[-1], name, args, cardinality)
       
  1075             else:
       
  1076                 line(out, indent + 1, 'PyErr_SetArgsError(%s, "%s"%s);',
       
  1077                      static and 'type' or '(PyObject *) self', name, args)
       
  1078                 line(out, indent + 1, 'return NULL;')
       
  1079 
       
  1080         line(out, indent, '}')
       
  1081 
       
  1082     if isExtension:
       
  1083         count = 0
       
  1084         for name, methods in extMethods:
       
  1085             for method in methods:
       
  1086                 line(out)
       
  1087                 line(out, indent,
       
  1088                      'static %s JNICALL t_%s_%s%d(JNIEnv *jenv, jobject jobj%s)',
       
  1089                      jniname(method.getReturnType()), names[-1], name, count,
       
  1090                      jniargs(method.getParameterTypes()))
       
  1091                 count += 1
       
  1092                 line(out, indent, '{')
       
  1093                 extension(env, out, indent + 1, cls, names, name, count, method,
       
  1094                           generics)
       
  1095                 line(out, indent, '}')
       
  1096         line(out)
       
  1097         line(out, indent, 'static PyObject *t_%s_get__self(t_%s *self, void *data)',
       
  1098              names[-1], names[-1])
       
  1099         line(out, indent, '{')
       
  1100         indent += 1
       
  1101         line(out, indent, 'jlong ptr;')
       
  1102         line(out, indent, 'OBJ_CALL(ptr = self->object.pythonExtension());')
       
  1103         line(out, indent, 'PyObject *obj = (PyObject *) (Py_intptr_t) ptr;')
       
  1104         line(out)
       
  1105         line(out, indent, 'if (obj != NULL)')
       
  1106         line(out, indent, '{')
       
  1107         line(out, indent + 1, 'Py_INCREF(obj);')
       
  1108         line(out, indent + 1, 'return obj;')
       
  1109         line(out, indent, '}')
       
  1110         line(out, indent, 'else')
       
  1111         line(out, indent + 1, 'Py_RETURN_NONE;')
       
  1112         indent -= 1
       
  1113         line(out, indent, '}')
       
  1114 
       
  1115     if clsParams:
       
  1116         line(out, indent, 'static PyObject *t_%s_get__parameters_(t_%s *self, void *data)', names[-1], names[-1])
       
  1117         line(out, indent, '{')
       
  1118         line(out, indent + 1, 'return typeParameters(self->parameters, sizeof(self->parameters));')
       
  1119         line(out, indent, '}')
       
  1120 
       
  1121     if instanceFields:
       
  1122         for field in instanceFields:
       
  1123             fieldName = field.getName()
       
  1124             if fieldName not in properties:
       
  1125                 line(out)
       
  1126                 fieldType = field.getType()
       
  1127                 typeName = typename(fieldType, cls, False)
       
  1128                 line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data)',
       
  1129                      names[-1], fieldName, names[-1])
       
  1130                 line(out, indent, '{')
       
  1131                 line(out, indent + 1, '%s value%s;', typeName,
       
  1132                      not fieldType.isPrimitive() and '((jobject) NULL)' or '')
       
  1133                 line(out, indent + 1, 'OBJ_CALL(value = self->object._get_%s());',
       
  1134                      fieldName)
       
  1135                 line(out, indent + 1, returnValue(cls, fieldType, 'value'))
       
  1136                 line(out, indent, '}')
       
  1137 
       
  1138                 if not Modifier.isFinal(field.getModifiers()):
       
  1139                     line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data)',
       
  1140                          names[-1], fieldName, names[-1])
       
  1141                     line(out, indent, '{')
       
  1142                     line(out, indent + 1, '%s value%s;', typeName,
       
  1143                          not fieldType.isPrimitive() and '((jobject) NULL)' or '')
       
  1144                     sig, check, x = parseArgs([fieldType], cls, False)
       
  1145                     line(out, indent + 1, 'if (!parseArg(arg, "%s"%s, &value))',
       
  1146                          sig, check)
       
  1147                     line(out, indent + 1, '{')
       
  1148                     line(out, indent + 2, 'INT_CALL(self->object._set_%s(value));',
       
  1149                          fieldName)
       
  1150                     line(out, indent + 2, 'return 0;')
       
  1151                     line(out, indent + 1, '}')
       
  1152                     line(out, indent + 1, 'PyErr_SetArgsError((PyObject *) self, "%s", arg);',
       
  1153                          fieldName)
       
  1154                     line(out, indent + 1, 'return -1;')
       
  1155                     line(out, indent, '}')
       
  1156 
       
  1157     if propMethods:
       
  1158         for fieldName, methods in propMethods:
       
  1159             line(out)
       
  1160             getter = None
       
  1161             setters = []
       
  1162             sort(methods, key=lambda x: x.getName())
       
  1163             for method in methods:
       
  1164                 methodName = method.getName()
       
  1165                 if not getter and (methodName.startswith('get') or
       
  1166                                    methodName.startswith('is')):
       
  1167                     getter = method
       
  1168                 elif methodName.startswith('set'):
       
  1169                     setters.append(method)
       
  1170 
       
  1171             if getter:
       
  1172                 methodName = getter.getName()
       
  1173                 returnType = getter.getReturnType()
       
  1174                 typeName = typename(returnType, cls, False)
       
  1175                 line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data)',
       
  1176                      names[-1], fieldName, names[-1])
       
  1177                 line(out, indent, '{')
       
  1178                 line(out, indent + 1, '%s value%s;', typeName,
       
  1179                      not returnType.isPrimitive() and '((jobject) NULL)' or '')
       
  1180                 line(out, indent + 1, 'OBJ_CALL(value = self->object.%s());',
       
  1181                      methodName)
       
  1182                 line(out, indent + 1, returnValue(cls, returnType, 'value'))
       
  1183                 line(out, indent, '}')
       
  1184 
       
  1185             if setters:
       
  1186                 line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data)',
       
  1187                      names[-1], fieldName, names[-1])
       
  1188                 line(out, indent, '{')
       
  1189                 methodName = setters[0].getName()
       
  1190                 for method in setters:
       
  1191                     argType = method.getParameterTypes()[0]
       
  1192                     typeName = typename(argType, cls, False)
       
  1193                     line(out, indent + 1, '{')
       
  1194                     line(out, indent + 2, '%s value%s;', typeName,
       
  1195                          not argType.isPrimitive() and '((jobject) NULL)' or '')
       
  1196                     sig, check, x = parseArgs([argType], cls, False)
       
  1197                     line(out, indent + 2, 'if (!parseArg(arg, "%s"%s, &value))',
       
  1198                          sig, check)
       
  1199                     line(out, indent + 2, '{')
       
  1200                     line(out, indent + 3, 'INT_CALL(self->object.%s(value));',
       
  1201                          methodName)
       
  1202                     line(out, indent + 3, 'return 0;')
       
  1203                     line(out, indent + 2, '}')
       
  1204                     line(out, indent + 1, '}')
       
  1205                 line(out, indent + 1, 'PyErr_SetArgsError((PyObject *) self, "%s", arg);',
       
  1206                      fieldName)
       
  1207                 line(out, indent + 1, 'return -1;')
       
  1208                 line(out, indent, '}')
       
  1209 
       
  1210     if mappingMethod:
       
  1211         method, cardinality = mappingMethod
       
  1212         if cardinality > 1:
       
  1213             methodName = method.getName()
       
  1214             getName = 't_%s_%s_map_' %(names[-1], methodName)
       
  1215             line(out)
       
  1216             line(out, indent, 'static PyObject *%s(t_%s *self, PyObject *arg)',
       
  1217                  getName, names[-1])
       
  1218             line(out, indent, '{')
       
  1219             call(out, indent + 1, cls, False, method, names, 1, isExtension,
       
  1220                  generics)
       
  1221             line(out)
       
  1222             line(out, indent + 1, 'PyErr_SetArgsError((PyObject *) self, "%s", arg);',
       
  1223                  methodName)
       
  1224             line(out, indent + 1, 'return NULL;')
       
  1225             line(out, indent, '}')
       
  1226 
       
  1227     if sequenceLenMethod:
       
  1228         method, cardinality = sequenceLenMethod
       
  1229         methodName = method.getName()
       
  1230         lenName = 't_%s_%s_seq_' %(names[-1], methodName)
       
  1231         line(out)
       
  1232         line(out, indent, 'static int %s(t_%s *self)', lenName, names[-1])
       
  1233         line(out, indent, '{')
       
  1234         line(out, indent + 1, '%s len;',
       
  1235              typename(method.getReturnType(), cls, False))
       
  1236         line(out, indent + 1, 'INT_CALL(len = self->object.%s());', methodName)
       
  1237         line(out, indent + 1, 'return (int) len;')
       
  1238         line(out, indent, '}')
       
  1239 
       
  1240     if sequenceGetMethod:
       
  1241         method, cardinality = sequenceGetMethod
       
  1242         methodName = method.getName()
       
  1243         returnType = method.getReturnType()
       
  1244         getName = 't_%s_%s_seq_' %(names[-1], methodName)
       
  1245         line(out)
       
  1246         line(out, indent, 'static PyObject *%s(t_%s *self, int n)', getName, names[-1])
       
  1247         line(out, indent, '{')
       
  1248         line(out, indent + 1, '%s result%s;',
       
  1249              typename(returnType, cls, False),
       
  1250              not returnType.isPrimitive() and '((jobject) NULL)' or '')
       
  1251         line(out, indent + 1, 'OBJ_CALL(result = self->object.%s((%s) n));',
       
  1252              methodName, typename(method.getParameterTypes()[0], cls, False))
       
  1253         line(out, indent + 1, returnValue(cls, returnType, 'result'))
       
  1254         line(out, indent, '}')
       
  1255 
       
  1256     while indent:
       
  1257         indent -= 1
       
  1258         line(out, indent, '}')
       
  1259 
       
  1260 
       
  1261 def package(out, allInOne, cppdir, namespace, names):
       
  1262 
       
  1263     if not allInOne:
       
  1264         out = file(os.path.join(os.path.join(cppdir, *names),
       
  1265                                 '__init__.cpp'), 'w')
       
  1266 
       
  1267     if allInOne and not names or not allInOne:
       
  1268         line(out, 0, '#include <jni.h>')
       
  1269         line(out, 0, '#include <Python.h>')
       
  1270         line(out, 0, '#include "JCCEnv.h"')
       
  1271         line(out, 0, '#include "functions.h"')
       
  1272 
       
  1273     if not names:
       
  1274         line(out)
       
  1275         line(out, 0, 'PyObject *initVM(PyObject *module, PyObject *args, PyObject *kwds);')
       
  1276 
       
  1277     packages = []
       
  1278     types = []
       
  1279 
       
  1280     namespaces = namespace.items()
       
  1281     sort(namespaces, key=lambda x: x[0])
       
  1282     for name, entries in namespaces:
       
  1283         if entries is True:
       
  1284             if names:
       
  1285                 line(out, 0, '#include "%s/%s.h"', '/'.join(names), name)
       
  1286             else:
       
  1287                 line(out, 0, '#include "%s.h"', name)
       
  1288             types.append(name)
       
  1289         else:
       
  1290             packages.append((name, entries))
       
  1291 
       
  1292     indent = 0
       
  1293     if names:
       
  1294         line(out)
       
  1295         for name in names:
       
  1296             line(out, indent, 'namespace %s {', cppname(name))
       
  1297             indent += 1
       
  1298 
       
  1299     line(out);
       
  1300     for name, entries in packages:
       
  1301         line(out, indent, 'namespace %s {', cppname(name))
       
  1302         line(out, indent + 1, 'void __install__(PyObject *module);')
       
  1303         line(out, indent + 1, 'void __initialize__(PyObject *module);')
       
  1304         line(out, indent, '}')
       
  1305 
       
  1306     line(out)
       
  1307     line(out, indent, 'void __install__(PyObject *module)')
       
  1308     line(out, indent, '{')
       
  1309     for name in types:
       
  1310         line(out, indent + 1, 't_%s::install(module);', name)
       
  1311     for name, entries in packages:
       
  1312         line(out, indent + 1, '%s::__install__(module);', cppname(name))
       
  1313     line(out, indent, '}')
       
  1314 
       
  1315     line(out)
       
  1316     if not names:
       
  1317         line(out, indent, 'PyObject *__initialize__(PyObject *module, PyObject *args, PyObject *kwds)')
       
  1318         line(out, indent, '{')
       
  1319         line(out, indent + 1, 'PyObject *env = initVM(module, args, kwds);')
       
  1320         line(out)
       
  1321         line(out, indent + 1, 'if (env == NULL)')
       
  1322         line(out, indent + 2, 'return NULL;')
       
  1323         line(out)
       
  1324         line(out, indent + 1, 'try {');
       
  1325         indent += 1
       
  1326     else:
       
  1327         line(out, indent, 'void __initialize__(PyObject *module)')
       
  1328         line(out, indent, '{')
       
  1329     for name in types:
       
  1330         line(out, indent + 1, 't_%s::initialize(module);', name)
       
  1331     for name, entries in packages:
       
  1332         line(out, indent + 1, '%s::__initialize__(module);', cppname(name))
       
  1333     if not names:
       
  1334         line(out, indent + 1, 'return env;')
       
  1335         indent -= 1
       
  1336         line(out, indent + 1, '} catch (JCCEnv::exception e) {')
       
  1337         line(out, indent + 2, 'PyErr_SetJavaError(e.throwable);')
       
  1338         line(out, indent + 2, 'return NULL;')
       
  1339         line(out, indent + 1, '}')
       
  1340 
       
  1341     line(out, indent, '}')
       
  1342 
       
  1343     while indent:
       
  1344         indent -= 1
       
  1345         line(out, indent, '}')
       
  1346 
       
  1347     if not allInOne:
       
  1348         out.close()
       
  1349     else:
       
  1350         line(out)
       
  1351 
       
  1352     for name, entries in packages:
       
  1353         package(out, allInOne, cppdir, entries, names + (name,))
       
  1354 
       
  1355 
       
  1356 def module(out, allInOne, classes, cppdir, moduleName, shared, generics):
       
  1357 
       
  1358     extname = '_%s' %(moduleName)
       
  1359     line(out, 0, '#include <Python.h>')
       
  1360     line(out, 0, '#include "macros.h"')
       
  1361     line(out, 0, '#include "jccfuncs.h"')
       
  1362 
       
  1363     if allInOne:
       
  1364         out_init = file(os.path.join(cppdir, '__init__.cpp'), 'w')
       
  1365     namespaces = {}
       
  1366     for cls in classes:
       
  1367         namespace = namespaces
       
  1368         classNames = cls.getName().split('.')
       
  1369         for className in classNames[:-1]:
       
  1370             namespace = namespace.setdefault(className, {})
       
  1371         namespace[classNames[-1]] = True
       
  1372     if allInOne:
       
  1373         package(out_init, True, cppdir, namespaces, ())
       
  1374         out_init.close()
       
  1375     else:
       
  1376         package(None, False, cppdir, namespaces, ())
       
  1377 
       
  1378     line(out)
       
  1379     line(out, 0, 'PyObject *initJCC(PyObject *module);')
       
  1380     line(out, 0, 'void __install__(PyObject *module);')
       
  1381     line(out, 0, 'extern PyTypeObject JObject$$Type, ConstVariableDescriptor$$Type, FinalizerClass$$Type, FinalizerProxy$$Type;')
       
  1382     line(out, 0, 'extern void _install_jarray(PyObject *);')
       
  1383     line(out)
       
  1384     line(out, 0, 'extern "C" {')
       
  1385 
       
  1386     line(out)
       
  1387     line(out, 1, 'void init%s(void)', extname)
       
  1388     line(out, 1, '{')
       
  1389     line(out, 2, 'PyObject *module = Py_InitModule3("%s", jcc_funcs, "");',
       
  1390          extname);
       
  1391     line(out)
       
  1392     line(out, 2, 'initJCC(module);')
       
  1393     line(out)
       
  1394     line(out, 2, 'INSTALL_TYPE(JObject, module);')
       
  1395     line(out, 2, 'INSTALL_TYPE(ConstVariableDescriptor, module);')
       
  1396     line(out, 2, 'INSTALL_TYPE(FinalizerClass, module);')
       
  1397     line(out, 2, 'INSTALL_TYPE(FinalizerProxy, module);')
       
  1398     line(out, 2, '_install_jarray(module);')
       
  1399     line(out, 2, '__install__(module);')
       
  1400     line(out, 1, '}')
       
  1401     line(out, 0, '}')
       
  1402 
       
  1403 
       
  1404 def compile(env, jccPath, output, moduleName, install, dist, debug, jars,
       
  1405             version, prefix, root, install_dir, home_dir, use_distutils,
       
  1406             shared, compiler, modules, wininst, arch, generics):
       
  1407 
       
  1408     try:
       
  1409         if use_distutils:
       
  1410             raise ImportError
       
  1411         from setuptools import setup, Extension
       
  1412         with_setuptools = True
       
  1413         if shared and not SHARED:
       
  1414             raise NotImplementedError, "JCC was not built with --shared mode support, see JCC's INSTALL file for more information"
       
  1415     except ImportError:
       
  1416         if python_ver < '2.4':
       
  1417             raise ImportError, 'setuptools is required when using Python 2.3'
       
  1418         if shared:
       
  1419             raise ImportError, 'setuptools is required when using --shared'
       
  1420         from distutils.core import setup, Extension
       
  1421         with_setuptools = False
       
  1422 
       
  1423     extname = '_%s' %(moduleName)
       
  1424 
       
  1425     modulePath = os.path.join(output, moduleName)
       
  1426     if not os.path.isdir(modulePath):
       
  1427         os.makedirs(modulePath)
       
  1428 
       
  1429     out = file(os.path.join(modulePath, '__init__.py'), 'w')
       
  1430     line(out)
       
  1431     if shared:
       
  1432         line(out, 0, "import os, sys")
       
  1433         line(out)
       
  1434         line(out, 0, "if sys.platform == 'win32':")
       
  1435         line(out, 1, "import jcc, %s", extname)
       
  1436         line(out, 0, "else:")
       
  1437         line(out, 1, "import %s", extname)
       
  1438     else:
       
  1439         line(out, 0, 'import os, %s', extname)
       
  1440     line(out)
       
  1441     line(out, 0, '__dir__ = os.path.abspath(os.path.dirname(__file__))')
       
  1442 
       
  1443     package_data = []
       
  1444     for jar in jars:
       
  1445         shutil.copy2(jar, modulePath)
       
  1446         package_data.append(os.path.basename(jar))
       
  1447 
       
  1448     packages = [moduleName]
       
  1449     if modules:
       
  1450         for module in modules:
       
  1451             if os.path.isdir(module):
       
  1452                 def copytree(src, dst, is_package):
       
  1453                     if is_package:
       
  1454                         packages.append('.'.join((moduleName, src.replace(os.path.sep, '.'))))
       
  1455                     if not os.path.exists(dst):
       
  1456                         os.mkdir(dst)
       
  1457                     for name in os.listdir(src):
       
  1458                         if name.startswith('.'):
       
  1459                             continue
       
  1460                         _src = os.path.join(src, name)
       
  1461                         if os.path.islink(_src):
       
  1462                             continue
       
  1463                         _dst = os.path.join(dst, name)
       
  1464                         if os.path.isdir(_src):
       
  1465                             copytree(_src, _dst, os.path.exists(os.path.join(_src, '__init__.py')))
       
  1466                         elif not is_package or name.endswith('.py'):
       
  1467                             shutil.copy2(_src, _dst)
       
  1468                 dst = modulePath
       
  1469                 if os.path.exists(os.path.join(module, '__init__.py')):
       
  1470                     dst = os.path.join(modulePath, os.path.basename(module))
       
  1471                     copytree(module, dst, True)
       
  1472                 else:
       
  1473                     copytree(module, dst, False)
       
  1474             else:
       
  1475                 shutil.copy2(module.split('.')[0] + '.py', modulePath)
       
  1476 
       
  1477     line(out)
       
  1478     line(out, 0, 'class JavaError(Exception):')
       
  1479     line(out, 1, 'def getJavaException(self):')
       
  1480     line(out, 2, 'return self.args[0]')
       
  1481     line(out, 1, 'def __str__(self):')
       
  1482     line(out, 2, 'writer = %s.StringWriter()', extname)
       
  1483     line(out, 2, 'self.getJavaException().printStackTrace(%s.PrintWriter(writer))', extname)
       
  1484     line(out, 2, 'return "\\n".join((super(JavaError, self).__str__(), "    Java stacktrace:", str(writer)))')
       
  1485     line(out)
       
  1486     line(out, 0, 'class InvalidArgsError(Exception):')
       
  1487     line(out, 1, 'pass')
       
  1488     line(out)
       
  1489     line(out, 0, '%s._set_exception_types(JavaError, InvalidArgsError)',
       
  1490          extname)
       
  1491 
       
  1492     if version:
       
  1493         line(out)
       
  1494         line(out, 0, 'VERSION = "%s"', version)
       
  1495         
       
  1496     line(out, 0, 'CLASSPATH = [%s]' %(', '.join(['os.path.join(__dir__, "%s")' %(os.path.basename(jar)) for jar in jars])))
       
  1497     line(out, 0, 'CLASSPATH = os.pathsep.join(CLASSPATH)')
       
  1498     line(out, 0, '%s.CLASSPATH = CLASSPATH', extname)
       
  1499     line(out, 0, '%s._set_function_self(%s.initVM, %s)',
       
  1500          extname, extname, extname)
       
  1501 
       
  1502     line(out)
       
  1503     line(out, 0, 'from %s import *', extname)
       
  1504     out.close()
       
  1505 
       
  1506     includes = [os.path.join(output, extname),
       
  1507                 os.path.join(jccPath, 'sources')]
       
  1508 
       
  1509     sources = ['JObject.cpp', 'JArray.cpp', 'functions.cpp', 'types.cpp']
       
  1510     if not shared:
       
  1511         sources.append('jcc.cpp')
       
  1512         sources.append('JCCEnv.cpp')
       
  1513     for source in sources:
       
  1514 	shutil.copy2(os.path.join(jccPath, 'sources', source),
       
  1515                      os.path.join(output, extname))
       
  1516 
       
  1517     sources = []
       
  1518     for path, dirs, names in os.walk(os.path.join(output, extname)):
       
  1519         for name in names:
       
  1520             if name.endswith('.cpp'):
       
  1521                 sources.append(os.path.join(path, name))
       
  1522 
       
  1523     script_args = ['build_ext']
       
  1524 
       
  1525     includes[0:0] = INCLUDES
       
  1526     compile_args = CFLAGS
       
  1527     link_args = LFLAGS
       
  1528     defines=['PYTHON']
       
  1529 
       
  1530     if compiler:
       
  1531         script_args.append('--compiler=%s' %(compiler))
       
  1532 
       
  1533     if shared:
       
  1534         defines.append('_jcc_shared')
       
  1535     script_args.append('--define=%s' %(','.join(defines)))
       
  1536 
       
  1537     if debug:
       
  1538         script_args.append('--debug')
       
  1539         compile_args += DEBUG_CFLAGS
       
  1540     elif sys.platform == 'win32':
       
  1541         pass
       
  1542     elif sys.platform == 'sunos5':
       
  1543         link_args.append('-Wl,-s')
       
  1544     else:
       
  1545         link_args.append('-Wl,-S')
       
  1546 
       
  1547     if install:
       
  1548         script_args.append('install')
       
  1549     if prefix:
       
  1550         script_args.append('--prefix=%s' % prefix)
       
  1551     if root:
       
  1552         script_args.append('--root=%s' % root)
       
  1553     if install_dir:
       
  1554         script_args.append('--install-lib=%s' % install_dir)
       
  1555     if home_dir:
       
  1556         script_args.append('--home=%s' % home_dir)
       
  1557 
       
  1558     if dist:
       
  1559         if wininst:
       
  1560             script_args.append('bdist_wininst')
       
  1561         elif with_setuptools:
       
  1562             script_args.append('bdist_egg')
       
  1563         else:
       
  1564             script_args.append('bdist')
       
  1565 
       
  1566     args = {
       
  1567         'extra_compile_args': compile_args,
       
  1568         'extra_link_args': link_args,
       
  1569         'include_dirs': includes,
       
  1570         'sources': sources
       
  1571     }
       
  1572 
       
  1573     if generics:
       
  1574         args['define_macros'] = [('_java_generics', None)]
       
  1575 
       
  1576     if shared:
       
  1577         shlibdir = os.path.dirname(os.path.dirname(_jcc.__file__))
       
  1578         if sys.platform == 'darwin':   # distutils no good with -R
       
  1579             machine = platform.machine()
       
  1580             if machine.startswith('iPod') or machine.startswith('iPhone'):
       
  1581                 args['extra_link_args'] += ['-L' + shlibdir]
       
  1582             else:
       
  1583                 args['extra_link_args'] += ['-Wl,-rpath', shlibdir]
       
  1584             args['library_dirs'] = [shlibdir]
       
  1585             args['libraries'] = ['jcc']
       
  1586         elif sys.platform == 'linux2': # distutils no good with -R
       
  1587             args['extra_link_args'] += ['-Wl,-rpath', shlibdir]
       
  1588             args['library_dirs'] = [shlibdir]
       
  1589             args['libraries'] = ['jcc']
       
  1590         elif sys.platform == 'win32':
       
  1591             jcclib = 'jcc%s.lib' %(debug and '_d' or '')
       
  1592             args['extra_link_args'] += [os.path.join(shlibdir, 'jcc', jcclib)]
       
  1593         else:
       
  1594             raise NotImplementedError, "shared mode on %s" %(sys.platform)
       
  1595 
       
  1596     if arch and sys.platform == 'darwin':
       
  1597         from distutils import sysconfig
       
  1598 
       
  1599         config_vars = sysconfig.get_config_vars()
       
  1600         cflags = config_vars['CFLAGS'].split(' ')
       
  1601         count = len(cflags)
       
  1602         i = 0
       
  1603         while i < count - 1:
       
  1604             if cflags[i] == '-arch' and cflags[i + 1] not in arch:
       
  1605                 del cflags[i:i+2]
       
  1606                 count -= 2
       
  1607             else:
       
  1608                 i += 1
       
  1609         config_vars['CFLAGS'] = ' '.join(cflags)
       
  1610 
       
  1611     extensions = [Extension('.'.join([moduleName, extname]), **args)]
       
  1612 
       
  1613     args = {
       
  1614         'name': moduleName,
       
  1615         'packages': packages,
       
  1616         'package_dir': {moduleName: modulePath},
       
  1617         'package_data': {moduleName: package_data},
       
  1618         'version': version,
       
  1619         'ext_modules': extensions,
       
  1620         'script_args': script_args
       
  1621     }
       
  1622     if with_setuptools:
       
  1623         args['zip_safe'] = False
       
  1624 
       
  1625     setup(**args)