1/*
2 * Support for libffi (http://sources.redhat.com/libffi)
3 *
4 * libffi is a library that makes it possible to dynamicly create calls
5 * to C functions (without knowing the signature at compile-time). It also
6 * provides a way to create closures, that is dynamicly create functions with
7 * a runtime specified interface.
8 *
9 * This file contains functions to dynamicly call objc_msgSendSuper and to
10 * dynamicly create IMPs for use in Objective-C method dispatch tables. The
11 * file 'register.m' contains compile-time generated equivalents of these.
12 *
13 * FIXME: There's way to much duplicated code in here, please refactor me.
14 */
15#include "pyobjc.h"
16
17#import <Foundation/NSHost.h>
18#import <CoreFoundation/CoreFoundation.h>
19
20#ifdef __ppc64__
21extern bool ffi64_stret_needs_ptr(const ffi_type* inType,
22		        unsigned short*, unsigned short*);
23#endif;
24
25/*
26 * Define SMALL_STRUCT_LIMIT as the largest struct that will be returned
27 * in registers instead of with a hidden pointer argument.
28 */
29
30static const char gCharEncoding[] = { _C_CHR, 0 };
31static const char gCFRangeEncoding[1024] = { 0 };
32
33#if defined(__ppc__)
34
35#   define SMALL_STRUCT_LIMIT	4
36
37#elif defined(__ppc64__)
38
39#   define SMALL_STRUCT_LIMIT	8
40
41#elif defined(__i386__)
42
43#   define SMALL_STRUCT_LIMIT 	8
44
45#elif defined(__x86_64__)
46
47#   define SMALL_STRUCT_LIMIT	16
48
49#else
50
51#   error "Unsupported MACOSX platform"
52
53#endif
54
55
56#ifndef FFI_CLOSURES
57#    error "Need FFI_CLOSURES!"
58#endif
59
60#if 0 /* Usefull during debugging, only used in the debugger */
61static void describe_ffitype(ffi_type* type)
62{
63	switch (type->type) {
64	case FFI_TYPE_VOID: printf("%s", "void"); break;
65	case FFI_TYPE_INT: printf("%s", "int"); break;
66	case FFI_TYPE_FLOAT: printf("%s", "float"); break;
67	case FFI_TYPE_DOUBLE: printf("%s", "double"); break;
68	case FFI_TYPE_UINT8: printf("%s", "uint8"); break;
69	case FFI_TYPE_SINT8: printf("%s", "sint8"); break;
70	case FFI_TYPE_UINT16: printf("%s", "uint16"); break;
71	case FFI_TYPE_SINT16: printf("%s", "sint16"); break;
72	case FFI_TYPE_UINT32: printf("%s", "uint32"); break;
73	case FFI_TYPE_SINT32: printf("%s", "sint32"); break;
74	case FFI_TYPE_UINT64: printf("%s", "uint64"); break;
75	case FFI_TYPE_SINT64: printf("%s", "sint64"); break;
76	case FFI_TYPE_POINTER: printf("%s", "*"); break;
77	case FFI_TYPE_STRUCT: {
78			ffi_type** elems = type->elements;
79
80			printf("%s", "struct { ");
81			if (elems) {
82				while (*elems) {
83					describe_ffitype(*(elems++));
84					printf("%s", "; ");
85				}
86			}
87			printf("%s", "}");
88		}
89	       break;
90
91	default:
92	       // Don't abort, this is called from the debugger
93	       printf("?(%d)", type->type);
94	}
95}
96
97static void describe_cif(ffi_cif* cif)
98{
99	size_t i;
100
101	printf("<ffi_cif abi=%d nargs=%d  bytes=%d flags=%#x args=[",
102		cif->abi, cif->nargs, cif->bytes, cif->flags);
103	for  (i = 0; i < cif->nargs; i++) {
104		describe_ffitype(cif->arg_types[i]);
105		printf("%s", ", ");
106	}
107	printf("%s", "] rettype=");
108	describe_ffitype(cif->rtype);
109	printf("%s", ">\n");
110}
111
112#endif
113
114
115
116static inline Py_ssize_t align(Py_ssize_t offset, Py_ssize_t alignment)
117{
118	Py_ssize_t rest = offset % alignment;
119	if (rest == 0) return offset;
120	return offset + (alignment - rest);
121}
122
123static Py_ssize_t
124num_struct_fields(const char* argtype)
125{
126	Py_ssize_t res = 0;
127
128	if (*argtype != _C_STRUCT_B) return -1;
129	while (*argtype != _C_STRUCT_E && *argtype != '=') argtype++;
130	if (*argtype == _C_STRUCT_E) return 0;
131
132	argtype++;
133	while (*argtype != _C_STRUCT_E) {
134		if (*argtype == '"') {
135			/* Skip field name */
136			argtype++;
137			while (*argtype++ != '"') {}
138		}
139
140		argtype = PyObjCRT_SkipTypeSpec(argtype);
141		if (argtype == NULL) return -1;
142		res ++;
143	}
144	return res;
145}
146
147
148static void
149free_type(void *obj)
150{
151	PyMem_Free(((ffi_type*)obj)->elements);
152	PyMem_Free(obj);
153}
154
155static ffi_type* signature_to_ffi_type(const char* argtype);
156
157static ffi_type*
158array_to_ffi_type(const char* argtype)
159{
160static  PyObject* array_types = NULL; /* XXX: Use NSMap  */
161	PyObject* v;
162	ffi_type* type;
163	Py_ssize_t field_count;
164	Py_ssize_t i;
165	const char* key = argtype;
166
167	if (array_types == NULL) {
168		array_types = PyDict_New();
169		if (array_types == NULL) return NULL;
170	}
171
172	v = PyDict_GetItemString(array_types, (char*)argtype);
173	if (v != NULL) {
174		return (ffi_type*)PyCObject_AsVoidPtr(v);
175	}
176
177	/* We don't have a type description yet, dynamicly
178	 * create it.
179	 */
180	field_count = atoi(argtype+1);
181
182	type = PyMem_Malloc(sizeof(*type));
183	if (type == NULL) {
184		PyErr_NoMemory();
185		return NULL;
186	}
187	type->size = PyObjCRT_SizeOfType(argtype);
188	type->alignment = PyObjCRT_AlignOfType(argtype);
189
190	/* Libffi doesn't really know about arrays as part of larger
191	 * data-structures (e.g. struct foo { int field[3]; };). We fake it
192	 * by treating the nested array as a struct. These seems to work
193	 * fine on MacOS X.
194	 */
195	type->type = FFI_TYPE_STRUCT;
196	type->elements = PyMem_Malloc((1+field_count) * sizeof(ffi_type*));
197	if (type->elements == NULL) {
198		PyMem_Free(type);
199		PyErr_NoMemory();
200		return NULL;
201	}
202
203	while (isdigit(*++argtype));
204	type->elements[0] = signature_to_ffi_type(argtype);
205	for (i = 1; i < field_count; i++) {
206		type->elements[i] = type->elements[0];
207	}
208	type->elements[field_count] = 0;
209
210	v = PyCObject_FromVoidPtr(type, free_type);
211	if (v == NULL) {
212		free_type(type);
213		return NULL;
214	}
215
216	PyDict_SetItemString(array_types, (char*)key, v);
217	if (PyErr_Occurred()) {
218		Py_DECREF(v);
219		return NULL;
220	}
221	Py_DECREF(v);
222	return type;
223}
224
225static ffi_type*
226struct_to_ffi_type(const char* argtype)
227{
228	static  PyObject* struct_types = NULL; /* XXX: Use NSMap  */
229	PyObject* v;
230	ffi_type* type;
231	Py_ssize_t field_count;
232	const char* curtype;
233
234	if (struct_types == NULL) {
235		struct_types = PyDict_New();
236		if (struct_types == NULL) return NULL;
237	}
238
239	v = PyDict_GetItemString(struct_types, (char*)argtype);
240	if (v != NULL) {
241		return (ffi_type*)PyCObject_AsVoidPtr(v);
242	}
243
244	/* We don't have a type description yet, dynamicly
245	 * create it.
246	 */
247	field_count = num_struct_fields(argtype);
248	if (field_count == -1) {
249		PyErr_Format(PyObjCExc_InternalError,
250			"Cannot determine layout of %s", argtype);
251		return NULL;
252	}
253
254	type = PyMem_Malloc(sizeof(*type));
255	if (type == NULL) {
256		PyErr_NoMemory();
257		return NULL;
258	}
259	type->size = PyObjCRT_SizeOfType(argtype);
260	type->alignment = PyObjCRT_AlignOfType(argtype);
261	type->type = FFI_TYPE_STRUCT;
262	type->elements = PyMem_Malloc((1+field_count) * sizeof(ffi_type*));
263	if (type->elements == NULL) {
264		PyMem_Free(type);
265		PyErr_NoMemory();
266		return NULL;
267	}
268
269	field_count = 0;
270	curtype = argtype+1;
271	while (*curtype != _C_STRUCT_E && *curtype != '=') curtype++;
272	if (*curtype == '=') {
273		curtype ++;
274		while (*curtype != _C_STRUCT_E) {
275			if (*curtype == '"') {
276				/* Skip field name */
277				curtype++;
278				while (*curtype++ != '"') {}
279			}
280			type->elements[field_count] =
281				signature_to_ffi_type(curtype);
282			if (type->elements[field_count] == NULL) {
283				PyMem_Free(type->elements);
284				return NULL;
285			}
286			field_count++;
287			curtype = PyObjCRT_SkipTypeSpec(curtype);
288			if (curtype == NULL) {
289				PyMem_Free(type->elements);
290				return NULL;
291			}
292		}
293	}
294	type->elements[field_count] = NULL;
295
296	v = PyCObject_FromVoidPtr(type, free_type);
297	if (v == NULL) {
298		free_type(type);
299		return NULL;
300	}
301
302	PyDict_SetItemString(struct_types, (char*)argtype, v);
303	if (PyErr_Occurred()) {
304		Py_DECREF(v);
305		return NULL;
306	}
307	Py_DECREF(v);
308	return type;
309}
310
311ffi_type*
312signature_to_ffi_return_type(const char* argtype)
313{
314#ifdef __ppc__
315static const char long_type[] = { _C_LNG, 0 };
316static const char ulong_type[] = { _C_ULNG, 0 };
317
318	switch (*argtype) {
319	case _C_CHR: case _C_SHT: case _C_UNICHAR:
320		return signature_to_ffi_type(long_type);
321	case _C_UCHR: case _C_USHT: //case _C_UNICHAR:
322		return signature_to_ffi_type(ulong_type);
323#ifdef _C_BOOL
324	case _C_BOOL: return signature_to_ffi_type(long_type);
325#endif
326	case _C_NSBOOL:
327		      return signature_to_ffi_type(long_type);
328	default:
329		return signature_to_ffi_type(argtype);
330	}
331#else
332	return signature_to_ffi_type(argtype);
333#endif
334}
335
336
337static ffi_type*
338signature_to_ffi_type(const char* argtype)
339{
340	argtype = PyObjCRT_SkipTypeQualifiers(argtype);
341	switch (*argtype) {
342	case _C_VOID: return &ffi_type_void;
343	case _C_ID: return &ffi_type_pointer;
344	case _C_CLASS: return &ffi_type_pointer;
345	case _C_SEL: return &ffi_type_pointer;
346	case _C_CHR: return &ffi_type_schar;
347	case _C_CHAR_AS_INT: return &ffi_type_schar;
348	case _C_CHAR_AS_TEXT: return &ffi_type_schar;
349#ifdef _C_BOOL
350	case _C_BOOL:
351	     /* sizeof(bool) == 4 on PPC32, and 1 on all others */
352#if defined(__ppc__) && !defined(__LP__)
353	     return &ffi_type_sint;
354#else
355	     return &ffi_type_schar;
356#endif
357
358#endif
359	case _C_NSBOOL: return &ffi_type_schar;
360	case _C_UCHR: return &ffi_type_uchar;
361	case _C_SHT: return &ffi_type_sshort;
362	case _C_UNICHAR: return &ffi_type_sshort;
363	case _C_USHT: return &ffi_type_ushort;
364	case _C_INT: return &ffi_type_sint;
365	case _C_UINT: return &ffi_type_uint;
366
367	 /* The next to defintions are incorrect, but the correct definitions
368	  * don't work (e.g. give testsuite failures).
369	  */
370#ifdef __LP64__
371	case _C_LNG: return &ffi_type_sint64;  /* ffi_type_slong */
372	case _C_ULNG: return &ffi_type_uint64;  /* ffi_type_ulong */
373#else
374	case _C_LNG: return &ffi_type_sint;  /* ffi_type_slong */
375	case _C_ULNG: return &ffi_type_uint;  /* ffi_type_ulong */
376#endif
377	case _C_LNG_LNG: return &ffi_type_sint64;
378	case _C_ULNG_LNG: return &ffi_type_uint64;
379	case _C_FLT: return &ffi_type_float;
380	case _C_DBL: return &ffi_type_double;
381	case _C_CHARPTR: return &ffi_type_pointer;
382	case _C_PTR: return &ffi_type_pointer;
383	case _C_ARY_B:
384		return array_to_ffi_type(argtype);
385	case _C_IN: case _C_OUT: case _C_INOUT: case _C_CONST:
386#if 0	/* 'O' is used by remote objects ??? */
387	  case 'O':
388#endif
389		return signature_to_ffi_type(argtype+1);
390	case _C_STRUCT_B:
391		return struct_to_ffi_type(argtype);
392	case _C_UNDEF:
393		return &ffi_type_pointer;
394	default:
395		PyErr_Format(PyExc_NotImplementedError,
396			"Type '%#x' (%c) not supported", *argtype, *argtype);
397		return NULL;
398	}
399}
400
401/*
402 * arg_signature_to_ffi_type: Make the ffi_type for the call to the method IMP.
403 */
404
405#ifdef __ppc__
406#define arg_signature_to_ffi_type signature_to_ffi_type
407
408#else
409static inline ffi_type*
410arg_signature_to_ffi_type(const char* argtype)
411{
412	/* NOTE: This is the minimal change to pass the unittests, it is not
413	 * based on analysis of the calling conventions.
414	 */
415	switch (*argtype) {
416	case _C_CHR: return &ffi_type_sint;
417	case _C_UCHR: return &ffi_type_uint;
418	case _C_SHT: return &ffi_type_sint;
419	case _C_USHT: return &ffi_type_uint;
420	default: return signature_to_ffi_type(argtype);
421	}
422}
423#endif
424
425static Py_ssize_t extract_count(const char* type, void* pvalue)
426{
427	type = PyObjCRT_SkipTypeQualifiers(type);
428	switch (*type) {
429	case _C_ID:
430		{
431			NSArray* value = *(id*)pvalue;
432			if (!value) {
433				return 0;
434			} else if ([value respondsToSelector:@selector(count)]) {
435				return [value count];
436			} else {
437				/* Fall through to error case */
438			}
439		}
440		break;
441	case _C_CHR: return *(char*)pvalue;
442	case _C_CHAR_AS_INT: return *(char*)pvalue;
443	case _C_UCHR: return *(unsigned char*)pvalue;
444	case _C_SHT: return *(short*)pvalue;
445	case _C_USHT: return *(unsigned short*)pvalue;
446	case _C_INT: return *(int*)pvalue;
447	case _C_UINT: return *(unsigned int*)pvalue;
448	case _C_LNG: return *(long*)pvalue;
449	case _C_ULNG: return *(unsigned long*)pvalue;
450	case _C_LNG_LNG: return *(long long*)pvalue;
451	case _C_ULNG_LNG: return *(unsigned long long*)pvalue;
452	case _C_PTR:
453		switch(type[1]) {
454		case _C_CHR: return **(char**)pvalue;
455		case _C_CHAR_AS_INT: return **(char**)pvalue;
456		case _C_UCHR: return **(unsigned char**)pvalue;
457		case _C_SHT: return **(short**)pvalue;
458		case _C_USHT: return **(unsigned short**)pvalue;
459		case _C_INT: return **(int**)pvalue;
460		case _C_UINT: return **(unsigned int**)pvalue;
461		case _C_LNG: return **(long**)pvalue;
462		case _C_ULNG: return **(unsigned long**)pvalue;
463		case _C_LNG_LNG: return **(long long**)pvalue;
464		case _C_ULNG_LNG: return **(unsigned long long**)pvalue;
465		}
466
467		if (strncmp(type+1, @encode(NSRange), sizeof(@encode(NSRange)) - 1) == 0) {
468			return (*(NSRange**)pvalue)->length;
469		}
470
471		/* Fall through: */
472	}
473	if (strncmp(type, @encode(NSRange), sizeof(@encode(NSRange)) - 1) == 0) {
474		return ((NSRange*)pvalue)->length;
475	}
476	if (strncmp(type, @encode(CFRange), sizeof(@encode(CFRange)) - 1) == 0) {
477		return ((CFRange*)pvalue)->length;
478	}
479#ifdef __LP64__
480	if (strncmp(type, "{_CFRange=qq}", sizeof("{_CFRange=qq}") - 1) == 0) {
481		return ((CFRange*)pvalue)->length;
482	}
483#else
484	if (strncmp(type, "{_CFRange=ii}", sizeof("{_CFRange=ii}") - 1) == 0) {
485		return ((CFRange*)pvalue)->length;
486	}
487#endif
488
489	if (strncmp(type, @encode(CFArrayRef), sizeof(@encode(CFArrayRef))-1) == 0 ||
490		strncmp(type, @encode(CFMutableArrayRef), sizeof(@encode(CFMutableArrayRef))-1) == 0) {
491
492		return CFArrayGetCount(*(CFArrayRef*)pvalue);
493	}
494	PyErr_Format(PyExc_TypeError,
495			"Don't know how to convert to extract count: %s", type);
496	return -1;
497}
498
499/* Support for printf format strings */
500static int
501parse_printf_args(
502	PyObject* py_format,
503	PyObject* argtuple, Py_ssize_t argoffset,
504	void** byref, struct byref_attr* byref_attr,
505	ffi_type** arglist, void** values,
506	Py_ssize_t curarg)
507{
508	/* Walk the format string as a UTF-8 encoded ASCII value. This isn't
509	 * perfect but keeps the code simple.
510	 */
511	Py_ssize_t maxarg = PyTuple_Size(argtuple);
512
513	PyObject* encoded;
514	PyObject* v;
515
516	if (PyString_Check(py_format)) {
517		encoded = py_format;
518		Py_INCREF(Py_None);
519
520	} else if (PyUnicode_Check(py_format)) {
521		encoded = PyUnicode_AsUTF8String(py_format);
522		if (encoded == NULL) {
523			return -1;
524		}
525
526	} else {
527		PyErr_SetString(PyExc_TypeError, "Unsupported format string type");
528		return -1;
529	}
530
531	const char* format = PyString_AsString(encoded);
532	if (format == NULL) {
533		Py_DECREF(encoded);
534		return -1;
535	}
536
537	format = strchr(format, '%');
538	while (format && *format != '\0') {
539		char typecode;
540
541		/* Skip '%' */
542		format ++;
543
544		/* Check for '%%' escape */
545		if (*format == '%') {
546			format++;
547			format = strchr(format, '%');
548			continue;
549		}
550
551		/* Skip flags */
552		while (1) {
553		   if (!*format)  break;
554		   if (
555			   (*format == '#')
556			|| (*format == '0')
557			|| (*format == '-')
558			|| (*format == ' ')
559			|| (*format == '+')
560			|| (*format == '\'')) {
561
562			format++;
563		   } else {
564			break;
565		   }
566		}
567
568		/* Field width */
569		if (*format == '*') {
570			if (argoffset >= maxarg) {
571				PyErr_Format(PyExc_ValueError, "Too few arguments for format string [cur:%"PY_FORMAT_SIZE_T"d/len:%"PY_FORMAT_SIZE_T"d]", argoffset, maxarg);
572				Py_DECREF(encoded);
573				return -1;
574			}
575			format++;
576			byref[curarg] = PyMem_Malloc(sizeof(int));
577			if (byref[curarg] == NULL) {
578				Py_DECREF(encoded);
579				return -1;
580			}
581
582			if (depythonify_c_value(@encode(int), PyTuple_GET_ITEM(argtuple, argoffset), byref[curarg]) < 0) {
583				Py_DECREF(encoded);
584				return -1;
585			}
586			values[curarg] = byref[curarg];
587			arglist[curarg] = signature_to_ffi_type(@encode(int));
588
589			argoffset++;
590			curarg++;
591
592		} else {
593			while (isdigit(*format)) format++;
594		}
595
596		/* Precision */
597		if (*format == '.') {
598			format++;
599			if (*format == '*') {
600				format++;
601				if (argoffset >= maxarg) {
602					PyErr_Format(PyExc_ValueError, "Too few arguments for format string [cur:%"PY_FORMAT_SIZE_T"d/len:%"PY_FORMAT_SIZE_T"d]", argoffset, maxarg);
603					Py_DECREF(encoded);
604					return -1;
605				}
606				byref[curarg] = PyMem_Malloc(sizeof(long long));
607				if (byref[curarg] == NULL) {
608					Py_DECREF(encoded);
609					return -1;
610				}
611
612
613				if (depythonify_c_value(@encode(int), PyTuple_GET_ITEM(argtuple, argoffset), byref[curarg]) < 0) {
614					Py_DECREF(encoded);
615					return -1;
616				}
617				values[curarg] = byref[curarg];
618				arglist[curarg] = signature_to_ffi_type(@encode(int));
619				argoffset++;
620				curarg++;
621			} else {
622				while (isdigit(*format)) format++;
623			}
624		}
625
626		/* length modifier */
627		typecode = 0;
628
629		if (*format == 'h') {
630			format++;
631
632			if (*format == 'h') {
633				format++;
634			}
635
636		} else if (*format == 'l') {
637			format++;
638			typecode = _C_LNG;
639			if (*format == 'l') {
640				typecode = _C_LNG_LNG;
641				format++;
642			}
643
644		} else if (*format == 'q') {
645			format++;
646			typecode = _C_LNG_LNG;
647
648		} else if (*format == 'j') {
649			typecode = _C_LNG_LNG;
650			format++;
651
652		} else if (*format == 'z') {
653			typecode = *@encode(size_t);
654			format++;
655
656		} else if (*format == 't') {
657			typecode = *@encode(ptrdiff_t);
658			format++;
659
660		} else if (*format == 'L') {
661			/* typecode = _C_LNGDBL, that's odd: no type encoding for long double! */
662			format++;
663
664		}
665
666		if (argoffset >= maxarg) {
667			PyErr_Format(PyExc_ValueError, "Too few arguments for format string [cur:%"PY_FORMAT_SIZE_T"d/len:%"PY_FORMAT_SIZE_T"d]", argoffset, maxarg);
668			Py_DECREF(encoded);
669			return -1;
670		}
671
672		/* And finally the info we're after: the actual format character */
673		switch (*format) {
674		case 'c': case 'C':
675#if SIZEOF_WCHAR_T != 4
676#	error "Unexpected wchar_t size"
677#endif
678
679			byref[curarg] = PyMem_Malloc(sizeof(int));
680			arglist[curarg] = signature_to_ffi_type(@encode(int));
681			v = PyTuple_GET_ITEM(argtuple, argoffset);
682			if (PyString_Check(v)) {
683				if (PyString_Size(v) != 1) {
684					PyErr_SetString(PyExc_ValueError, "Expecting string of length 1");
685					Py_DECREF(encoded);
686					return -1;
687				}
688				*(int*)byref[curarg] = (wchar_t)*PyString_AsString(v);
689			} else if (PyUnicode_Check(v)) {
690
691				if (PyUnicode_GetSize(v) != 1) {
692					PyErr_SetString(PyExc_ValueError, "Expecting string of length 1");
693					Py_DECREF(encoded);
694					return -1;
695				}
696				*(int*)byref[curarg] = (wchar_t)*PyUnicode_AsUnicode(v);
697			} else if (depythonify_c_value(@encode(int), v, byref[curarg]) < 0) {
698				Py_DECREF(encoded);
699				return -1;
700			}
701
702			values[curarg] = byref[curarg];
703
704			argoffset++;
705			curarg++;
706			break;
707
708		case 'd': case 'i': case 'D':
709			/* INT */
710			if (*format == 'D') {
711				typecode = _C_LNG;
712			}
713
714			if (typecode == _C_LNG_LNG) {
715				byref[curarg] = PyMem_Malloc(sizeof(long long));
716
717			} else if (typecode == _C_LNG) {
718				byref[curarg] = PyMem_Malloc(sizeof(long));
719
720			} else {
721				typecode = _C_INT;
722				byref[curarg] = PyMem_Malloc(sizeof(int));
723			}
724			if (byref[curarg] == NULL) {
725				PyErr_NoMemory();
726				return -1;
727			}
728			if (depythonify_c_value(&typecode, PyTuple_GET_ITEM(argtuple, argoffset), byref[curarg]) < 0) {
729				Py_DECREF(encoded);
730				return -1;
731			}
732			values[curarg] = byref[curarg];
733			arglist[curarg] = signature_to_ffi_type(&typecode);
734
735			argoffset++;
736			curarg++;
737			break;
738
739		case 'o': case 'u': case 'x':
740		case 'X': case 'U': case 'O':
741			/* UNSIGNED */
742			if (*format == 'U' || *format == 'X') {
743				typecode = _C_LNG;
744			}
745
746			if (typecode == _C_LNG_LNG) {
747				byref[curarg] = PyMem_Malloc(sizeof(long long));
748				typecode = _C_ULNG_LNG;
749
750			} else if (typecode == _C_LNG) {
751				byref[curarg] = PyMem_Malloc(sizeof(long));
752				typecode = _C_ULNG;
753
754			} else {
755				byref[curarg] = PyMem_Malloc(sizeof(int));
756				typecode = _C_UINT;
757			}
758			if (byref[curarg] == NULL) {
759				PyErr_NoMemory();
760				Py_DECREF(encoded);
761				return -1;
762			}
763			if (depythonify_c_value(&typecode, PyTuple_GET_ITEM(argtuple, argoffset), byref[curarg]) < 0) {
764				Py_DECREF(encoded);
765				return -1;
766			}
767			values[curarg] = byref[curarg];
768			arglist[curarg] = signature_to_ffi_type(&typecode);
769
770			argoffset++;
771			curarg++;
772			break;
773
774		case 'f': case 'F': case 'e': case 'E':
775		case 'g': case 'G': case 'a': case 'A':
776			/* double */
777			typecode = _C_DBL;
778			byref[curarg] = PyMem_Malloc(sizeof(double));
779			if (byref[curarg] == NULL) {
780				PyErr_NoMemory();
781				Py_DECREF(encoded);
782				return -1;
783			}
784
785			if (depythonify_c_value(&typecode, PyTuple_GET_ITEM(argtuple, argoffset), byref[curarg]) < 0) {
786				Py_DECREF(encoded);
787				return -1;
788			}
789			values[curarg] = byref[curarg];
790#if defined(__ppc__)
791			/* Passing floats to variadic functions on darwin/ppc
792			 * is slightly convoluted. Lying to libffi about the
793			 * type of the argument seems to trick it into doing
794			 * what the callee expects.
795			 * XXX: need to test if this is still needed.
796			 */
797			arglist[curarg] = &ffi_type_uint64;
798#else
799			arglist[curarg] = signature_to_ffi_type(&typecode);
800#endif
801
802			argoffset++;
803			curarg++;
804			break;
805
806
807		case 's': case 'S':
808			/* string */
809			if (*format == 'S' || typecode == _C_LNG) {
810				/* whar_t */
811				v = byref_attr[curarg].buffer = PyUnicode_FromObject( PyTuple_GET_ITEM(argtuple, argoffset));
812				if (byref_attr[curarg].buffer == NULL) {
813					Py_DECREF(encoded);
814					return -1;
815				}
816
817				Py_ssize_t sz = PyUnicode_GetSize(v);
818				byref[curarg] = PyMem_Malloc(sizeof(wchar_t)*(sz+1));
819				if (byref[curarg] == NULL) {
820					Py_DECREF(encoded);
821					return -1;
822				}
823
824				if (PyUnicode_AsWideChar((PyUnicodeObject*)v, (wchar_t*)byref[curarg], sz)<0) {
825					Py_DECREF(encoded);
826					return -1;
827				}
828				((wchar_t*)byref[curarg])[sz] = 0;
829				arglist[curarg] = signature_to_ffi_type(@encode(wchar_t*));
830				values[curarg] = byref + curarg;
831			} else {
832				/* char */
833				typecode = _C_CHARPTR;
834				byref[curarg] = PyMem_Malloc(sizeof(char*));
835				if (byref[curarg] == NULL) {
836					PyErr_NoMemory();
837					Py_DECREF(encoded);
838					return -1;
839				}
840				if (depythonify_c_value(&typecode, PyTuple_GET_ITEM(argtuple, argoffset), byref[curarg]) < 0) {
841					Py_DECREF(encoded);
842					return -1;
843				}
844				arglist[curarg] = signature_to_ffi_type(&typecode);
845				values[curarg] = byref[curarg];
846			}
847
848			argoffset++;
849			curarg++;
850			break;
851
852		case '@': case 'K':
853			/* object (%K is only used by NSPredicate */
854			typecode = _C_ID;
855			byref[curarg] = PyMem_Malloc(sizeof(char*));
856			if (byref[curarg] == NULL) {
857				PyErr_NoMemory();
858				Py_DECREF(encoded);
859				return -1;
860			}
861			if (depythonify_c_value(&typecode, PyTuple_GET_ITEM(argtuple, argoffset), byref[curarg]) < 0) {
862				Py_DECREF(encoded);
863				return -1;
864			}
865			values[curarg] = byref[curarg];
866			arglist[curarg] = signature_to_ffi_type(&typecode);
867
868			argoffset++;
869			curarg++;
870			break;
871
872		case 'p':
873			/* pointer */
874			byref[curarg] = PyMem_Malloc(sizeof(char*));
875			if (byref[curarg] == NULL) {
876				PyErr_NoMemory();
877				Py_DECREF(encoded);
878				return -1;
879			}
880			*((char**)byref[curarg]) = (char*)PyTuple_GET_ITEM(argtuple, argoffset);
881			values[curarg] = byref[curarg];
882			arglist[curarg] = signature_to_ffi_type(@encode(void*));
883
884			argoffset++;
885			curarg++;
886			break;
887
888		case 'n':
889			/* pointer-to-int */
890			byref[curarg] = PyMem_Malloc(sizeof(long long));
891			if (byref[curarg] == NULL) {
892				PyErr_NoMemory();
893				Py_DECREF(encoded);
894				return -1;
895			}
896			values[curarg] = byref[curarg];
897			arglist[curarg] = signature_to_ffi_type(&typecode);
898
899			argoffset++;
900			break;
901
902		default:
903			PyErr_SetString(PyExc_ValueError, "Invalid format string");
904			Py_DECREF(encoded);
905			return -1;
906		}
907
908
909		format = strchr(format+1, '%');
910	}
911
912	if (argoffset != maxarg) {
913		PyErr_Format(PyExc_ValueError, "Too many values for format [%"PY_FORMAT_SIZE_T"d/%"PY_FORMAT_SIZE_T"d]", argoffset, maxarg);
914		return -1;
915	}
916	return curarg;
917}
918
919static int parse_varargs_array(
920	PyObjCMethodSignature* methinfo,
921	PyObject* argtuple, Py_ssize_t argoffset,
922	void** byref,
923	ffi_type** arglist, void** values, Py_ssize_t count)
924{
925	Py_ssize_t curarg = methinfo->ob_size-1;
926	Py_ssize_t maxarg = PyTuple_Size(argtuple);
927	Py_ssize_t argSize;
928
929	if (count != -1) {
930		if (maxarg - curarg != count) {
931			PyErr_Format(PyExc_ValueError, "Wrong number of variadic arguments, need %" PY_FORMAT_SIZE_T "d, got %" PY_FORMAT_SIZE_T "d",
932					count, (maxarg - curarg));
933			return -1;
934		}
935	}
936
937	struct _PyObjC_ArgDescr* argType = (
938			methinfo->argtype + methinfo->ob_size - 1);
939
940	argSize = PyObjCRT_SizeOfType(argType->type);
941
942	if (count == -1) {
943		if (argType->type[0] != _C_ID) {
944			PyErr_Format(PyExc_TypeError,
945				"variadic null-terminated arrays only supported for type '%c', not '%s' || %s", _C_ID, argType->type, PyObject_REPR((PyObject*)methinfo));
946			return -1;
947		}
948	}
949
950	for (;argoffset < maxarg; curarg++, argoffset++) {
951		byref[curarg]  = PyMem_Malloc(argSize);
952		if (byref[curarg] == NULL) {
953			return -1;
954		}
955		if (depythonify_c_value(argType->type,
956			PyTuple_GET_ITEM(argtuple, argoffset),
957			byref[curarg]) < 0) {
958
959			return -1;
960		}
961
962		values[curarg] = byref[curarg];
963		arglist[curarg] = &ffi_type_pointer;
964	}
965	byref[curarg]  = NULL;
966	values[curarg] = &byref[curarg];
967	arglist[curarg] = &ffi_type_pointer;
968	return curarg+1;
969}
970
971/* This function decodes its arguments into Python values, then
972 * calls the python method and finally encodes the return value
973 */
974
975enum closureType {
976	PyObjC_Function,
977	PyObjC_Method,
978	PyObjC_Block,
979};
980
981typedef struct {
982	PyObject* callable;
983	int       argCount;
984	PyObjCMethodSignature* methinfo;
985	enum closureType	  closureType;
986} _method_stub_userdata;
987
988static void
989method_stub(ffi_cif* cif __attribute__((__unused__)), void* resp, void** args, void* _userdata)
990{
991	int err;
992	PyObject*  seq;
993	_method_stub_userdata* userdata = (_method_stub_userdata*)_userdata;
994	PyObject* callable = userdata->callable;
995	PyObjCMethodSignature* methinfo = userdata->methinfo;
996	Py_ssize_t         i, startArg;
997	PyObject*          arglist;
998	PyObject*          res;
999	PyObject*          v = NULL;
1000	int                have_output = 0;
1001	const char*        rettype;
1002	PyObject* 	   pyself;
1003	int		   cookie;
1004	Py_ssize_t	   count;
1005	BOOL		   haveCountArg;
1006
1007	PyGILState_STATE   state = PyGILState_Ensure();
1008
1009	rettype = methinfo->rettype.type;
1010
1011	arglist = PyList_New(0);
1012
1013	/* First translate from Objective-C to python */
1014	if (userdata->closureType == PyObjC_Method) {
1015		pyself = PyObjCObject_NewTransient(*(id*)args[0], &cookie);
1016		if (pyself == NULL) {
1017			goto error;
1018		}
1019		pyself = PyObjC_AdjustSelf(pyself);
1020		if (pyself == NULL) {
1021			goto error;
1022		}
1023		if (PyList_Append(arglist, pyself) == -1) {
1024			goto error;
1025		}
1026		startArg = 2;
1027	} else if (userdata->closureType == PyObjC_Block) {
1028		startArg = 1;
1029		pyself = NULL;
1030	} else {
1031		startArg = 0;
1032		pyself = NULL;
1033	}
1034
1035	for (i = startArg; i < methinfo->ob_size; i++) {
1036
1037		const char* argtype = methinfo->argtype[i].type;
1038
1039#if 0
1040		if (argtype[0] == 'O') {
1041			argtype ++;
1042		}
1043#endif
1044
1045		switch (*argtype) {
1046		case _C_INOUT:
1047			if (argtype[1] == _C_PTR) {
1048				have_output ++;
1049			}
1050			/* FALL THROUGH */
1051		case _C_IN: case _C_CONST:
1052			if (argtype[1] == _C_PTR && argtype[2] == _C_VOID && methinfo->argtype[i].ptrType == PyObjC_kPointerPlain) {
1053				/* A plain 'void*' that was marked up.
1054				 * This is wrong, but happens in the official metadata included
1055				 * with 10.5.x
1056				 */
1057				v = pythonify_c_value(argtype, args[i]);
1058			} else if (argtype[1] == _C_PTR || argtype[1] == _C_CHARPTR) {
1059				const char* resttype;
1060
1061				if (argtype[1] == _C_PTR) {
1062					resttype = argtype + 2;
1063				} else {
1064					resttype = gCharEncoding;
1065				}
1066
1067				if (*(void**)args[i] == NULL) {
1068					v = PyObjC_NULL;
1069					Py_INCREF(v);
1070				} else {
1071					switch (methinfo->argtype[i].ptrType) {
1072					case PyObjC_kPointerPlain:
1073						v = pythonify_c_value(resttype,
1074							*(void**)args[i]);
1075						break;
1076
1077					case PyObjC_kNullTerminatedArray:
1078						v = pythonify_c_array_nullterminated(resttype, *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1079						break;
1080
1081					case PyObjC_kArrayCountInArg:
1082						count = extract_count(
1083							methinfo->argtype[methinfo->argtype[i].arrayArg].type,
1084							args[methinfo->argtype[i].arrayArg]);
1085						if (count == -1 && PyErr_Occurred()) {
1086							v = NULL;
1087						} else {
1088							v = PyObjC_CArrayToPython2(resttype, *(void**)args[i], count, methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1089						}
1090						break;
1091
1092					case PyObjC_kFixedLengthArray:
1093						count = methinfo->argtype[i].arrayArg;
1094						v = PyObjC_CArrayToPython2(resttype, *(void**)args[i], count, methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1095						break;
1096
1097					case PyObjC_kVariableLengthArray:
1098						v = PyObjC_VarList_New(resttype, *(void**)args[i]);
1099						break;
1100					}
1101				}
1102
1103			} else {
1104				if (argtype[1] == _C_ARY_B) {
1105					v = pythonify_c_value(argtype+1, *(void**)(args[i]));
1106				} else {
1107					v = pythonify_c_value(argtype+1, args[i]);
1108				}
1109
1110			}
1111			break;
1112
1113		case _C_OUT:
1114			if (argtype[1] == _C_PTR) {
1115				have_output ++;
1116			}
1117
1118			if (userdata->argCount == methinfo->ob_size-1) {
1119				/* Python method has parameters for the output
1120				 * arguments as well, pass a placeholder value.
1121				 *
1122				 * XXX: For some types of arguments we could
1123				 * well pass in a buffer/array.array-style object!
1124				 */
1125				if (*(void**)args[i] == NULL) {
1126					v = PyObjC_NULL;
1127				} else {
1128					v = Py_None;
1129				}
1130				Py_INCREF(v);
1131			} else {
1132				/* Skip output parameter */
1133				continue;
1134			}
1135			break;
1136
1137		case _C_CHARPTR:
1138			 /* XXX: Not quite happy about this, why special case 'char*' but not 'int*' (both without in/out/inout markup) */
1139			if (*(void**)args[i] == NULL) {
1140				v = PyObjC_NULL;
1141				Py_INCREF(v);
1142			} else {
1143				switch (methinfo->argtype[i].ptrType) {
1144				case PyObjC_kPointerPlain:
1145					v = pythonify_c_value(argtype, args[i]);
1146					break;
1147
1148				case PyObjC_kNullTerminatedArray:
1149					v = pythonify_c_array_nullterminated(argtype, args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1150					break;
1151
1152				case PyObjC_kArrayCountInArg:
1153					count = extract_count(
1154						methinfo->argtype[methinfo->argtype[i].arrayArg].type,
1155						args[methinfo->argtype[i].arrayArg]);
1156					if (count == -1 && PyErr_Occurred()) {
1157						v = NULL;
1158					} else {
1159						v = PyString_FromStringAndSize(args[i], count);
1160					}
1161					break;
1162
1163				case PyObjC_kFixedLengthArray:
1164					count = methinfo->argtype[i].arrayArg;
1165					v = PyString_FromStringAndSize(args[i], count);
1166					break;
1167
1168				case PyObjC_kVariableLengthArray:
1169					v = PyObjC_VarList_New(gCharEncoding,
1170						args[i]);
1171					break;
1172				}
1173			}
1174			break;
1175
1176		case _C_ARY_B:
1177			/* An array is actually a pointer to the first
1178			 * element of the array. Libffi passes a pointer to
1179			 * that pointer, we need to strip one level of
1180			 * indirection to ensure that pythonify_c_value works
1181			 * correctly.
1182			 */
1183			v = pythonify_c_value(argtype, *(void**)args[i]);
1184			break;
1185
1186		default:
1187			v = pythonify_c_value(argtype, args[i]);
1188		}
1189		if (v == NULL) {
1190			Py_DECREF(arglist);
1191			goto error;
1192		}
1193		if (PyList_Append(arglist, v) == -1) {
1194			Py_DECREF(v);
1195			Py_DECREF(arglist);
1196			goto error;
1197		}
1198		Py_DECREF(v);
1199	}
1200
1201	v = PyList_AsTuple(arglist);
1202	if (v == NULL) {
1203		Py_DECREF(arglist);
1204		if (pyself) {
1205			PyObjCObject_ReleaseTransient(pyself, cookie);
1206		}
1207		goto error;
1208	}
1209	Py_DECREF(arglist);
1210	arglist = v;
1211
1212	if (!callable) {
1213		abort();
1214	}
1215
1216	/* Avoid calling a PyObjCPythonSelector directory, it does
1217	 * additional work that we don't need.
1218	 */
1219	if (PyObjCPythonSelector_Check(callable)) {
1220		callable = ((PyObjCPythonSelector*)callable)->callable;
1221	}
1222
1223	res = PyObject_Call(callable, arglist, NULL);
1224
1225	Py_DECREF(arglist);
1226	if (pyself) {
1227		PyObjCObject_ReleaseTransient(pyself, cookie);
1228	}
1229	if (res == NULL) {
1230		goto error;
1231	}
1232
1233	if (!have_output) {
1234		if (*rettype != _C_VOID) {
1235			const char* unqualified_type = PyObjCRT_SkipTypeQualifiers(rettype);
1236			if (unqualified_type[0] == _C_PTR || unqualified_type[0] == _C_CHARPTR) {
1237				const char* rest = unqualified_type + 1;
1238				if (*unqualified_type == _C_CHARPTR) {
1239					rest = gCharEncoding;
1240				}
1241
1242				if (res == PyObjC_NULL) {
1243					*(void**)resp = NULL;
1244				} else {
1245					switch (methinfo->rettype.ptrType) {
1246					case PyObjC_kPointerPlain:
1247						err = depythonify_c_return_value(unqualified_type, res, resp);
1248						if (err == -1) {
1249							Py_DECREF(res);
1250							goto error;
1251						}
1252						break;
1253
1254					case PyObjC_kFixedLengthArray:
1255						count = methinfo->rettype.arrayArg;
1256						err = depythonify_c_return_array_count(rest, count, res, resp, methinfo->rettype.alreadyRetained, methinfo->rettype.alreadyCFRetained);
1257						if (err == -1) {
1258							Py_DECREF(res);
1259							goto error;
1260						}
1261						break;
1262
1263					case PyObjC_kVariableLengthArray:
1264						err = depythonify_c_return_array_count(rest, -1, res, resp, methinfo->rettype.alreadyRetained, methinfo->rettype.alreadyCFRetained);
1265						if (err == -1) {
1266							Py_DECREF(res);
1267							goto error;
1268						}
1269						break;
1270
1271					case PyObjC_kNullTerminatedArray:
1272						err = depythonify_c_return_array_nullterminated(rest, res, resp, methinfo->rettype.alreadyRetained, methinfo->rettype.alreadyCFRetained);
1273						if (err == -1) {
1274							Py_DECREF(res);
1275							goto error;
1276						}
1277						break;
1278
1279					case PyObjC_kArrayCountInArg:
1280						/* We don't have output arguments, thus can calculate the response immediately */
1281						count = extract_count(
1282							methinfo->argtype[methinfo->rettype.arrayArg].type,
1283							args[methinfo->rettype.arrayArg]);
1284						if (count == -1 && PyErr_Occurred()) {
1285							goto error;
1286						}
1287						err = depythonify_c_return_array_count(rest, count, res, resp, methinfo->rettype.alreadyRetained, methinfo->rettype.alreadyCFRetained);
1288						if (err == -1) {
1289							Py_DECREF(res);
1290							goto error;
1291						}
1292					}
1293				}
1294
1295			} else {
1296				err = depythonify_c_return_value(rettype,
1297					res, resp);
1298
1299				if (methinfo->rettype.alreadyRetained) {
1300				   /* Must return a 'new' instead of a borrowed
1301				    * reference.
1302				    */
1303				   [(*(id*)resp) retain];
1304
1305				} else if (methinfo->rettype.alreadyCFRetained) {
1306				   /* Must return a 'new' instead of a borrowed
1307				    * reference.
1308				    */
1309				   CFRetain((*(id*)resp));
1310
1311				} else if (*rettype == _C_ID && res->ob_refcnt == 1) {
1312					/* make sure return value doesn't die before
1313					 * the caller can get its hands on it.
1314					 */
1315				    [[(*(id*)resp) retain] autorelease];
1316				}
1317
1318				if (err == -1) {
1319					if (res == Py_None) {
1320						if (userdata->closureType == PyObjC_Method) {
1321							PyErr_Format(PyExc_ValueError,
1322							   "%s: returned None, expecting "
1323							   "a value",
1324							   sel_getName(*(SEL*)args[1]));
1325						} else {
1326							PyObject* repr = PyObject_Repr(
1327								userdata->callable);
1328							PyErr_Format(PyExc_ValueError,
1329							   "%s: returned None, expecting "
1330							   "a value",
1331							   PyString_AsString(repr));
1332							Py_XDECREF(repr);
1333						}
1334
1335					}
1336					Py_DECREF(res);
1337					goto error;
1338				}
1339			}
1340		} else {
1341			if (res != Py_None) {
1342				if (userdata->closureType == PyObjC_Method) {
1343					PyErr_Format(PyExc_ValueError,
1344						"%s: did not return None, expecting "
1345						"void return value",
1346						sel_getName(*(SEL*)args[1]));
1347				} else {
1348					PyObject* repr = PyObject_Repr(
1349						userdata->callable);
1350					PyErr_Format(PyExc_ValueError,
1351					   "%s: returned None, expecting "
1352					   "a value",
1353					   PyString_AsString(repr));
1354					Py_XDECREF(repr);
1355				}
1356				goto error;
1357			}
1358			//*((int*)resp) = 0;
1359		}
1360
1361	} else {
1362		/* We have some output parameters, locate them and encode
1363		 * their values
1364		 */
1365		Py_ssize_t idx;
1366		PyObject* real_res;
1367
1368		if (*rettype == _C_VOID && have_output == 1) {
1369			/* Special case: the python method returned only
1370			 * the return value, not a tuple.
1371			 */
1372
1373			for (i = startArg; i < methinfo->ob_size; i++) {
1374				const char* argtype = methinfo->argtype[i].type;
1375
1376				switch (*argtype) {
1377				case _C_INOUT: case _C_OUT:
1378					if (argtype[1] == _C_PTR) {
1379						argtype += 2;
1380					} else if (argtype[1] == _C_CHARPTR) {
1381						argtype = gCharEncoding;
1382					} else {
1383						continue;
1384					}
1385					break;
1386				default: continue;
1387				}
1388
1389				if (*(void**)args[i] == NULL) {
1390					break;
1391				}
1392
1393				switch (methinfo->argtype[i].ptrType) {
1394				case PyObjC_kPointerPlain:
1395					err = depythonify_c_value(argtype, res, *(void**)args[i]);
1396					if (err == -1) {
1397						goto error;
1398					}
1399					if (argtype[0] == _C_ID && methinfo->argtype[i].alreadyRetained) {
1400						[**(id**)args[i] retain];
1401
1402					} else if (argtype[0] == _C_ID && methinfo->argtype[i].alreadyCFRetained) {
1403						CFRetain(**(id**)args[i]);
1404
1405					} else if (res->ob_refcnt == 1 && argtype[0] == _C_ID) {
1406						/* make sure return value doesn't die before
1407						 * the caller can get its hands on it.
1408						 */
1409						[[**(id**)args[i] retain] autorelease];
1410					}
1411					break;
1412
1413				case PyObjC_kNullTerminatedArray:
1414					count = c_array_nullterminated_size(res, &seq);
1415					if (count == -1) {
1416						goto error;
1417					}
1418					err = depythonify_c_array_nullterminated(argtype, count, seq, *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1419					Py_DECREF(seq);
1420					if (err == -1) {
1421						goto error;
1422					}
1423					break;
1424
1425				case PyObjC_kArrayCountInArg:
1426					count = extract_count(
1427							methinfo->argtype[methinfo->argtype[i].arrayArg].type,
1428							args[methinfo->argtype[i].arrayArg]);
1429					if (count == -1 && PyErr_Occurred()) {
1430						goto error;
1431					}
1432					err = depythonify_c_array_count(argtype, count, NO, res, *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1433					if (err == -1) {
1434						goto error;
1435					}
1436					break;
1437
1438				case PyObjC_kFixedLengthArray:
1439					count = methinfo->argtype[i].arrayArg;
1440					err = depythonify_c_array_count(argtype, count, YES, res, *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1441					if (err == -1) {
1442						goto error;
1443					}
1444					break;
1445
1446				case PyObjC_kVariableLengthArray:
1447					err = depythonify_c_array_count(argtype, -1, YES, res, *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1448					if (err == -1) {
1449						goto error;
1450					}
1451					break;
1452				}
1453
1454				break;
1455			}
1456
1457			PyGILState_Release(state);
1458			return;
1459		}
1460
1461		if (*rettype != _C_VOID) {
1462			if (!PyTuple_Check(res) || PyTuple_Size(res) != have_output+1) {
1463				PyErr_Format(PyExc_TypeError,
1464					"%s: Need tuple of %d arguments as result",
1465					sel_getName(*(SEL*)args[1]), have_output+1);
1466				Py_DECREF(res);
1467				goto error;
1468			}
1469
1470			real_res = PyTuple_GET_ITEM(res, 0);
1471			idx = 1;
1472
1473			const char* unqualified_type = PyObjCRT_SkipTypeQualifiers(rettype);
1474			if (unqualified_type[0] == _C_PTR || unqualified_type[0] == _C_CHARPTR) {
1475				const char* resttype = rettype + 1;
1476				if (unqualified_type[0] == _C_CHARPTR) {
1477					resttype = gCharEncoding;
1478				}
1479
1480				if (real_res == PyObjC_NULL) {
1481					*(void**)resp = NULL;
1482				} else {
1483					switch (methinfo->rettype.ptrType) {
1484					case PyObjC_kPointerPlain:
1485						err = depythonify_c_return_value(unqualified_type,
1486							real_res, resp);
1487						if (err == -1) {
1488							Py_DECREF(res);
1489							goto error;
1490						}
1491						break;
1492
1493					case PyObjC_kFixedLengthArray:
1494						count = methinfo->rettype.arrayArg;
1495						err = depythonify_c_return_array_count(resttype, count, real_res, resp, methinfo->rettype.alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1496						if (err == -1) {
1497							Py_DECREF(res);
1498							goto error;
1499						}
1500						break;
1501
1502					case PyObjC_kVariableLengthArray:
1503						err = depythonify_c_return_array_count(resttype, -1, real_res, resp, methinfo->rettype.alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1504						if (err == -1) {
1505							Py_DECREF(res);
1506							goto error;
1507						}
1508						break;
1509
1510					case PyObjC_kNullTerminatedArray:
1511						err = depythonify_c_return_array_nullterminated(resttype, real_res, resp, methinfo->rettype.alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1512						if (err == -1) {
1513							Py_DECREF(res);
1514							goto error;
1515						}
1516						break;
1517
1518					case PyObjC_kArrayCountInArg:
1519						if (*PyObjCRT_SkipTypeQualifiers(methinfo->argtype[methinfo->rettype.arrayArg].type) != _C_PTR) {
1520							count = extract_count(
1521								methinfo->argtype[methinfo->rettype.arrayArg].type,
1522								args[methinfo->rettype.arrayArg]);
1523							if (count == -1 && PyErr_Occurred()) {
1524								goto error;
1525							}
1526							err = depythonify_c_return_array_count(resttype, count, real_res, resp, methinfo->rettype.alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1527							if (err == -1) {
1528								Py_DECREF(res);
1529								goto error;
1530							}
1531						} else {
1532							/* Wait until after the arguments have been depythonified */
1533							*(void**)resp = NULL;
1534							break;
1535						}
1536
1537					}
1538				}
1539
1540			} else {
1541				err = depythonify_c_return_value(rettype,
1542					real_res, resp);
1543
1544				if (methinfo->rettype.alreadyRetained) {
1545				   /* Must return a 'new' instead of a borrowed
1546				    * reference.
1547				    */
1548				   [(*(id*)resp) retain];
1549
1550				} else if (methinfo->rettype.alreadyCFRetained) {
1551					CFRetain(*(id*)resp);
1552
1553				} else if (*rettype == _C_ID && real_res->ob_refcnt == 1) {
1554					/* make sure return value doesn't die before
1555					 * the caller can get its hands on it.
1556					 */
1557				    [[(*(id*)resp) retain] autorelease];
1558				}
1559				if (err == -1) {
1560					if (real_res == Py_None) {
1561						PyErr_Format(PyExc_ValueError,
1562						   "%s: returned None, expecting "
1563						   "a value",
1564						   sel_getName(*(SEL*)args[1]));
1565					}
1566					Py_DECREF(res);
1567					goto error;
1568				}
1569			}
1570		} else {
1571			if (!PyTuple_Check(res) || PyTuple_Size(res) != have_output) {
1572				PyErr_Format(PyExc_TypeError,
1573					"%s: Need tuple of %d arguments as result",
1574					sel_getName(*(SEL*)args[1]), have_output);
1575				Py_DECREF(res);
1576				goto error;
1577			}
1578			real_res = NULL;
1579			idx = 0;
1580		}
1581
1582		haveCountArg = NO;
1583		for (i = startArg; i < methinfo->ob_size; i++) {
1584			const char* argtype = methinfo->argtype[i].type;
1585
1586			switch (*argtype) {
1587			case _C_INOUT: case _C_OUT:
1588				if (argtype[1] == _C_PTR) {
1589					argtype += 2;
1590				} else if (argtype[1] == _C_CHARPTR) {
1591					argtype ++;
1592				} else {
1593					continue;
1594				}
1595				break;
1596			default: continue;
1597			}
1598
1599			if (*(void**)args[i] == NULL) {
1600				idx++;
1601				continue;
1602			}
1603
1604			switch (methinfo->argtype[i].ptrType) {
1605			case PyObjC_kPointerPlain:
1606				err = depythonify_c_value(argtype, PyTuple_GET_ITEM(res, idx++), *(void**)args[i]);
1607				if (err == -1) {
1608					goto error;
1609				}
1610
1611				if (argtype[0] == _C_ID && methinfo->argtype[i].alreadyRetained) {
1612					[**(id**)args[i] retain];
1613
1614				} else if (argtype[0] == _C_ID && methinfo->argtype[i].alreadyCFRetained) {
1615					CFRetain(**(id**)args[i]);
1616
1617				} else if (res->ob_refcnt == 1 && argtype[0] == _C_ID) {
1618					/* make sure return value doesn't die before
1619					 * the caller can get its hands on it.
1620					 */
1621					[[**(id**)args[i] retain] autorelease];
1622				}
1623				break;
1624
1625			case PyObjC_kNullTerminatedArray:
1626				count = c_array_nullterminated_size(PyTuple_GET_ITEM(res, idx++), &seq);
1627				if (count == -1) {
1628					goto error;
1629				}
1630
1631				err = depythonify_c_array_nullterminated(argtype, count, seq, *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1632				Py_DECREF(seq);
1633				if (err == -1) {
1634					goto error;
1635				}
1636				break;
1637
1638			case PyObjC_kArrayCountInArg:
1639				if (methinfo->argtype[i].arraySizeInRetval) {
1640					count = extract_count(methinfo->rettype.type, resp);
1641					if (count == -1 && PyErr_Occurred()) goto error;
1642
1643					err = depythonify_c_array_count(argtype, count, NO, PyTuple_GET_ITEM(res, idx++), *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1644					if (err == -1) {
1645						goto error;
1646					}
1647
1648				} else {
1649					haveCountArg = YES;
1650				}
1651				break;
1652
1653			case PyObjC_kFixedLengthArray:
1654				if (methinfo->argtype[i].arraySizeInRetval) {
1655					count = extract_count(methinfo->rettype.type, resp);
1656					if (count == -1 && PyErr_Occurred()) goto error;
1657
1658				} else {
1659					count = methinfo->argtype[i].arrayArg;
1660				}
1661				err = depythonify_c_array_count(argtype, count, YES, PyTuple_GET_ITEM(res, idx++), *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1662				if (err == -1) {
1663					goto error;
1664				}
1665				break;
1666
1667			case PyObjC_kVariableLengthArray:
1668				if (methinfo->argtype[i].arraySizeInRetval) {
1669					count = extract_count(methinfo->rettype.type, resp);
1670					if (count == -1 && PyErr_Occurred()) goto error;
1671
1672				} else {
1673					count = -1;
1674				}
1675				err = depythonify_c_array_count(argtype, count, YES, PyTuple_GET_ITEM(res, idx++), *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1676				if (err == -1) {
1677					goto error;
1678				}
1679				break;
1680
1681			}
1682		}
1683
1684		if (haveCountArg) {
1685			if (real_res == NULL) {
1686				idx = 0;
1687			} else {
1688				idx = 1;
1689			}
1690			for (i = 2; i < methinfo->ob_size; i++) {
1691				const char* argtype = methinfo->argtype[i].type;
1692
1693				switch (*argtype) {
1694				case _C_INOUT: case _C_OUT:
1695					if (argtype[1] == _C_PTR) {
1696						argtype += 2;
1697					} else if (argtype[1] == _C_CHARPTR) {
1698						argtype ++;
1699					} else {
1700						continue;
1701					}
1702					break;
1703				default: continue;
1704				}
1705
1706				if (*(void**)args[i] == NULL) {
1707					idx++;
1708					continue;
1709				}
1710
1711				switch (methinfo->argtype[i].ptrType) {
1712				case PyObjC_kPointerPlain:
1713				case PyObjC_kNullTerminatedArray:
1714				case PyObjC_kFixedLengthArray:
1715				case PyObjC_kVariableLengthArray:
1716					idx++;
1717					break;
1718
1719				case PyObjC_kArrayCountInArg:
1720					count = extract_count(
1721							methinfo->argtype[methinfo->argtype[i].arrayArg].type,
1722							args[methinfo->argtype[i].arrayArg]);
1723					if (count == -1 && PyErr_Occurred()) {
1724						goto error;
1725					}
1726					err = depythonify_c_array_count(argtype, count, NO, PyTuple_GET_ITEM(res, idx++), *(void**)args[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1727					if (err == -1) {
1728						goto error;
1729					}
1730					break;
1731				}
1732			}
1733		}
1734
1735		if (*rettype != _C_VOID) {
1736			const char* unqualified = PyObjCRT_SkipTypeQualifiers(rettype);
1737			if (unqualified[0] == _C_PTR || unqualified[0] == _C_CHARPTR) {
1738				if (methinfo->rettype.ptrType == PyObjC_kArrayCountInArg) {
1739					const char* rest = unqualified + 1;
1740					if (unqualified[0] == _C_CHARPTR) {
1741						rest = gCharEncoding;
1742					}
1743
1744					count = extract_count(
1745						methinfo->argtype[methinfo->rettype.arrayArg].type,
1746						args[methinfo->rettype.arrayArg]);
1747					if (count == -1 && PyErr_Occurred()) {
1748						goto error;
1749					}
1750					err = depythonify_c_return_array_count(rest, count, real_res, resp, methinfo->rettype.alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
1751					if (err == -1) {
1752						Py_DECREF(res);
1753						goto error;
1754					}
1755				}
1756			}
1757		}
1758
1759
1760		Py_DECREF(res);
1761
1762	}
1763
1764	PyGILState_Release(state);
1765
1766	return;
1767
1768error:
1769	PyObjCErr_ToObjCWithGILState(&state);
1770}
1771
1772/*
1773 * Return an IMP that is suitable for forwarding a method with the specified
1774 * signature from Objective-C to Python.
1775 */
1776
1777static int _argcount(PyObject* callable, BOOL* haveVarArgs, BOOL* haveVarKwds)
1778{
1779	PyCodeObject *func_code;
1780
1781	if (PyFunction_Check(callable)) {
1782		func_code = (PyCodeObject *)PyFunction_GetCode(callable);
1783		*haveVarArgs = (func_code->co_flags & CO_VARARGS) != 0;
1784		*haveVarKwds = (func_code->co_flags & CO_VARKEYWORDS) != 0;
1785		return func_code->co_argcount;
1786	} else if (PyMethod_Check(callable)) {
1787		func_code = (PyCodeObject *)PyFunction_GetCode(
1788			PyMethod_Function (callable));
1789		*haveVarArgs = (func_code->co_flags & CO_VARARGS) != 0;
1790		*haveVarKwds = (func_code->co_flags & CO_VARKEYWORDS) != 0;
1791		if (PyMethod_Self(callable) == NULL) {
1792			return func_code->co_argcount;
1793		} else {
1794			return func_code->co_argcount - 1;
1795		}
1796	} else if (PyObjCPythonSelector_Check(callable)) {
1797		return _argcount(((PyObjCPythonSelector*)callable)->callable, haveVarArgs, haveVarKwds);
1798
1799
1800	} else if (PyObjCNativeSelector_Check(callable)) {
1801		PyObjCMethodSignature* sig = PyObjCSelector_GetMetadata(callable);
1802		 int result = sig->ob_size - 1;
1803
1804		 Py_DECREF(sig);
1805		 return result;
1806
1807
1808	} else {
1809		PyErr_Format(PyExc_TypeError,
1810			"Sorry, cannot create IMP for instances of type %s",
1811			callable->ob_type->tp_name);
1812		return -1;
1813	}
1814}
1815
1816
1817PyObjC_callback_function
1818PyObjCFFI_MakeFunctionClosure(PyObjCMethodSignature* methinfo, PyObject* callable)
1819{
1820	_method_stub_userdata* stubUserdata;
1821	PyObjC_callback_function closure;
1822
1823	stubUserdata = PyMem_Malloc(sizeof(*stubUserdata));
1824	if (stubUserdata == NULL) {
1825		return NULL;
1826	}
1827
1828	stubUserdata->methinfo = methinfo;
1829	Py_INCREF(methinfo);
1830	stubUserdata->closureType = PyObjC_Function;
1831
1832	if (callable) {
1833		BOOL haveVarArgs = NO;
1834		BOOL haveVarKwds = NO;
1835		stubUserdata->argCount = _argcount(callable, &haveVarArgs, &haveVarKwds);
1836		if (stubUserdata->argCount == -1) {
1837			Py_DECREF(methinfo);
1838			PyMem_Free(stubUserdata);
1839			return NULL;
1840		}
1841
1842
1843		if (stubUserdata->argCount == methinfo->ob_size && !haveVarArgs && !haveVarKwds) {
1844			/* OK */
1845		} else if ((stubUserdata->argCount <= 1) && haveVarArgs && haveVarKwds) {
1846			/* OK:
1847			 *    def m(self, *args, **kwds), or
1848			 *    def m(*args, **kwds)
1849			 */
1850		} else {
1851			/* Wrong number of arguments, raise an error */
1852			PyObject* repr = PyObject_Repr(callable);
1853			if (repr == NULL) {
1854				return NULL;
1855			}
1856
1857			PyErr_Format(PyObjCExc_BadPrototypeError,
1858				"Objective-C expects %"PY_FORMAT_SIZE_T"d arguments, Python argument has %d arguments for %s",
1859				methinfo->ob_size, stubUserdata->argCount,
1860				PyString_AsString(repr));
1861			Py_DECREF(repr);
1862			Py_DECREF(methinfo);
1863			PyMem_Free(stubUserdata);
1864			return NULL;
1865		}
1866
1867		stubUserdata->callable = callable;
1868		Py_INCREF(stubUserdata->callable);
1869	} else {
1870		stubUserdata->callable = NULL;
1871		stubUserdata->argCount = 0;
1872	}
1873
1874
1875	closure = (PyObjC_callback_function)PyObjCFFI_MakeClosure(methinfo, method_stub, stubUserdata);
1876	if (closure == NULL) {
1877		Py_DECREF(methinfo);
1878		if (stubUserdata->callable) {
1879			Py_DECREF(stubUserdata->callable);
1880		}
1881		PyMem_Free(stubUserdata);
1882		return NULL;
1883	}
1884
1885	return closure;
1886}
1887
1888
1889static int _coloncount(SEL sel)
1890{
1891	const char* selname = sel_getName(sel);
1892	int result = 0;
1893	while (*selname != 0) {
1894		if (*selname++ == ':') {
1895			result ++;
1896		}
1897	}
1898	return result;
1899}
1900
1901IMP
1902PyObjCFFI_MakeIMPForSignature(PyObjCMethodSignature* methinfo, SEL sel, PyObject* callable)
1903{
1904	_method_stub_userdata* stubUserdata;
1905	IMP closure;
1906
1907	stubUserdata = PyMem_Malloc(sizeof(*stubUserdata));
1908	if (stubUserdata == NULL) {
1909		return NULL;
1910	}
1911
1912	stubUserdata->methinfo = methinfo;
1913	Py_INCREF(methinfo);
1914	stubUserdata->closureType = PyObjC_Method;
1915
1916	if (callable) {
1917		BOOL haveVarArgs = NO;
1918		BOOL haveVarKwds = NO;
1919		stubUserdata->argCount = _argcount(callable, &haveVarArgs, &haveVarKwds);
1920		if (stubUserdata->argCount == -1) {
1921			Py_DECREF(methinfo);
1922			PyMem_Free(stubUserdata);
1923			return NULL;
1924		}
1925
1926		if (stubUserdata->argCount == methinfo->ob_size - 1&& !haveVarArgs && !haveVarKwds) {
1927			/* OK */
1928		} else if ((stubUserdata->argCount <= 1) && haveVarArgs && haveVarKwds) {
1929			/* OK */
1930		} else {
1931			/* Wrong number of arguments, raise an error */
1932			PyObject* repr = PyObject_Repr(callable);
1933			if (repr == NULL) {
1934				return NULL;
1935			}
1936
1937			PyErr_Format(PyObjCExc_BadPrototypeError,
1938				"Objective-C expects %"PY_FORMAT_SIZE_T"d arguments, Python argument has %d arguments for %s",
1939				methinfo->ob_size - 1, stubUserdata->argCount,
1940				PyString_AsString(repr));
1941			Py_DECREF(repr);
1942			Py_DECREF(methinfo);
1943			PyMem_Free(stubUserdata);
1944			return NULL;
1945		}
1946
1947		if (!haveVarArgs && !haveVarKwds) {
1948			/* Check if the number of colons is correct */
1949			int cc= _coloncount(sel);
1950
1951			if (cc != 0 && stubUserdata->argCount - 1 != cc) {
1952				PyObject* repr = PyObject_Repr(callable);
1953				if (repr == NULL) {
1954					return NULL;
1955				}
1956
1957				PyErr_Format(PyObjCExc_BadPrototypeError,
1958					"Python signature doesn't match implied Objective-C signature for %s",
1959					PyString_AsString(repr));
1960				Py_DECREF(repr);
1961				Py_DECREF(methinfo);
1962				PyMem_Free(stubUserdata);
1963				return NULL;
1964			}
1965		}
1966
1967		stubUserdata->callable = callable;
1968		Py_INCREF(stubUserdata->callable);
1969	} else {
1970		stubUserdata->callable = NULL;
1971		stubUserdata->argCount = 0;
1972	}
1973
1974
1975
1976	closure = PyObjCFFI_MakeClosure(methinfo, method_stub, stubUserdata);
1977	if (closure == NULL) {
1978		Py_DECREF(methinfo);
1979		if (stubUserdata->callable) {
1980			Py_DECREF(stubUserdata->callable);
1981		}
1982		PyMem_Free(stubUserdata);
1983		return NULL;
1984	}
1985
1986	return closure;
1987}
1988
1989void
1990PyObjCFFI_FreeIMP(IMP imp)
1991{
1992	_method_stub_userdata* userdata = PyObjCFFI_FreeClosure(imp);
1993
1994	if (userdata) {
1995		Py_XDECREF(userdata->methinfo);
1996		Py_DECREF(userdata->callable);
1997		PyMem_Free(userdata);
1998	}
1999}
2000
2001IMP
2002PyObjCFFI_MakeIMPForPyObjCSelector(PyObjCSelector *aSelector)
2003{
2004	if (PyObjCNativeSelector_Check(aSelector)) {
2005		PyObjCNativeSelector *nativeSelector =
2006			(PyObjCNativeSelector *) aSelector;
2007		Method aMeth;
2008
2009		if (nativeSelector->sel_flags & PyObjCSelector_kCLASS_METHOD) {
2010			aMeth = class_getClassMethod(nativeSelector->sel_class, nativeSelector->sel_selector);
2011		} else {
2012			aMeth = class_getInstanceMethod(nativeSelector->sel_class, nativeSelector->sel_selector);
2013		}
2014		return method_getImplementation(aMeth);
2015	} else {
2016		IMP result;
2017
2018		PyObjCPythonSelector *pythonSelector = (PyObjCPythonSelector *) aSelector;
2019		PyObjCMethodSignature* methinfo = PyObjCMethodSignature_ForSelector(
2020				pythonSelector->sel_class,
2021				pythonSelector->sel_selector,
2022				pythonSelector->sel_python_signature);
2023
2024		result = PyObjCFFI_MakeIMPForSignature(methinfo, pythonSelector->sel_selector, pythonSelector->callable);
2025		Py_DECREF(methinfo);
2026		return result;
2027	}
2028}
2029
2030
2031PyObjCBlockFunction
2032PyObjCFFI_MakeBlockFunction(PyObjCMethodSignature* methinfo, PyObject* callable)
2033{
2034	_method_stub_userdata* stubUserdata;
2035	PyObjCBlockFunction closure;
2036
2037	stubUserdata = PyMem_Malloc(sizeof(*stubUserdata));
2038	if (stubUserdata == NULL) {
2039		return NULL;
2040	}
2041
2042	stubUserdata->methinfo = methinfo;
2043	Py_INCREF(methinfo);
2044	stubUserdata->closureType = PyObjC_Block;
2045
2046	if (callable) {
2047		BOOL haveVarArgs = NO;
2048		BOOL haveVarKwds = NO;
2049		stubUserdata->argCount = _argcount(callable, &haveVarArgs, &haveVarKwds);
2050		if (stubUserdata->argCount == -1) {
2051			Py_DECREF(methinfo);
2052			PyMem_Free(stubUserdata);
2053			return NULL;
2054		}
2055
2056		if (stubUserdata->argCount == methinfo->ob_size -1 && !haveVarArgs && !haveVarKwds) {
2057			/* OK */
2058		} else if ((stubUserdata->argCount <= 1) && haveVarArgs && haveVarKwds) {
2059			/* OK */
2060		} else {
2061			/* Wrong number of arguments, raise an error */
2062			PyObject* repr = PyObject_Repr(callable);
2063			if (repr == NULL) {
2064				return NULL;
2065			}
2066
2067			PyErr_Format(PyObjCExc_BadPrototypeError,
2068				"Objective-C expects %"PY_FORMAT_SIZE_T"d arguments, Python argument has %d arguments for %s",
2069				methinfo->ob_size - 1, stubUserdata->argCount,
2070				PyString_AsString(repr));
2071			Py_DECREF(repr);
2072			Py_DECREF(methinfo);
2073			PyMem_Free(stubUserdata);
2074			return NULL;
2075		}
2076
2077		stubUserdata->callable = callable;
2078		Py_INCREF(stubUserdata->callable);
2079	} else {
2080		stubUserdata->callable = NULL;
2081		stubUserdata->argCount = 0;
2082	}
2083
2084	closure = (PyObjCBlockFunction)PyObjCFFI_MakeClosure(methinfo, method_stub, stubUserdata);
2085	if (closure == NULL) {
2086		Py_DECREF(methinfo);
2087		if (stubUserdata->callable) {
2088			Py_DECREF(stubUserdata->callable);
2089		}
2090		PyMem_Free(stubUserdata);
2091		return NULL;
2092	}
2093
2094	return closure;
2095}
2096
2097void
2098PyObjCFFI_FreeBlockFunction(PyObjCBlockFunction imp)
2099{
2100	_method_stub_userdata* userdata = PyObjCFFI_FreeClosure((IMP)imp);
2101
2102	if (userdata) {
2103		Py_XDECREF(userdata->methinfo);
2104		Py_DECREF(userdata->callable);
2105		PyMem_Free(userdata);
2106	}
2107}
2108
2109/* Count the number of arguments and their total size */
2110/* argument_size is not cleared and should be initialized to the amount of
2111 * bufferspace that will be allocated just before the argument array
2112 */
2113int PyObjCFFI_CountArguments(
2114		PyObjCMethodSignature* methinfo, Py_ssize_t argOffset,
2115		Py_ssize_t* byref_in_count,
2116		Py_ssize_t* byref_out_count,
2117		Py_ssize_t* plain_count,
2118		Py_ssize_t* argbuf_len,
2119		BOOL* variadicAllArgs)
2120{
2121	Py_ssize_t i;
2122	Py_ssize_t itemAlign;
2123	Py_ssize_t itemSize;
2124
2125	*byref_in_count = *byref_out_count = *plain_count = 0;
2126
2127	for (i = argOffset; i < methinfo->ob_size; i++) {
2128		const char *argtype = methinfo->argtype[i].type;
2129#if 0
2130		if (argtype[0] == 'O') {
2131			argtype++;
2132		}
2133#endif
2134
2135		switch (*argtype) {
2136		case _C_INOUT:
2137			if (argtype[1] == _C_PTR && PyObjCPointerWrapper_HaveWrapper(argtype+1)) {
2138				itemAlign = PyObjCRT_AlignOfType(argtype+1);
2139				itemSize = PyObjCRT_SizeOfType(argtype+1);
2140
2141			} else if (argtype[1] == _C_PTR) {
2142				(*byref_out_count) ++;
2143				(*byref_in_count) ++;
2144				itemAlign = PyObjCRT_AlignOfType(argtype+2);
2145				itemSize = PyObjCRT_SizeOfType(argtype+2);
2146				if (itemSize == -1) {
2147					return -1;
2148				}
2149			} else if (argtype[1] == _C_CHARPTR) {
2150				(*byref_out_count) ++;
2151				(*byref_in_count) ++;
2152				itemAlign = PyObjCRT_AlignOfType(gCharEncoding);
2153				itemSize = PyObjCRT_SizeOfType(gCharEncoding);
2154				if (itemSize == -1) {
2155					return -1;
2156				}
2157			} else {
2158				itemSize = PyObjCRT_SizeOfType(argtype+1);
2159				itemAlign = PyObjCRT_AlignOfType(argtype+1);
2160				if (itemSize == -1) {
2161					return -1;
2162				}
2163			}
2164			*argbuf_len = align(*argbuf_len, itemAlign);
2165			(*argbuf_len) += itemSize;
2166			break;
2167
2168		case _C_IN: case _C_CONST:
2169			if (argtype[1] == _C_PTR && argtype[2] == _C_VOID && methinfo->argtype[i].ptrType == PyObjC_kPointerPlain) {
2170				itemSize = PyObjCRT_SizeOfType(argtype);
2171				itemAlign = PyObjCRT_AlignOfType(argtype);
2172				if (itemSize == -1) {
2173					return -1;
2174				}
2175				*argbuf_len = align(*argbuf_len, itemAlign);
2176				(*argbuf_len) += itemSize;
2177				(*plain_count)++;
2178			} else if (argtype[1] == _C_PTR) {
2179				(*byref_in_count) ++;
2180				itemSize = PyObjCRT_SizeOfType(argtype+2);
2181				itemAlign = PyObjCRT_AlignOfType(argtype+2);
2182				if (itemSize == -1) {
2183					return -1;
2184				}
2185			} else if (argtype[1] == _C_CHARPTR) {
2186				(*byref_in_count) ++;
2187				itemAlign = PyObjCRT_AlignOfType(gCharEncoding);
2188				itemSize = PyObjCRT_SizeOfType(gCharEncoding);
2189				if (itemSize == -1) {
2190					return -1;
2191				}
2192			} else {
2193				(*plain_count) ++;
2194				itemSize = PyObjCRT_SizeOfType(argtype+1);
2195				itemAlign = PyObjCRT_AlignOfType(argtype+1);
2196				if (itemSize == -1) {
2197					return -1;
2198				}
2199			}
2200			*argbuf_len = align(*argbuf_len, itemAlign);
2201			(*argbuf_len) += itemSize;
2202			break;
2203
2204		case _C_OUT:
2205			if (argtype[1] == _C_PTR) {
2206				(*byref_out_count) ++;
2207				itemSize = PyObjCRT_SizeOfType(argtype+2);
2208				itemAlign = PyObjCRT_AlignOfType(argtype+2);
2209				if (itemSize == -1) {
2210					return -1;
2211				}
2212			} else if (argtype[1] == _C_CHARPTR) {
2213				(*byref_out_count) ++;
2214				itemAlign = PyObjCRT_AlignOfType(gCharEncoding);
2215				itemSize = PyObjCRT_SizeOfType(gCharEncoding);
2216				if (itemSize == -1) {
2217					return -1;
2218				}
2219			} else {
2220				(*plain_count)++;
2221				itemSize = PyObjCRT_SizeOfType(argtype+1);
2222				itemAlign = PyObjCRT_AlignOfType(argtype+1);
2223				if (itemSize == -1) {
2224					return -1;
2225				}
2226			}
2227			*argbuf_len = align(*argbuf_len, itemAlign);
2228			(*argbuf_len) += itemSize;
2229			break;
2230
2231		case _C_STRUCT_B: case _C_UNION_B: case _C_ARY_B:
2232			(*plain_count)++;
2233			itemSize = PyObjCRT_SizeOfType(argtype);
2234			itemAlign = PyObjCRT_AlignOfType(argtype);
2235			if (itemSize == -1) {
2236				return -1;
2237			}
2238			*argbuf_len = align(*argbuf_len, itemAlign);
2239			(*argbuf_len) += itemSize;
2240			break;
2241
2242#if 0
2243		case _C_UNDEF:
2244			*argbuf_len = align(*argbuf_len, __alignof__(PyObjC_callback_function));
2245			(*argbuf_len) += sizeof(PyObjC_callback_function);
2246			break;
2247#endif
2248
2249		default:
2250			if (methinfo->argtype[i].printfFormat) {
2251				/* XXX: is this still needed? */
2252				*variadicAllArgs = YES;
2253				*argbuf_len += sizeof(NSObject*) * 2;
2254			}
2255			itemSize = PyObjCRT_SizeOfType(argtype);
2256			itemAlign = PyObjCRT_AlignOfType(argtype);
2257			if (itemSize == -1) {
2258				return -1;
2259			}
2260			*argbuf_len = align(*argbuf_len, itemAlign);
2261			(*argbuf_len) += itemSize;
2262			(*plain_count)++;
2263			break;
2264		}
2265	}
2266	return 0;
2267}
2268
2269
2270int PyObjCFFI_ParseArguments(
2271		PyObjCMethodSignature* methinfo, Py_ssize_t argOffset,
2272		PyObject* args,
2273		Py_ssize_t argbuf_cur, unsigned char* argbuf,
2274		Py_ssize_t argbuf_len __attribute__((__unused__)), // only used in debug builds
2275		void** byref,
2276		struct byref_attr* byref_attr,
2277		ffi_type** arglist, void** values)
2278{
2279	Py_ssize_t py_arg = 0;
2280	Py_ssize_t i;
2281	void* arg;
2282	Py_ssize_t count;
2283	PyObject* seq;
2284	BOOL have_counted_array = NO;
2285	PyObject* printf_format = NULL;
2286	Py_ssize_t sz;
2287	void* buffer = NULL;
2288	Py_ssize_t bufferlen = 0;
2289
2290	/* We have to do two passes over the argument array: the first to deal
2291	 * with plain arguments, the second deals with arrays whose size is
2292	 * the value of another argument.
2293	 */
2294
2295	Py_ssize_t meth_arg_count;
2296	if (methinfo->variadic && (methinfo->null_terminated_array || (methinfo->arrayArg != -1))) {
2297		meth_arg_count = methinfo->ob_size - 1;
2298	}  else {
2299		meth_arg_count = methinfo->ob_size;
2300	}
2301
2302
2303	for (i = argOffset; i < meth_arg_count; i++) {
2304
2305		int error = 0;
2306		PyObject *argument = NULL;
2307		const char *argtype = methinfo->argtype[i].type;
2308
2309		if (argtype[0] == _C_OUT && (
2310				(argtype[1] == _C_PTR && !PyObjCPointerWrapper_HaveWrapper(argtype + 1))
2311			     || (argtype[1] == _C_CHARPTR)
2312			)) {
2313			/* Just allocate room in argbuf and set that*/
2314			const char* resttype = argtype+2;
2315			if (argtype[1] == _C_CHARPTR) {
2316				resttype = gCharEncoding;
2317			}
2318
2319			error = 0;
2320			argument = PyTuple_GET_ITEM (args, py_arg);
2321			py_arg ++;
2322
2323			if (argument == Py_None) {
2324				/* Fall through to the default
2325				 * behaviour
2326				 */
2327				error = 1; /* misuse of this flag ... */
2328
2329			} else if (argument == PyObjC_NULL) {
2330				if (methinfo->argtype[i].allowNULL) {
2331
2332					byref[i] = NULL;
2333					arglist[i] = &ffi_type_pointer;
2334					values[i] = byref + i;
2335
2336					error = 0;
2337				} else {
2338					PyErr_Format(
2339						PyExc_ValueError,
2340						"argument %" PY_FORMAT_SIZE_T "d isn't allowed to be NULL",
2341						i - argOffset);
2342					error = -1;
2343				}
2344			} else {
2345
2346				switch (methinfo->argtype[i].ptrType) {
2347				case PyObjC_kFixedLengthArray:
2348				case PyObjC_kVariableLengthArray:
2349				case PyObjC_kArrayCountInArg:
2350					if (PyObject_AsWriteBuffer(argument, &buffer, &bufferlen) != -1) {
2351						error = 1;
2352						break;
2353
2354					} else {
2355						PyErr_Clear();
2356						/* FALL THROUGH */
2357					}
2358
2359				default:
2360					PyErr_Format(
2361						PyExc_ValueError,
2362						"argument %" PY_FORMAT_SIZE_T "d must be None or objc.NULL",
2363						i - argOffset);
2364					error = -1;
2365				}
2366			}
2367
2368			if (error == -1) {
2369				return -1;
2370
2371			}  else if (error == 0) {
2372				continue;
2373
2374			}
2375
2376			switch (methinfo->argtype[i].ptrType) {
2377			case PyObjC_kPointerPlain:
2378				argbuf_cur = align(argbuf_cur,
2379					PyObjCRT_AlignOfType(resttype));
2380				sz = PyObjCRT_SizeOfType(resttype);
2381				byref[i] = PyMem_Malloc(sz);
2382				arg = NULL;
2383
2384				arglist[i] = &ffi_type_pointer;
2385				values[i] = byref+i;
2386
2387				/* Clear the output buffer, just in case the called
2388				 * function doesn't write anything into the buffer.
2389				 */
2390				memset(byref[i], 0, sz);
2391				break;
2392
2393			case PyObjC_kNullTerminatedArray:
2394				PyErr_SetString(PyExc_TypeError,
2395					"NULL-terminated 'out' arguments are not supported");
2396				return -1;
2397
2398			case PyObjC_kFixedLengthArray:
2399				if (PyObject_AsWriteBuffer(argument, &buffer, &bufferlen) != -1) {
2400
2401					count = methinfo->argtype[i].arrayArg;
2402					byref_attr[i].token = PyObjC_PythonToCArray(
2403						YES, YES,
2404						resttype,
2405						argument,
2406						byref + i,
2407						&count,
2408						&byref_attr[i].buffer);
2409					if (byref_attr[i].token == -1) {
2410						return -1;
2411					}
2412
2413
2414				} else {
2415					PyErr_Clear();
2416
2417					sz = PyObjCRT_SizeOfType(resttype) * methinfo->argtype[i].arrayArg;
2418					byref[i] = PyMem_Malloc(sz);
2419					if (byref[i] == NULL) {
2420						PyErr_NoMemory();
2421						return -1;
2422					}
2423					memset(byref[i], 0, sz);
2424				}
2425
2426				arglist[i] = &ffi_type_pointer;
2427				values[i] = byref+i;
2428				break;
2429
2430			case PyObjC_kVariableLengthArray:
2431				if (PyObject_AsWriteBuffer(argument, &buffer, &bufferlen) != -1) {
2432
2433					count = methinfo->argtype[i].arrayArg;
2434					byref_attr[i].token = PyObjC_PythonToCArray(
2435						YES, YES,
2436						resttype,
2437						argument,
2438						byref + i,
2439						NULL,
2440						&byref_attr[i].buffer);
2441					if (byref_attr[i].token == -1) {
2442						return -1;
2443					}
2444
2445
2446				} else {
2447					PyErr_Format(PyExc_TypeError,
2448						"Need explict buffer for variable-length array argument");
2449					return -1;
2450				}
2451
2452				arglist[i] = &ffi_type_pointer;
2453				values[i] = byref+i;
2454				break;
2455
2456			case PyObjC_kArrayCountInArg:
2457				have_counted_array = YES;
2458				break;
2459			}
2460
2461		} else {
2462			/* Encode argument, maybe after allocating space */
2463
2464			if (argtype[0] == _C_OUT) argtype ++; /* XXX: is this correct ???? */
2465
2466			argument = PyTuple_GET_ITEM (args, py_arg);
2467			switch (*argtype) {
2468			case _C_STRUCT_B: case _C_ARY_B: case _C_UNION_B:
2469				/* Allocate space and encode */
2470
2471				sz = PyObjCRT_SizeOfType(argtype);
2472				byref[i] = PyMem_Malloc(sz);
2473				if (byref[i] == NULL) {
2474					PyErr_NoMemory();
2475					return -1;
2476				}
2477				error = depythonify_c_value (
2478					argtype,
2479					argument,
2480					byref[i]);
2481
2482				arglist[i] = signature_to_ffi_type(argtype);
2483
2484				if (*argtype == _C_ARY_B) {
2485					values[i] = &byref[i];
2486				} else {
2487					values[i] = byref[i];
2488				}
2489				break;
2490
2491			case _C_INOUT:
2492			case _C_IN:
2493			case _C_CONST:
2494				if (argtype[1] == _C_PTR && argtype[2] == _C_VOID && methinfo->argtype[i].ptrType == PyObjC_kPointerPlain) {
2495					argbuf_cur = align(argbuf_cur, PyObjCRT_AlignOfType(argtype));
2496					arg = argbuf + argbuf_cur;
2497					argbuf_cur += PyObjCRT_SizeOfType(argtype);
2498					PyObjC_Assert(argbuf_cur <= argbuf_len, -1);
2499
2500					if (methinfo->argtype[i].printfFormat) {
2501						printf_format = argument;
2502						Py_INCREF(argument);
2503					}
2504
2505					error = depythonify_c_value (
2506						argtype,
2507						argument,
2508						arg);
2509
2510					arglist[i] = signature_to_ffi_type(argtype);
2511					values[i] = arg;
2512
2513				} else if (argtype[1] == _C_CHARPTR || (argtype[1] == _C_PTR && !PyObjCPointerWrapper_HaveWrapper(argtype+1))) {
2514					/* Allocate space and encode */
2515					const char* resttype = argtype + 2;
2516					if (argtype[1] == _C_CHARPTR) {
2517						resttype = gCharEncoding;
2518					} else if (argtype[2] == _C_UNDEF) {
2519						/* This better be a function argument, other types of 'undefined' arguments
2520						 * aren't supported.
2521						 */
2522						if (methinfo->argtype[i].callable == NULL) {
2523							PyErr_SetString(PyExc_ValueError, "calling method/function with 'undefined' argument");
2524							return -1;
2525						}
2526						argbuf_cur = align(argbuf_cur, __alignof__(PyObjC_callback_function));
2527						arg = argbuf + argbuf_cur;
2528						argbuf_cur += sizeof(PyObjC_callback_function);
2529						PyObjC_Assert(argbuf_cur <= argbuf_len, -1);
2530						arglist[i] = signature_to_ffi_type(argtype);
2531						values[i] = arg;
2532
2533						if (argument == Py_None) {
2534							*(PyObjC_callback_function*)arg = NULL;
2535
2536						} else {
2537							PyObjC_callback_function closure;
2538							PyObject* v = PyObject_GetAttrString(argument, "pyobjc_closure");
2539							if (v == NULL) {
2540								if (!methinfo->argtype[i].callableRetained) {
2541									/* The callback isn't retained by the called function,
2542									 * therefore we can safely synthesize a closure and
2543									 * clean it up after the call.
2544									 */
2545									PyErr_Clear();
2546
2547									closure = PyObjCFFI_MakeFunctionClosure(
2548											methinfo->argtype[i].callable,
2549											argument
2550										);
2551									if (closure == NULL) {
2552										return -1;
2553									}
2554									byref_attr[i].buffer = PyCObject_FromVoidPtr(
2555										closure,
2556										(void(*)(void*))PyObjCFFI_FreeIMP);
2557								} else {
2558									PyErr_SetString(PyExc_TypeError,
2559										"Callable argument is not a PyObjC closure");
2560									return -1;
2561								}
2562
2563							} else {
2564								if (!PyCObject_Check(v) || PyCObject_GetDesc(v) != &PyObjCMethodSignature_Type) {
2565									PyErr_SetString(PyExc_TypeError,
2566										"Invalid pyobjc_closure attribute");
2567								}
2568								closure = PyCObject_AsVoidPtr(v);
2569							}
2570							*(PyObjC_callback_function*)arg = closure;
2571						}
2572						break;
2573					}
2574
2575					if (argument == PyObjC_NULL || argument == Py_None) {
2576						if (methinfo->argtype[i].allowNULL) {
2577
2578							byref[i] = NULL;
2579							error = 0;
2580						} else {
2581							PyErr_Format(
2582								PyExc_ValueError,
2583								"argument %" PY_FORMAT_SIZE_T "d isn't allowed to be NULL", i - argOffset);
2584							error = -1;
2585						}
2586
2587					} else {
2588						switch (methinfo->argtype[i].ptrType) {
2589						case PyObjC_kPointerPlain:
2590							byref[i] = PyMem_Malloc(PyObjCRT_SizeOfType(resttype));
2591							error = depythonify_c_value (
2592								resttype,
2593								argument,
2594								byref[i]);
2595							break;
2596
2597
2598						case PyObjC_kFixedLengthArray:
2599							count = methinfo->argtype[i].arrayArg;
2600
2601							byref_attr[i].token = PyObjC_PythonToCArray(
2602								argtype[0] == _C_INOUT, YES,
2603								resttype,
2604								argument,
2605								byref + i,
2606								&count,
2607								&byref_attr[i].buffer);
2608							if (byref_attr[i].token == -1) {
2609								error = -1;
2610							} else {
2611								error = 0;
2612							}
2613							break;
2614
2615						case PyObjC_kVariableLengthArray:
2616							 /* TODO: add explicit support for UniChar arrays */
2617							byref_attr[i].token = PyObjC_PythonToCArray(
2618									argtype[0] == _C_INOUT, YES,
2619									resttype,
2620									argument,
2621									byref + i,
2622									NULL,
2623									&byref_attr[i].buffer);
2624							if (byref_attr[i].token == -1) {
2625								error = -1;
2626							} else {
2627								error = 0;
2628							}
2629							break;
2630
2631						case PyObjC_kNullTerminatedArray:
2632							 /* TODO: add explicit support for UniChar arrays */
2633							seq = NULL;
2634							count = c_array_nullterminated_size(argument, &seq);
2635							if (seq == NULL) {
2636								error = -1;
2637							} else {
2638								byref[i] = PyMem_Malloc(count * PyObjCRT_SizeOfType(resttype));
2639								if (byref[i] == NULL) {
2640									PyErr_NoMemory();
2641									error = -1;
2642								} else {
2643									error = depythonify_c_array_nullterminated(resttype,
2644										count,
2645										seq,
2646										byref[i], methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
2647								}
2648								Py_DECREF(seq);
2649							}
2650							break;
2651
2652						case PyObjC_kArrayCountInArg:
2653							have_counted_array = YES;
2654							error = 0;
2655							break;
2656
2657
2658						default:
2659							Py_FatalError("Corrupt metadata!");
2660						}
2661					}
2662
2663					arglist[i] = &ffi_type_pointer;
2664					values[i] = byref + i;
2665
2666				} else {
2667					/* just encode */
2668					argbuf_cur = align(argbuf_cur, PyObjCRT_AlignOfType(argtype+1));
2669					arg = argbuf + argbuf_cur;
2670					argbuf_cur += PyObjCRT_SizeOfType(argtype+1);
2671					PyObjC_Assert(argbuf_cur <= argbuf_len, -1);
2672
2673					if (methinfo->argtype[i].printfFormat) {
2674						printf_format = argument;
2675						Py_INCREF(argument);
2676						error = 0;
2677
2678					}
2679					error = depythonify_c_value (
2680						argtype+1,
2681						argument,
2682						arg);
2683
2684					arglist[i] = signature_to_ffi_type(
2685						argtype+1);
2686					values[i] = arg;
2687
2688				}
2689				break;
2690
2691			case _C_CHARPTR:
2692
2693				arglist[i] = NULL;
2694				if (argument == PyObjC_NULL) {
2695					if (methinfo->argtype[i].allowNULL) {
2696
2697						byref[i] = NULL;
2698						error = 0;
2699					} else {
2700						PyErr_Format(
2701							PyExc_ValueError,
2702							"argument %" PY_FORMAT_SIZE_T "d isn't allowed to be NULL", i - argOffset);
2703						error = -1;
2704					}
2705
2706				} else {
2707					switch (methinfo->argtype[i].ptrType) {
2708					case PyObjC_kPointerPlain:
2709						argbuf_cur = align(argbuf_cur, PyObjCRT_AlignOfType(argtype));
2710						arg = argbuf + argbuf_cur;
2711						argbuf_cur += PyObjCRT_SizeOfType(argtype);
2712						PyObjC_Assert(argbuf_cur <= argbuf_len, -1);
2713
2714						if (methinfo->argtype[i].printfFormat) {
2715							printf_format = argument;
2716							Py_INCREF(argument);
2717
2718						}
2719						error = depythonify_c_value (
2720							argtype,
2721							argument,
2722							arg);
2723
2724						arglist[i] = signature_to_ffi_type(argtype);
2725						values[i] = arg;
2726						break;
2727
2728
2729					case PyObjC_kFixedLengthArray:
2730						{
2731						char resttype[] = {  _C_CHR, 0 };
2732						count = methinfo->argtype[i].arrayArg;
2733						byref_attr[i].token = PyObjC_PythonToCArray(
2734							NO, YES,
2735							resttype,
2736							argument,
2737							byref + i,
2738							&count,
2739							&byref_attr[i].buffer);
2740						}
2741						if (byref_attr[i].token == -1) {
2742							error = -1;
2743						}
2744						break;
2745
2746					case PyObjC_kVariableLengthArray:
2747						{
2748							const char* buf;
2749							Py_ssize_t len;
2750
2751							error = PyObject_AsCharBuffer(argument, &buf, &len);
2752							if (error != -1) {
2753								byref[i] = PyMem_Malloc(len);
2754								if (byref[i] == NULL) {
2755									PyErr_NoMemory();
2756									error = -1;
2757								} else {
2758									memcpy(byref[i], buf, len);
2759									error = 0;
2760								}
2761							} else {
2762								/* XXX */
2763								error = -1;
2764							}
2765
2766						}
2767
2768						break;
2769
2770					case PyObjC_kNullTerminatedArray:
2771						{
2772						const char* buf;
2773						Py_ssize_t len;
2774
2775						error = PyObject_AsCharBuffer(argument, &buf, &len);
2776						if (error != -1) {
2777							byref[i] = PyMem_Malloc(len+1);
2778							if (byref[i] == NULL) {
2779								PyErr_NoMemory();
2780								error = -1;
2781							} else {
2782								memcpy(byref[i], buf, len);
2783								((char*)byref[i])[len] = '\0';
2784							}
2785							Py_DECREF(seq);
2786						} else {
2787							error = -1;
2788						}
2789						}
2790						break;
2791
2792					case PyObjC_kArrayCountInArg:
2793						have_counted_array = YES;
2794						error = 0;
2795						break;
2796
2797
2798					default:
2799						Py_FatalError("Corrupt metadata!");
2800					}
2801				}
2802
2803				if (arglist[i] == NULL) {
2804					arglist[i] = &ffi_type_pointer;
2805					values[i] = byref + i;
2806				}
2807				break;
2808
2809			case _C_PTR:
2810				if (argtype[1] == _C_UNDEF) {
2811					/* This better be a function argument, other types of 'undefined' arguments
2812					 * aren't supported.
2813					 */
2814					if (methinfo->argtype[i].callable == NULL) {
2815						PyErr_SetString(PyExc_ValueError, "calling method/function with 'undefined' argument");
2816						return -1;
2817					}
2818					argbuf_cur = align(argbuf_cur, __alignof__(PyObjC_callback_function));
2819					arg = argbuf + argbuf_cur;
2820					argbuf_cur += sizeof(PyObjC_callback_function);
2821					PyObjC_Assert(argbuf_cur <= argbuf_len, -1);
2822					arglist[i] = signature_to_ffi_type(argtype);
2823					values[i] = arg;
2824
2825					if (argument == Py_None) {
2826						*(PyObjC_callback_function*)arg = NULL;
2827
2828					} else {
2829						PyObjC_callback_function closure;
2830						PyObject* v = PyObject_GetAttrString(argument, "pyobjc_closure");
2831						if (v == NULL) {
2832							if (!methinfo->argtype[i].callableRetained) {
2833								/* The callback isn't retained by the called function,
2834								 * therefore we can safely synthesize a closure and
2835								 * clean it up after the call.
2836								 */
2837								PyErr_Clear();
2838
2839								closure = PyObjCFFI_MakeFunctionClosure(
2840										methinfo->argtype[i].callable,
2841										argument
2842									);
2843								if (closure == NULL) {
2844									return -1;
2845								}
2846								byref_attr[i].buffer = PyCObject_FromVoidPtr(
2847									closure,
2848									(void(*)(void*))PyObjCFFI_FreeIMP);
2849							} else {
2850								PyErr_SetString(PyExc_TypeError,
2851									"Callable argument is not a PyObjC closure");
2852								return -1;
2853							}
2854
2855						} else {
2856							if (!PyCObject_Check(v) || PyCObject_GetDesc(v) != &PyObjCMethodSignature_Type) {
2857								PyErr_SetString(PyExc_TypeError,
2858									"Invalid pyobjc_closure attribute");
2859							}
2860							closure = PyCObject_AsVoidPtr(v);
2861						}
2862						*(PyObjC_callback_function*)arg = closure;
2863					}
2864					break;
2865				} else {
2866					/* FALL THROUGH */
2867				}
2868
2869
2870			case _C_ID:
2871				if (argtype[1] == '?') {
2872					/* Argument is a block */
2873					if (methinfo->argtype[i].callable == NULL) {
2874						PyErr_Format(PyExc_TypeError, "Argument %"PY_FORMAT_SIZE_T"d is a block, but no signature available", i);
2875						return -1;
2876					}
2877					argbuf_cur = align(argbuf_cur, PyObjCRT_AlignOfType(argtype));
2878					arg = argbuf + argbuf_cur;
2879					argbuf_cur += PyObjCRT_SizeOfType(argtype);
2880					PyObjC_Assert(argbuf_cur <= argbuf_len, -1);
2881					*(void**)arg = PyObjCBlock_Create(
2882						methinfo->argtype[i].callable, argument);
2883					if (*(void**)arg == NULL) {
2884						return -1;
2885					}
2886					byref_attr[i].buffer = PyCObject_FromVoidPtr(
2887						*(void**)arg,
2888						(void(*)(void*))PyObjCBlock_Release);
2889					arglist[i] = signature_to_ffi_type(argtype);
2890					values[i] = arg;
2891
2892					break;
2893				}
2894				/* else: fallthrough */
2895
2896			default:
2897				argbuf_cur = align(argbuf_cur, PyObjCRT_AlignOfType(argtype));
2898				arg = argbuf + argbuf_cur;
2899				argbuf_cur += PyObjCRT_SizeOfType(argtype);
2900				PyObjC_Assert(argbuf_cur <= argbuf_len, -1);
2901
2902				if (methinfo->argtype[i].printfFormat) {
2903					printf_format = argument;
2904					Py_INCREF(argument);
2905				}
2906
2907				error = depythonify_c_value (
2908					argtype,
2909					argument,
2910					arg);
2911
2912				arglist[i] = signature_to_ffi_type(argtype);
2913				values[i] = arg;
2914			}
2915
2916			if (error == -1) {
2917				return -1;
2918			}
2919			py_arg++;
2920		}
2921	}
2922
2923	if (have_counted_array) {
2924		py_arg = 0;
2925
2926		for (i = argOffset; i < meth_arg_count; i++) {
2927			PyObject *argument = NULL;
2928			const char *argtype = methinfo->argtype[i].type;
2929
2930			if (argtype[0] == _C_OUT && (argtype[1] == _C_PTR || argtype[1] == _C_CHARPTR)) {
2931				argument = PyTuple_GET_ITEM (args, py_arg);
2932				py_arg ++;
2933
2934				const char* resttype = argtype+2;
2935				if (argtype[1] == _C_CHARPTR) {
2936					resttype = gCharEncoding;
2937				}
2938
2939				if (methinfo->argtype[i].ptrType == PyObjC_kArrayCountInArg) {
2940					count = extract_count(
2941							methinfo->argtype[methinfo->argtype[i].arrayArg].type,
2942							values[methinfo->argtype[i].arrayArg]);
2943					if (count == -1 && PyErr_Occurred()) {
2944						return -1;
2945					}
2946					if (argument && (PyObject_AsWriteBuffer(argument, &buffer, &bufferlen) != -1)) {
2947						byref_attr[i].token = PyObjC_PythonToCArray(
2948							YES, YES,
2949							resttype,
2950							argument,
2951							byref + i,
2952							&count,
2953							&byref_attr[i].buffer);
2954						if (byref_attr[i].token == -1) {
2955							return -1;
2956						}
2957					} else {
2958						PyErr_Clear();
2959
2960						byref[i] = PyMem_Malloc(count * PyObjCRT_SizeOfType(resttype));
2961						if (byref[i] == NULL) {
2962							PyErr_NoMemory();
2963							return -1;
2964						} else {
2965							memset(byref[i], 0, count * PyObjCRT_SizeOfType(resttype));
2966						}
2967					}
2968				}
2969
2970				arglist[i] = &ffi_type_pointer;
2971				values[i] = byref + i;
2972
2973			} else {
2974				/* Encode argument, maybe after allocating space */
2975				if (argtype[0] == _C_OUT) argtype ++;
2976
2977				argument = PyTuple_GET_ITEM (args, py_arg);
2978				py_arg ++;
2979
2980				switch (*argtype) {
2981				case _C_INOUT:
2982				case _C_IN:
2983				case _C_CONST:
2984					if (argtype[1] == _C_PTR || argtype[1] == _C_CHARPTR) {
2985						/* Allocate space and encode */
2986						const char* resttype = argtype+2;
2987						if (argtype[1] == _C_CHARPTR) {
2988							resttype = gCharEncoding;
2989						}
2990
2991						if (argument != PyObjC_NULL) {
2992							switch (methinfo->argtype[i].ptrType) {
2993							case PyObjC_kPointerPlain:
2994							case PyObjC_kNullTerminatedArray:
2995							case PyObjC_kFixedLengthArray:
2996							case PyObjC_kVariableLengthArray:
2997								/* To keep the compiler happy */
2998								break;
2999
3000							case PyObjC_kArrayCountInArg:
3001								count = extract_count(
3002										methinfo->argtype[methinfo->argtype[i].arrayArg].type,
3003										values[methinfo->argtype[i].arrayArg]);
3004								if (count == -1 && PyErr_Occurred()) {
3005									return -1;
3006								}
3007
3008								byref_attr[i].token = PyObjC_PythonToCArray(
3009									argtype[0] == _C_INOUT, NO,
3010									resttype,
3011									argument,
3012									byref + i,
3013									&count,
3014									&byref_attr[i].buffer);
3015								if (byref_attr[i].token == -1) {
3016									return -1;
3017								}
3018
3019								arglist[i] = &ffi_type_pointer;
3020								values[i] = byref + i;
3021								break;
3022							}
3023						}
3024					}
3025					break;
3026
3027				case _C_CHARPTR:
3028					if (argument != PyObjC_NULL) {
3029						switch (methinfo->argtype[i].ptrType) {
3030						case PyObjC_kPointerPlain:
3031						case PyObjC_kNullTerminatedArray:
3032						case PyObjC_kFixedLengthArray:
3033						case PyObjC_kVariableLengthArray:
3034							/* To keep the compiler happy */
3035							break;
3036
3037						case PyObjC_kArrayCountInArg:
3038							count = extract_count(
3039									methinfo->argtype[methinfo->argtype[i].arrayArg].type,
3040									values[methinfo->argtype[i].arrayArg]);
3041							if (count == -1 && PyErr_Occurred()) {
3042								return -1;
3043							}
3044							byref_attr[i].token = PyObjC_PythonToCArray(
3045									NO, NO,
3046									gCharEncoding,
3047									argument,
3048									byref + i,
3049									&count,
3050									&byref_attr[i].buffer);
3051							if (byref_attr[i].token == -1) {
3052								return -1;
3053							}
3054							arglist[i] = &ffi_type_pointer;
3055							values[i] = byref + i;
3056						}
3057					}
3058				}
3059			}
3060		}
3061	}
3062
3063	if (printf_format) {
3064		int r;
3065
3066		r = parse_printf_args(
3067			printf_format,
3068			args, py_arg,
3069			byref, byref_attr,
3070			arglist, values,
3071			methinfo->ob_size);
3072		if (r == -1) {
3073			return -1;
3074		}
3075		Py_DECREF(printf_format);
3076		printf_format = NULL;
3077
3078		return r;
3079	} else if (methinfo->variadic && methinfo->null_terminated_array) {
3080		int r;
3081
3082		r = parse_varargs_array(
3083				methinfo,
3084				args, py_arg, byref,
3085				arglist, values, -1);
3086		if (r == -1) {
3087			return -1;
3088		}
3089		return r;
3090	} else if (methinfo->variadic && methinfo->arrayArg != -1) {
3091		int r;
3092		Py_ssize_t cnt = extract_count(
3093			methinfo->argtype[methinfo->arrayArg].type,
3094			values[methinfo->arrayArg]);
3095		if (cnt == -1) {
3096			return -1;
3097		}
3098
3099		r = parse_varargs_array(
3100				methinfo,
3101				args, py_arg, byref,
3102				arglist, values, cnt);
3103		if (r == -1) {
3104			return -1;
3105		}
3106		return r;
3107	}
3108
3109	return methinfo->ob_size;
3110}
3111
3112
3113PyObject*
3114PyObjCFFI_BuildResult(
3115	PyObjCMethodSignature* methinfo, Py_ssize_t argOffset,
3116	void* pRetval, void** byref, struct byref_attr* byref_attr,
3117	Py_ssize_t byref_out_count, PyObject* self, int flags,
3118	void** argvalues)
3119{
3120	PyObject* objc_result = NULL;
3121	PyObject* result = NULL;
3122	int py_arg;
3123	void* arg;
3124	Py_ssize_t i;
3125	Py_ssize_t count;
3126
3127	if ( (*methinfo->rettype.type != _C_VOID) /* && (![methinfo isOneway]) */ ) {
3128		const char* tp = methinfo->rettype.type;
3129		BOOL isOut = NO;
3130
3131		if (tp[0] == _C_CONST) {
3132			tp++;
3133		}
3134
3135		if (tp[0] == _C_OUT) {
3136			isOut = YES;
3137			tp++;
3138		}
3139
3140		/* Pointer values: */
3141		if (tp[0] == _C_PTR && tp[1] == _C_UNDEF && methinfo->rettype.callable) {
3142			if (*(void**)pRetval == NULL) {
3143				objc_result = Py_None;
3144				Py_INCREF(Py_None);
3145			} else {
3146				objc_result = PyObjCFunc_WithMethodSignature(NULL, *(void**)pRetval, methinfo->rettype.callable);
3147				if (objc_result == NULL) {
3148					return NULL;
3149				}
3150			}
3151
3152		} else if (*tp == _C_CHARPTR || (*tp == _C_PTR && !PyObjCPointerWrapper_HaveWrapper(tp))) {
3153			const char* resttype = tp + 1;
3154			if (*tp == _C_CHARPTR) {
3155				resttype = gCharEncoding;
3156			}
3157
3158			if (isOut) {
3159				objc_result = pythonify_c_return_value (resttype, *(void**)pRetval);
3160				if (objc_result == NULL) {
3161					return NULL;
3162				}
3163
3164				if (methinfo->rettype.alreadyRetained) {
3165					if (PyObjCObject_Check(objc_result)) {
3166						/* pythonify_c_return_value has retained the object, but we already
3167						 * own a reference, therefore give the ref away again
3168						 */
3169						[PyObjCObject_GetObject(objc_result) release];
3170					}
3171				}
3172				if (methinfo->rettype.alreadyCFRetained) {
3173					if (PyObjCObject_Check(objc_result)) {
3174						/* pythonify_c_return_value has retained the object, but we already
3175						 * own a reference, therefore give the ref away again
3176						 */
3177						CFRelease(PyObjCObject_GetObject(objc_result));
3178					}
3179				}
3180
3181
3182			} else {
3183
3184				switch (methinfo->rettype.ptrType) {
3185				case PyObjC_kPointerPlain:
3186					/* Fall through to default behaviour */
3187					break;
3188				case PyObjC_kNullTerminatedArray:
3189					if (*(void**)pRetval == NULL) {
3190						Py_INCREF(PyObjC_NULL);
3191						objc_result = PyObjC_NULL;
3192					} else {
3193						objc_result = pythonify_c_array_nullterminated(resttype, *(void**)pRetval, methinfo->rettype.alreadyRetained, methinfo->rettype.alreadyCFRetained);
3194						if (objc_result == NULL) {
3195							return NULL;
3196						}
3197					}
3198					break;
3199
3200				case PyObjC_kFixedLengthArray:
3201					if (*(void**)pRetval == NULL) {
3202						Py_INCREF(PyObjC_NULL);
3203						objc_result = PyObjC_NULL;
3204
3205					} else {
3206						objc_result = PyObjC_CArrayToPython2(
3207							resttype,
3208							*(void**)pRetval,
3209							methinfo->rettype.arrayArg, methinfo->rettype.alreadyRetained, methinfo->rettype.alreadyCFRetained);
3210						if (objc_result == NULL) {
3211							return NULL;
3212						}
3213					}
3214					break;
3215
3216				case PyObjC_kVariableLengthArray:
3217					/* FIXME: explict support for UniChar buffers */
3218					if (*(void**)pRetval == NULL) {
3219						Py_INCREF(PyObjC_NULL);
3220						objc_result = PyObjC_NULL;
3221					} else {
3222						objc_result = PyObjC_VarList_New(resttype, *(void**)pRetval);
3223					}
3224					break;
3225
3226				case PyObjC_kArrayCountInArg:
3227
3228					if (*(void**)pRetval == NULL) {
3229						Py_INCREF(PyObjC_NULL);
3230						objc_result = PyObjC_NULL;
3231					} else {
3232						count = extract_count(methinfo->argtype[methinfo->rettype.arrayArg].type, argvalues[methinfo->rettype.arrayArg]);
3233						if (count == -1 && PyErr_Occurred()) {
3234								return NULL;
3235						}
3236
3237						objc_result = PyObjC_CArrayToPython2(
3238							resttype,
3239							*(void**)pRetval,
3240							count, methinfo->rettype.alreadyRetained, methinfo->rettype.alreadyCFRetained);
3241
3242						if (objc_result == NULL) {
3243							return NULL;
3244						}
3245					}
3246					break;
3247
3248				default:
3249					PyErr_Format(PyExc_SystemError,
3250						"Unhandled pointer type: %d",
3251						methinfo->rettype.ptrType);
3252					return NULL;
3253				}
3254
3255				if (methinfo->free_result) {
3256					free(*(void**)pRetval);
3257				}
3258
3259			}
3260	 	}
3261
3262		/* default behaviour: */
3263		if (objc_result == NULL) {
3264			if (tp[0] == _C_ID && tp[1] == '?') {
3265				/* The value is a block, those values are
3266				 * treated slightly differently than normal:
3267				 * - always use -copy on them to ensure we
3268				 *   can safely store them.
3269				 * - try to attach the calling signature to the
3270				 *   block.
3271				 */
3272				id v = [*(id*)pRetval copy];
3273				objc_result = pythonify_c_return_value (tp, &v);
3274				[v release];
3275				if (objc_result == NULL) {
3276					return NULL;
3277				}
3278
3279				if (methinfo->rettype.callable != NULL) {
3280					if (PyObjCObject_IsBlock(objc_result) && PyObjCObject_GetBlock(objc_result) == NULL) {
3281						PyObjCObject_SET_BLOCK(objc_result, methinfo->rettype.callable);
3282						Py_INCREF(methinfo->rettype.callable);
3283					}
3284				}
3285
3286			} else {
3287
3288				objc_result = pythonify_c_return_value (tp, pRetval);
3289				if (objc_result == NULL) {
3290					return NULL;
3291				}
3292
3293			}
3294
3295			if (methinfo->rettype.alreadyRetained) {
3296				if (PyObjCObject_Check(objc_result)) {
3297					/* pythonify_c_return_value has retained the object, but we already
3298					 * own a reference, therefore give the ref away again
3299					 */
3300					[PyObjCObject_GetObject(objc_result) release];
3301				}
3302			}
3303			if (methinfo->rettype.alreadyCFRetained) {
3304				if (PyObjCObject_Check(objc_result)) {
3305					/* pythonify_c_return_value has retained the object, but we already
3306					 * own a reference, therefore give the ref away again
3307					 */
3308					CFRelease(PyObjCObject_GetObject(objc_result));
3309				}
3310			}
3311		}
3312	} else {
3313		Py_INCREF(Py_None);
3314		objc_result =  Py_None;
3315	}
3316
3317	/* XXX: This is for selectors only, need to change this !!!! */
3318
3319	if (self != NULL && objc_result != self
3320		&& PyObjCObject_Check(self) && PyObjCObject_Check(objc_result)
3321		&& !(flags & PyObjCSelector_kRETURNS_UNINITIALIZED)
3322		&& (((PyObjCObject*)self)->flags & PyObjCObject_kUNINITIALIZED)) {
3323		[PyObjCObject_GetObject(objc_result) release];
3324		PyObjCObject_ClearObject(self);
3325	}
3326
3327	if (byref_out_count == 0) {
3328		return objc_result;
3329
3330	} else {
3331
3332		if (*methinfo->rettype.type == _C_VOID) {
3333			if (byref_out_count > 1) {
3334				result = PyTuple_New(byref_out_count);
3335				if (result == NULL) {
3336					return NULL;
3337				}
3338			} else {
3339				result = NULL;
3340			}
3341			Py_DECREF(objc_result);
3342			py_arg = 0;
3343		} else {
3344			result = PyTuple_New(byref_out_count+1);
3345			if (result == NULL) {
3346				return NULL;
3347			}
3348			PyTuple_SET_ITEM(result, 0, objc_result);
3349			py_arg = 1;
3350		}
3351		objc_result = NULL;
3352
3353		for (i = argOffset; i < methinfo->ob_size; i++) {
3354			const char *argtype = methinfo->argtype[i].type;
3355			PyObject*   v = NULL;
3356
3357			switch (*argtype) {
3358			case _C_INOUT:
3359			case _C_OUT:
3360				if (argtype[1] == _C_CHARPTR || (argtype[1] == _C_PTR && !PyObjCPointerWrapper_HaveWrapper(argtype+1))) {
3361					const char* resttype = argtype+2;
3362					if (argtype[1] == _C_CHARPTR) {
3363						resttype = gCharEncoding;
3364					}
3365
3366					arg = byref[i];
3367
3368					if (arg == NULL) {
3369						v = PyObjC_NULL;
3370						Py_INCREF(v);
3371
3372					} else if (byref_attr[i].buffer != NULL) {
3373						v = byref_attr[i].buffer;
3374						Py_INCREF(v);
3375
3376					} else {
3377						switch (methinfo->argtype[i].ptrType) {
3378						case PyObjC_kPointerPlain:
3379
3380							if (resttype[0] == _C_ID && resttype[1] == '?') {
3381								id tmp = [*(id*)arg copy];
3382								v = pythonify_c_value(resttype, &tmp);
3383								[tmp release];
3384
3385								if (methinfo->argtype[i].callable != NULL) {
3386									if (PyObjCObject_IsBlock(v) && PyObjCObject_GetBlock(v) == NULL) {
3387										PyObjCObject_SET_BLOCK(v, methinfo->argtype[i].callable);
3388										Py_INCREF(methinfo->argtype[i].callable);
3389									}
3390								}
3391							} else {
3392								v = pythonify_c_value(resttype, arg);
3393							}
3394							if (methinfo->argtype[i].alreadyRetained && PyObjCObject_Check(v)) {
3395								[PyObjCObject_GetObject(v) release];
3396							}
3397							if (methinfo->argtype[i].alreadyCFRetained && PyObjCObject_Check(v)) {
3398								CFRelease(PyObjCObject_GetObject(v));
3399							}
3400							if (!v) goto error_cleanup;
3401							break;
3402
3403						case PyObjC_kFixedLengthArray:
3404							if (methinfo->argtype[i].arraySizeInRetval) {
3405								count = extract_count(methinfo->rettype.type, pRetval);
3406								if (count == -1 && PyErr_Occurred()) goto error_cleanup;
3407
3408							} else {
3409								count = methinfo->argtype[i].arrayArg;
3410							}
3411
3412							if (*resttype == _C_UNICHAR) {
3413								v = PyUnicode_FromUnicode(NULL, count);
3414								if (!v) goto error_cleanup;
3415
3416								Py_ssize_t j;
3417								Py_UNICODE* buffer = PyUnicode_AsUnicode(v);
3418								for (j = 0; j < count; j++) {
3419									buffer[j] = ((UniChar*)arg)[j];
3420								}
3421
3422							} else {
3423								v = PyObjC_CArrayToPython2(resttype,
3424									arg,
3425									count, methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
3426								if (!v) goto error_cleanup;
3427							}
3428							break;
3429
3430						case PyObjC_kVariableLengthArray:
3431							 /* TODO: add support for UniChar arrays */
3432							if (methinfo->argtype[i].arraySizeInRetval) {
3433								count = extract_count(methinfo->rettype.type, pRetval);
3434								if (count == -1 && PyErr_Occurred()) goto error_cleanup;
3435
3436								v = PyObjC_CArrayToPython2(resttype,
3437									arg,
3438									count, methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
3439								if (!v) goto error_cleanup;
3440
3441							} else {
3442								v = PyObjC_VarList_New(methinfo->rettype.type, pRetval);
3443								if (!v) goto error_cleanup;
3444							}
3445
3446							break;
3447
3448						case PyObjC_kNullTerminatedArray:
3449							 /* TODO: add support for UniChar arrays */
3450							v = pythonify_c_array_nullterminated(
3451								resttype, arg, methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
3452							if (!v) goto error_cleanup;
3453							break;
3454
3455						case PyObjC_kArrayCountInArg:
3456							if (methinfo->argtype[i].arraySizeInRetval) {
3457								count = extract_count(methinfo->rettype.type, pRetval);
3458
3459							} else {
3460								count = extract_count(
3461									methinfo->argtype[methinfo->argtype[i].arrayArgOut].type,
3462									argvalues[methinfo->argtype[i].arrayArgOut]);
3463							}
3464							if (count == -1 && PyErr_Occurred()) goto error_cleanup;
3465
3466							if (*resttype == _C_UNICHAR) {
3467								v = PyUnicode_FromUnicode(NULL, count);
3468								if (!v) goto error_cleanup;
3469
3470								Py_ssize_t j;
3471								Py_UNICODE* buffer = PyUnicode_AsUnicode(v);
3472								for (j = 0; j < count; j++) {
3473									buffer[j] = ((UniChar*)arg)[j];
3474								}
3475
3476							} else {
3477								v = PyObjC_CArrayToPython2(
3478									resttype,
3479									arg,
3480									count, methinfo->argtype[i].alreadyRetained, methinfo->argtype[i].alreadyCFRetained);
3481							}
3482
3483							if (v == NULL) goto error_cleanup;
3484							break;
3485						}
3486					}
3487
3488					if (result != NULL) {
3489						if (PyTuple_SetItem(result,
3490							py_arg++, v) < 0) {
3491
3492							Py_DECREF(v);
3493							goto error_cleanup;
3494						}
3495					} else {
3496						result = v;
3497					}
3498
3499				}
3500				break;
3501			}
3502		}
3503	}
3504
3505	return result;
3506
3507error_cleanup:
3508	Py_XDECREF(result);
3509	return NULL;
3510}
3511
3512int PyObjCFFI_AllocByRef(int argcount, void*** byref, struct byref_attr** byref_attr)
3513{
3514	*byref = NULL; *byref_attr = NULL;
3515
3516	*byref = PyMem_Malloc(sizeof(void*) * argcount);
3517	if (*byref == NULL) {
3518		PyErr_NoMemory();
3519		return -1;
3520	}
3521	memset(*byref, 0, sizeof(void*) * argcount);
3522
3523	*byref_attr = PyMem_Malloc(sizeof(struct byref_attr) * argcount);
3524	if (*byref_attr == NULL) {
3525		free(*byref);
3526		*byref = NULL;
3527
3528		PyErr_NoMemory();
3529		return -1;
3530	}
3531	memset(*byref_attr, 0, sizeof(struct byref_attr) * argcount);
3532
3533	return 0;
3534}
3535
3536int PyObjCFFI_FreeByRef(int argcount, void** byref, struct byref_attr* byref_attr)
3537{
3538	Py_ssize_t i;
3539	if (byref) {
3540		for (i = 0; i < argcount; i++) {
3541			if (byref[i] == NULL) continue;
3542
3543			if (byref_attr[i].token != 0) {
3544				PyObjC_FreeCArray(byref_attr[i].token, byref[i]);
3545				byref[i] = NULL;
3546
3547				Py_XDECREF(byref_attr[i].buffer); byref_attr[i].buffer = NULL;
3548
3549			} else {
3550				PyMem_Free(byref[i]); byref[i] = NULL;
3551			}
3552		}
3553		PyMem_Free(byref);
3554	}
3555
3556	if (byref_attr) {
3557		PyMem_Free(byref_attr);
3558	}
3559
3560	return 0;
3561}
3562
3563
3564PyObject *
3565PyObjCFFI_Caller(PyObject *aMeth, PyObject* self, PyObject *args)
3566{
3567	Py_ssize_t argbuf_len = 0;
3568	Py_ssize_t argbuf_cur = 0;
3569	unsigned char* volatile argbuf = NULL;
3570	Py_ssize_t byref_in_count = 0;
3571	Py_ssize_t byref_out_count = 0;
3572	Py_ssize_t plain_count = 0;
3573	void** byref = NULL; /* offset for arguments in argbuf */
3574	struct byref_attr* byref_attr = NULL;
3575	const char* 	  rettype;
3576	PyObjCMethodSignature*  volatile methinfo;
3577	PyObjCNativeSelector* meth = (PyObjCNativeSelector*)aMeth;
3578	PyObject* objc_result = NULL;
3579	PyObject* volatile result = NULL;
3580	id		  self_obj = nil;
3581	struct objc_super super;
3582	struct objc_super* superPtr;
3583	ffi_cif		  cif;
3584	ffi_type*	  arglist[128]; /* XX: Magic constant */
3585	void*             values[128];
3586	int               r;
3587	void* volatile	  msgResult;
3588	Py_ssize_t        resultSize;
3589	volatile int      useStret;
3590	volatile int      flags;
3591	SEL		  theSel;
3592	volatile int		  isUninitialized;
3593	BOOL		  variadicAllArgs = NO;
3594
3595	if (PyObjCIMP_Check(aMeth)) {
3596		methinfo = PyObjCIMP_GetSignature(aMeth);
3597		flags = PyObjCIMP_GetFlags(aMeth);
3598	} else {
3599		methinfo = PyObjCSelector_GetMetadata(aMeth);
3600		if (methinfo == NULL) {
3601			return NULL;
3602		}
3603		flags = meth->sel_flags;
3604	}
3605	rettype = methinfo->rettype.type;
3606	variadicAllArgs = methinfo->variadic && (methinfo->null_terminated_array || methinfo->arrayArg != -1);
3607
3608	if (methinfo->suggestion != NULL) {
3609		PyErr_SetObject(PyExc_TypeError, methinfo->suggestion);
3610		return NULL;
3611	}
3612
3613	if (methinfo->ob_size >= 127) {
3614		 PyErr_Format(PyObjCExc_Error,
3615			 "wrapping a function with %"PY_FORMAT_SIZE_T"d arguments, at most 64 "
3616			 "are supported", methinfo->ob_size);
3617		 return NULL;
3618	}
3619
3620
3621	resultSize = PyObjCRT_SizeOfReturnType(rettype);
3622	if (resultSize == -1) {
3623		return NULL;
3624	}
3625
3626
3627	/* First count the number of by reference parameters, and the number
3628	 * of bytes of storage needed for them. Note that arguments 0 and 1
3629	 * are self and the selector, no need to count those.
3630	 */
3631	argbuf_len = align(resultSize, sizeof(void*));
3632	r = PyObjCFFI_CountArguments(
3633		methinfo, 2,
3634		&byref_in_count,
3635		&byref_out_count,
3636		&plain_count,
3637		&argbuf_len,
3638		&variadicAllArgs);
3639	if (r == -1) {
3640		return NULL;
3641	}
3642
3643
3644	/*
3645	 * We need input arguments for every normal argument and for every
3646	 * input argument that is passed by reference.
3647	 */
3648	if (variadicAllArgs) {
3649		if (byref_in_count != 0 || byref_out_count != 0) {
3650			PyErr_Format(PyExc_TypeError, "Sorry, printf format with by-ref args not supported");
3651			goto error_cleanup;
3652		}
3653		if (methinfo->null_terminated_array) {
3654			if (PyTuple_Size(args) < methinfo->ob_size - 3) {
3655				PyErr_Format(PyExc_TypeError,
3656					"Need %"PY_FORMAT_SIZE_T"d arguments, got %"PY_FORMAT_SIZE_T"d",
3657					methinfo->ob_size - 3,
3658					PyTuple_Size(args));
3659				goto error_cleanup;
3660			}
3661		} else if (PyTuple_Size(args) < methinfo->ob_size - 2) {
3662			PyErr_Format(PyExc_TypeError, "Need %"PY_FORMAT_SIZE_T"d arguments, got %"PY_FORMAT_SIZE_T"d",
3663			methinfo->ob_size - 2, PyTuple_Size(args));
3664			goto error_cleanup;
3665		}
3666
3667		if (PyTuple_Size(args) > 127) {
3668			PyErr_Format(PyExc_TypeError, "At most %d arguments are supported, got %" PY_FORMAT_SIZE_T "d arguments", 127, PyTuple_Size(args));
3669			goto error_cleanup;
3670		}
3671
3672	} else if (PyTuple_Size(args) != methinfo->ob_size - 2) {
3673
3674		PyErr_Format(PyExc_TypeError, "Need %"PY_FORMAT_SIZE_T"d arguments, got %"PY_FORMAT_SIZE_T"d",
3675			methinfo->ob_size - 2, PyTuple_Size(args));
3676		goto error_cleanup;
3677	}
3678
3679
3680	argbuf = PyMem_Malloc(argbuf_len);
3681	if (argbuf == 0) {
3682		PyErr_NoMemory();
3683		goto error_cleanup;
3684	}
3685
3686	if (variadicAllArgs) {
3687		if (PyObjCFFI_AllocByRef(methinfo->ob_size+PyTuple_Size(args),
3688					&byref, &byref_attr) < 0) {
3689			goto error_cleanup;
3690		}
3691	} else {
3692		if (PyObjCFFI_AllocByRef(methinfo->ob_size, &byref, &byref_attr) < 0) {
3693			goto error_cleanup;
3694		}
3695	}
3696
3697	/* Set 'self' argument, for class methods we use the class */
3698	if (flags & PyObjCSelector_kCLASS_METHOD) {
3699		if (PyObjCObject_Check(self)) {
3700			self_obj = PyObjCObject_GetObject(self);
3701			if (self_obj != NULL) {
3702				self_obj = object_getClass(self_obj);
3703			}
3704		} else if (PyObjCClass_Check(self)) {
3705			self_obj = PyObjCClass_GetClass(self);
3706
3707
3708		} else if (PyType_Check(self) && PyType_IsSubtype((PyTypeObject*)self, &PyType_Type)) {
3709			PyObject* c = PyObjCClass_ClassForMetaClass(self);
3710			if (c == NULL) {
3711				self_obj = nil;
3712
3713			} else {
3714				self_obj = PyObjCClass_GetClass(c);
3715			}
3716
3717		} else {
3718			PyErr_Format(PyExc_TypeError,
3719				"Need objective-C object or class as self, not an instance of '%s'", self->ob_type->tp_name);
3720			goto error_cleanup;
3721		}
3722	} else {
3723		int err;
3724		if (PyObjCObject_Check(self)) {
3725			self_obj = PyObjCObject_GetObject(self);
3726		} else {
3727			err = depythonify_c_value(@encode(id), self, &self_obj);
3728			if (err == -1) {
3729				goto error_cleanup;
3730			}
3731		}
3732	}
3733	/* XXX: Ronald: why the XXX? */
3734
3735	useStret = 0;
3736
3737	if (PyObjCIMP_Check(aMeth)) {
3738		useStret = 0;
3739		theSel = PyObjCIMP_GetSelector(aMeth);
3740		arglist[0] = &ffi_type_pointer;
3741		values[0] = &self_obj;
3742		arglist[1] = &ffi_type_pointer;
3743		values[1] = &theSel;
3744		msgResult = argbuf;
3745		argbuf_cur = align(resultSize, sizeof(void*));
3746
3747	} else {
3748		objc_superSetReceiver(super, self_obj);
3749		if (meth->sel_flags & PyObjCSelector_kCLASS_METHOD) {
3750			objc_superSetClass(super,
3751					object_getClass(meth->sel_class));
3752		} else {
3753			objc_superSetClass(super,  meth->sel_class);
3754		}
3755
3756		useStret = 0;
3757		if (*rettype == _C_STRUCT_B &&
3758#ifdef  __ppc64__
3759			ffi64_stret_needs_ptr(signature_to_ffi_return_type(rettype), NULL, NULL)
3760
3761#else /* !__ppc64__ */
3762			(resultSize > SMALL_STRUCT_LIMIT
3763#ifdef __i386__
3764			 /* darwin/x86 ABI is slightly odd ;-) */
3765			 || (resultSize != 1
3766				&& resultSize != 2
3767				&& resultSize != 4
3768				&& resultSize != 8)
3769#endif
3770#ifdef __x86_64__
3771			 /* darwin/x86-64 ABI is slightly odd ;-) */
3772			 || (resultSize != 1
3773				&& resultSize != 2
3774				&& resultSize != 4
3775				&& resultSize != 8
3776				&& resultSize != 16
3777				)
3778#endif
3779			)
3780#endif /* !__ppc64__ */
3781			) {
3782
3783			useStret = 1;
3784		}
3785		superPtr = &super;
3786		arglist[ 0] = &ffi_type_pointer;
3787		values[ 0] = &superPtr;
3788		arglist[ 1] = &ffi_type_pointer;
3789		values[ 1] = &meth->sel_selector;
3790		theSel = meth->sel_selector;
3791		msgResult = argbuf;
3792		argbuf_cur = align(resultSize, sizeof(void*));
3793	}
3794
3795	r = PyObjCFFI_ParseArguments(methinfo, 2, args,
3796		argbuf_cur, argbuf, argbuf_len, byref, byref_attr,
3797		arglist, values);
3798	if (r == -1) {
3799		goto error_cleanup;
3800	}
3801
3802
3803	PyErr_Clear();
3804	ffi_type* retsig = signature_to_ffi_return_type(rettype);
3805	if (retsig == NULL) goto error_cleanup;
3806	r = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, r, retsig, arglist);
3807	if (r != FFI_OK) {
3808		PyErr_Format(PyExc_RuntimeError,
3809			"Cannot setup FFI CIF [%d]", r);
3810		goto error_cleanup;
3811	}
3812
3813	if (PyObjCObject_Check(self)) {
3814		isUninitialized = ((PyObjCObject*)self)->flags  & PyObjCObject_kUNINITIALIZED;
3815		((PyObjCObject*)self)->flags  &= ~PyObjCObject_kUNINITIALIZED;
3816	} else {
3817		isUninitialized = NO;
3818        }
3819
3820	if (methinfo->ob_size >= 3) {
3821	}
3822
3823	PyObjC_DURING
3824		if (PyObjCIMP_Check(aMeth)) {
3825			ffi_call(&cif, FFI_FN(PyObjCIMP_GetIMP(aMeth)),
3826				msgResult, values);
3827
3828		} else {
3829			if (useStret) {
3830				ffi_call(&cif, FFI_FN(objc_msgSendSuper_stret),
3831					msgResult, values);
3832			} else {
3833				ffi_call(&cif, FFI_FN(objc_msgSendSuper),
3834					msgResult, values);
3835
3836			}
3837		}
3838
3839	PyObjC_HANDLER
3840		PyObjCErr_FromObjC(localException);
3841
3842	PyObjC_ENDHANDLER
3843#if 1
3844	if (isUninitialized && PyObjCObject_Check(self)) {
3845		((PyObjCObject*)self)->flags  |= PyObjCObject_kUNINITIALIZED;
3846	}
3847#endif
3848
3849	if (PyErr_Occurred()) goto error_cleanup;
3850
3851	if (methinfo->ob_size >= 3) {
3852	}
3853
3854	result = PyObjCFFI_BuildResult(methinfo, 2, msgResult, byref,
3855			byref_attr, byref_out_count,
3856			self, flags, values);
3857
3858	if (variadicAllArgs) {
3859		if (PyObjCFFI_FreeByRef(methinfo->ob_size+PyTuple_Size(args), byref, byref_attr) < 0) {
3860			byref = NULL; byref_attr = NULL;
3861			goto error_cleanup;
3862		}
3863	} else {
3864		if (PyObjCFFI_FreeByRef(methinfo->ob_size, byref, byref_attr) < 0) {
3865			byref = NULL; byref_attr = NULL;
3866			goto error_cleanup;
3867		}
3868	}
3869	PyMem_Free(argbuf); argbuf = NULL;
3870	methinfo = NULL;
3871
3872	return result;
3873
3874error_cleanup:
3875
3876	if (objc_result) {
3877		Py_DECREF(objc_result);
3878		objc_result = NULL;
3879	}
3880	if (result) {
3881		Py_DECREF(result);
3882		result = NULL;
3883	}
3884	if (variadicAllArgs) {
3885		if (PyObjCFFI_FreeByRef(PyTuple_Size(args), byref, byref_attr) < 0) {
3886			byref = NULL; byref_attr = NULL;
3887			goto error_cleanup;
3888		}
3889	} else {
3890		if (PyObjCFFI_FreeByRef(methinfo->ob_size, byref, byref_attr) < 0) {
3891			byref = NULL; byref_attr = NULL;
3892			goto error_cleanup;
3893		}
3894	}
3895	if (argbuf) {
3896		PyMem_Free(argbuf);
3897		argbuf = NULL;
3898	}
3899	return NULL;
3900}
3901
3902/*
3903 * PyObjCFFI_CIFForSignature - Create CIF for a method signature
3904 *
3905 * return the CIF, return NULL on error. pArgOffset is set to 1 if the method
3906 * should be called using objc_sendMsg_sret (using a pointer to the return value
3907 * as an initial argument), and is set to 0 otherwise.
3908 */
3909ffi_cif*
3910PyObjCFFI_CIFForSignature(PyObjCMethodSignature* methinfo)
3911{
3912	ffi_cif* cif;
3913	ffi_type** cl_arg_types;
3914	ffi_type* cl_ret_type;
3915	const char* rettype;
3916	ffi_status rv;
3917	int i;
3918
3919	rettype = methinfo->rettype.type;
3920
3921	cl_ret_type = signature_to_ffi_return_type(rettype);
3922	if (cl_ret_type == NULL) {
3923		return NULL;
3924	}
3925
3926	/* Build FFI argumentlist description */
3927	cl_arg_types = PyMem_Malloc(sizeof(ffi_type*) * (2 + methinfo->ob_size));
3928	if (cl_arg_types == NULL) {
3929		PyMem_Free(cl_ret_type);
3930		PyErr_NoMemory();
3931		return NULL;
3932	}
3933
3934	for (i = 0; i < methinfo->ob_size; i++) {
3935		cl_arg_types[i] = arg_signature_to_ffi_type(
3936			methinfo->argtype[i].type);
3937		if (cl_arg_types[i] == NULL) {
3938			PyMem_Free(cl_arg_types);
3939			return NULL;
3940		}
3941	}
3942
3943	/* Create the invocation description */
3944	cif = PyMem_Malloc(sizeof(*cif));
3945	if (cif == NULL) {
3946		PyMem_Free(cl_arg_types);
3947		PyErr_NoMemory();
3948		return NULL;
3949	}
3950
3951	rv = ffi_prep_cif(cif, FFI_DEFAULT_ABI, methinfo->ob_size,
3952		cl_ret_type, cl_arg_types);
3953
3954	if (rv != FFI_OK) {
3955		PyMem_Free(cl_arg_types);
3956		PyErr_Format(PyExc_RuntimeError,
3957			"Cannot create FFI CIF: %d", rv);
3958		return NULL;
3959	}
3960
3961	return cif;
3962}
3963
3964/*
3965 * PyObjCFFI_FreeCIF - Free the CIF created by PyObjCFFI_CIFForSignature
3966 */
3967void
3968PyObjCFFI_FreeCIF(ffi_cif* cif)
3969{
3970	if (cif->arg_types) PyMem_Free(cif->arg_types);
3971	PyMem_Free(cif);
3972}
3973
3974/*
3975 * PyObjCFFI_MakeClosure - Create a closure for an Objective-C method
3976 *
3977 * Return the closure, or NULL. The 'func' will be called with a CIF object,
3978 * a pointer to the return value, the argument array and the 'userdata'.
3979 */
3980IMP
3981PyObjCFFI_MakeClosure(
3982	PyObjCMethodSignature* methinfo,
3983	PyObjCFFI_ClosureFunc func,
3984	void* userdata)
3985{
3986	ffi_cif *cif;
3987	ffi_closure *cl;
3988	ffi_status rv;
3989
3990	cif = PyObjCFFI_CIFForSignature(methinfo);
3991	if (cif == NULL) {
3992		return NULL;
3993	}
3994
3995
3996	/* And finally create the actual closure */
3997	/*cl = PyMem_Malloc(sizeof(*cl));*/
3998	cl = PyObjC_malloc_closure();
3999	if (cl == NULL) {
4000		PyObjCFFI_FreeCIF(cif);
4001		/*PyErr_NoMemory();*/
4002		return NULL;
4003	}
4004
4005	rv = ffi_prep_closure(cl, cif, func, userdata);
4006	if (rv != FFI_OK) {
4007		PyObjCFFI_FreeCIF(cif);
4008		PyErr_Format(PyExc_RuntimeError,
4009			"Cannot create FFI closure: %d", rv);
4010		return NULL;
4011	}
4012
4013	return (IMP)cl;
4014}
4015
4016/*
4017 * PyObjCFFI_FreeClosure - Free the closure created by PyObjCFFI_MakeClosure
4018 *
4019 * Returns the userdata.
4020 */
4021void*
4022PyObjCFFI_FreeClosure(IMP closure)
4023{
4024	void* retval;
4025	ffi_closure* cl;
4026
4027	cl = (ffi_closure*)closure;
4028	retval = cl->user_data;
4029	PyObjCFFI_FreeCIF(cl->cif);
4030	PyObjC_free_closure(cl); /* XXX: error handling */
4031
4032	return retval;
4033}
4034