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