1/* Copyright (c) 1996,97,98 by Lele Gaifax.  All Rights Reserved
2 * Copyright (c) 2002-2008 Ronald Oussoren
3 *
4 * This software may be used and distributed freely for any purpose
5 * provided that this notice is included unchanged on any and all
6 * copies. The author does not warrant or guarantee this software in
7 * any way.
8 *
9 * This file is part of the PyObjC package.
10 *
11 * RCSfile: objc_support.m,v
12 * Revision: 1.24
13 * Date: 1998/08/18 15:35:58
14 *
15 * Created Tue Sep 10 14:16:02 1996.
16 */
17
18#include "pyobjc.h"
19#include <objc/Protocol.h>
20
21#include <unistd.h>
22#include <sys/socket.h>
23#include <netinet/in.h>
24
25#import <Foundation/NSInvocation.h>
26#import <Foundation/NSData.h>
27#import <Foundation/NSValue.h>
28#import <Foundation/NSDecimalNumber.h>
29
30#include <CoreFoundation/CFNumber.h>
31
32/*
33 * Category on NSObject to make sure that every object supports
34 * the method  __pyobjc_PythonObject__, this helps to simplify
35 * pythonify_c_value.
36 */
37@interface NSObject (PyObjCSupport)
38-(PyObject*)__pyobjc_PythonObject__;
39+(PyObject*)__pyobjc_PythonObject__;
40
41-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie;
42+(PyObject*)__pyobjc_PythonTransient__:(int*)cookie;
43@end /* PyObjCSupport */
44
45@implementation NSObject (PyObjCSupport)
46
47-(PyObject*)__pyobjc_PythonObject__
48{
49	PyObject *rval;
50
51	rval = PyObjC_FindPythonProxy(self);
52	if (rval == NULL) {
53		rval = (PyObject *)PyObjCObject_New(self,
54				PyObjCObject_kDEFAULT, YES);
55		PyObjC_RegisterPythonProxy(self, rval);
56	}
57
58	return rval;
59}
60
61+(PyObject*)__pyobjc_PythonObject__
62{
63	PyObject *rval;
64
65	//rval = PyObjC_FindPythonProxy(self);
66	rval = NULL;
67	if (rval == NULL) {
68		rval = (PyObject *)PyObjCClass_New(self);
69		//PyObjC_RegisterPythonProxy(self, rval);
70	}
71
72	return rval;
73}
74
75-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie
76{
77	PyObject* result = PyObjC_FindPythonProxy(self);
78	if (result) {
79		*cookie = 0;
80		return result;
81	}
82
83	*cookie = 1;
84	return PyObjCObject_New(self, PyObjCObject_kSHOULD_NOT_RELEASE, NO);
85}
86
87+(PyObject*)__pyobjc_PythonTransient__:(int*)cookie
88{
89	*cookie = 0;
90	return (PyObject *)PyObjCClass_New(self);
91}
92
93@end /* PyObjCSupport */
94
95@interface NSProxy (PyObjCSupport)
96-(PyObject*)__pyobjc_PythonObject__;
97+(PyObject*)__pyobjc_PythonObject__;
98
99-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie;
100+(PyObject*)__pyobjc_PythonTransient__:(int*)cookie;
101@end /* PyObjCSupport */
102
103@implementation NSProxy (PyObjCSupport)
104
105-(PyObject*)__pyobjc_PythonObject__
106{
107	PyObject *rval;
108
109	rval = PyObjC_FindPythonProxy(self);
110	if (rval == NULL) {
111		rval = (PyObject *)PyObjCObject_New(self,
112				PyObjCObject_kDEFAULT, YES);
113		PyObjC_RegisterPythonProxy(self, rval);
114	}
115	return rval;
116}
117
118+(PyObject*)__pyobjc_PythonObject__
119{
120	PyObject *rval;
121
122	rval = NULL;
123	if (rval == NULL) {
124		rval = (PyObject *)PyObjCClass_New(self);
125	}
126	return rval;
127}
128
129-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie
130{
131	PyObject* result = PyObjC_FindPythonProxy(self);
132	if (result) {
133		*cookie = 0;
134		return result;
135	}
136
137	*cookie = 1;
138	return PyObjCObject_New(self, PyObjCObject_kSHOULD_NOT_RELEASE, NO);
139}
140
141+(PyObject*)__pyobjc_PythonTransient__:(int*)cookie
142{
143	*cookie = 0;
144	return (PyObject *)PyObjCClass_New(self);
145}
146@end /* PyObjCSupport */
147
148@interface Protocol (PyObjCSupport)
149-(PyObject*)__pyobjc_PythonObject__;
150-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie;
151@end /* PyObjCSupport */
152
153@implementation Protocol (PyObjCSupport)
154
155-(PyObject*)__pyobjc_PythonObject__
156{
157	PyObject *rval;
158
159	rval = PyObjC_FindPythonProxy(self);
160	if (rval == NULL) {
161		rval = PyObjCFormalProtocol_ForProtocol(self);
162	}
163	return rval;
164}
165
166-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie
167{
168	PyObject *rval;
169
170	*cookie = 0;
171	rval = PyObjC_FindPythonProxy(self);
172	if (rval == NULL) {
173		rval = PyObjCFormalProtocol_ForProtocol(self);
174	}
175	return rval;
176}
177
178@end /* PyObjCSupport */
179
180@interface Object (PyObjCSupport)
181-(PyObject*)__pyobjc_PythonObject__;
182-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie;
183@end /* PyObjCSupport */
184
185@implementation Object (PyObjCSupport)
186
187-(PyObject*)__pyobjc_PythonObject__
188{
189	PyObject *rval;
190
191	rval = PyObjC_FindPythonProxy(self);
192	if (rval == NULL) {
193		rval = (PyObject *)PyObjCObject_New(self,
194				PyObjCObject_kCLASSIC, NO);
195		PyObjC_RegisterPythonProxy(self, rval);
196	}
197	return rval;
198}
199
200-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie
201{
202	PyObject *rval;
203
204	*cookie = 0;
205	rval = PyObjC_FindPythonProxy(self);
206	if (rval == NULL) {
207		rval = (PyObject *)PyObjCObject_New(self,
208				PyObjCObject_kCLASSIC, NO);
209		PyObjC_RegisterPythonProxy(self, rval);
210	}
211	return rval;
212}
213
214@end /* PyObjCSupport */
215
216@interface NSString (PyObjCSupport)
217-(PyObject*)__pyobjc_PythonObject__;
218-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie;
219@end /* NSString (PyObjCSupport) */
220
221@implementation NSString (PyObjCSupport)
222
223-(PyObject*)__pyobjc_PythonObject__
224{
225	/* Don't register the proxy, see XXX */
226	PyObject *rval = (PyObject *)PyObjCUnicode_New(self);
227	return rval;
228}
229
230-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie
231{
232	*cookie = 0;
233	return (PyObject *)PyObjCUnicode_New(self);
234}
235
236@end /* NSString (PyObjCSupport) */
237
238@interface NSNumber (PyObjCSupport)
239-(PyObject*)__pyobjc_PythonObject__;
240-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie;
241@end /* NSNumber (PyObjCSupport) */
242
243@implementation NSNumber (PyObjCSupport)
244-(PyObject*)__pyobjc_PythonObject__
245{
246	/* FIXME: rewrite PyObjC_NSNumberWrapper in C */
247	PyObject *rval;
248
249
250	/* shortcut for booleans */
251	if (kCFBooleanTrue == (CFBooleanRef)self) {
252		return PyBool_FromLong(1);
253	} else if (kCFBooleanFalse == (CFBooleanRef)self) {
254		return PyBool_FromLong(0);
255	}
256
257	rval = PyObjC_FindPythonProxy(self);
258	if (rval == NULL) {
259		rval= PyObjCObject_New(self,
260				PyObjCObject_kDEFAULT, YES);
261
262		if (PyObjC_NSNumberWrapper && rval) {
263			PyObject *val = rval;
264			rval = PyObject_CallFunctionObjArgs(
265					PyObjC_NSNumberWrapper, val, NULL);
266			Py_DECREF(val);
267		}
268	}
269	return rval;
270}
271
272-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie
273{
274	*cookie = 0;
275	return [self __pyobjc_PythonObject__];
276}
277@end
278
279@interface NSDecimalNumber (PyObjCSupport)
280-(PyObject*)__pyobjc_PythonObject__;
281-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie;
282@end /* NSDecimalNumber (PyObjCSupport) */
283
284@implementation NSDecimalNumber (PyObjCSupport)
285-(PyObject*)__pyobjc_PythonObject__
286{
287	PyObject *rval;
288
289	rval = PyObjC_FindPythonProxy(self);
290	if (rval == NULL) {
291		rval = (PyObject *)PyObjCObject_New(self,
292				PyObjCObject_kDEFAULT, YES);
293		PyObjC_RegisterPythonProxy(self, rval);
294	}
295
296	return rval;
297}
298
299-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie
300{
301	*cookie = 0;
302	return [self __pyobjc_PythonObject__];
303}
304@end
305
306#ifndef MAX
307static inline Py_ssize_t
308MAX(Py_ssize_t x, Py_ssize_t y)
309{
310	return x > y ? x : y;
311}
312#endif
313
314static inline Py_ssize_t
315ROUND(Py_ssize_t v, Py_ssize_t a)
316{
317	if (v % a == 0) {
318		return v;
319	} else {
320		return v + a - (v % a);
321	}
322}
323
324
325const char*
326PyObjCRT_SkipTypeQualifiers (const char* type)
327{
328	PyObjC_Assert(type != NULL, NULL);
329
330	while (
331			*type == _C_CONST ||
332			*type == _C_IN ||
333			*type == _C_INOUT ||
334			*type == _C_OUT ||
335			*type == _C_BYCOPY ||
336			*type == _C_BYREF ||
337			*type == _C_ONEWAY ||
338			*type == 'O') {
339		type++;
340	}
341	while (*type && isdigit(*type)) type++;
342	return type;
343}
344
345const char *
346PyObjCRT_SkipTypeSpec (const char *type)
347{
348	PyObjC_Assert(type != NULL, NULL);
349
350	type = PyObjCRT_SkipTypeQualifiers (type);
351
352	switch (*type) {
353	/* The following are one character type codes */
354	case _C_UNDEF:
355	case _C_CLASS:
356	case _C_SEL:
357	case _C_CHR:
358	case _C_UCHR:
359	case _C_CHARPTR:
360#ifdef _C_ATOM
361	case _C_ATOM:
362#endif
363#ifdef _C_BOOL
364	case _C_BOOL:
365#endif
366	case _C_SHT:
367	case _C_USHT:
368	case _C_INT:
369	case _C_UINT:
370	case _C_LNG:
371	case _C_ULNG:
372	case _C_FLT:
373	case _C_DBL:
374	case _C_VOID:
375	case _C_LNG_LNG:
376	case _C_ULNG_LNG:
377	case _C_UNICHAR:
378	case _C_CHAR_AS_TEXT:
379	case _C_CHAR_AS_INT:
380	case _C_NSBOOL:
381		++type;
382		break;
383
384	case _C_BFLD:
385		while (isdigit (*++type));
386		break;
387
388	case _C_ID:
389		++type;
390		if (*type == '?') {
391			/* Block pointer */
392			type++;
393                }
394		if (*type == '"') {
395			/* embedded field name in an ivar_type */
396			type=strchr(type+1, '"');
397			if (type != NULL) {
398				type++;
399			}
400		}
401		break;
402
403	case _C_ARY_B:
404		/* skip digits, typespec and closing ']' */
405
406		while (isdigit (*++type));
407		type = PyObjCRT_SkipTypeSpec (type);
408		assert (type == NULL || *type == _C_ARY_E);
409		if (type) type++;
410		break;
411
412	case _C_STRUCT_B:
413		/* skip name, and elements until closing '}'  */
414		while (*type != _C_STRUCT_E && *type++ != '=');
415		while (type && *type != _C_STRUCT_E) {
416			if (*type == '"') {
417				/* embedded field names */
418				type = strchr(type+1, '"');
419				if (type != NULL) {
420					type++;
421				} else {
422					return NULL;
423				}
424			}
425			type = PyObjCRT_SkipTypeSpec (type);
426		}
427		if (type) type++;
428		break;
429
430	case _C_UNION_B:
431		/* skip name, and elements until closing ')'  */
432		while (*type != _C_UNION_E && *type++ != '=');
433		while (type && *type != _C_UNION_E) {
434			if (*type == '"') {
435				/* embedded field names */
436				type = strchr(type+1, '"');
437				if (type != NULL) {
438					type++;
439				} else {
440					return NULL;
441				}
442			}
443			type = PyObjCRT_SkipTypeSpec (type);
444		}
445		if (type) type++;
446		break;
447
448	case _C_PTR:
449	case _C_CONST:
450	case _C_IN:
451	case _C_INOUT:
452	case _C_OUT:
453	case _C_BYCOPY:
454	case _C_BYREF:
455	case _C_ONEWAY:
456
457		/* Just skip the following typespec */
458		type = PyObjCRT_SkipTypeSpec (type+1);
459		break;
460
461
462	default:
463		PyErr_Format(PyObjCExc_InternalError,
464			"PyObjCRT_SkipTypeSpec: Unhandled type '%#x' %s", *type, type);
465		return NULL;
466	}
467
468	/* The compiler inserts a number after the actual signature,
469	 * this number may or may not be usefull depending on the compiler
470	 * version. We never use it.
471	 */
472	while (type && *type && isdigit(*type)) type++;
473	return type;
474}
475
476const char *
477PyObjCRT_NextField(const char *type)
478{
479	PyObjC_Assert(type != NULL, NULL);
480
481	type = PyObjCRT_SkipTypeQualifiers (type);
482
483	switch (*type) {
484	/* The following are one character type codes */
485	case _C_UNDEF:
486	case _C_CLASS:
487	case _C_SEL:
488	case _C_CHR:
489	case _C_UCHR:
490	case _C_CHARPTR:
491#ifdef _C_ATOM
492	case _C_ATOM:
493#endif
494#ifdef _C_BOOL
495	case _C_BOOL:
496#endif
497	case _C_SHT:
498	case _C_USHT:
499	case _C_INT:
500	case _C_UINT:
501	case _C_LNG:
502	case _C_ULNG:
503	case _C_FLT:
504	case _C_DBL:
505	case _C_VOID:
506	case _C_LNG_LNG:
507	case _C_ULNG_LNG:
508	case _C_UNICHAR:
509	case _C_CHAR_AS_TEXT:
510	case _C_CHAR_AS_INT:
511	case _C_NSBOOL:
512	case _C_BFLD: /* Not really 1 character, but close enough  */
513		++type;
514		break;
515
516	case _C_ID:
517		++type;
518		break;
519
520	case _C_ARY_B:
521		/* skip digits, typespec and closing ']' */
522
523		while (isdigit (*++type));
524		type = PyObjCRT_SkipTypeSpec (type);
525		assert (type == NULL || *type == _C_ARY_E);
526		if (type) type++;
527		break;
528
529	case _C_STRUCT_B:
530		/* skip name, and elements until closing '}'  */
531		while (*type != _C_STRUCT_E && *type++ != '=');
532		while (type && *type != _C_STRUCT_E) {
533			if (*type == '"') {
534				/* embedded field names */
535				type = strchr(type+1, '"');
536				if (type != NULL) {
537					type++;
538				} else {
539					return NULL;
540				}
541			}
542			type = PyObjCRT_SkipTypeSpec (type);
543		}
544		if (type) type++;
545		break;
546
547	case _C_UNION_B:
548		/* skip name, and elements until closing ')'  */
549		while (*type != _C_UNION_E && *type++ != '=');
550		while (type && *type != _C_UNION_E) {
551			if (*type == '"') {
552				/* embedded field names */
553				type = strchr(type+1, '"');
554				if (type != NULL) {
555					type++;
556				} else {
557					return NULL;
558				}
559			}
560			type = PyObjCRT_SkipTypeSpec (type);
561		}
562		if (type) type++;
563		break;
564
565	case _C_PTR:
566	case _C_CONST:
567	case _C_IN:
568	case _C_INOUT:
569	case _C_OUT:
570	case _C_BYCOPY:
571	case _C_BYREF:
572	case _C_ONEWAY:
573
574		/* Just skip the following typespec */
575		type = PyObjCRT_NextField(type+1);
576		break;
577
578
579	default:
580		PyErr_Format(PyObjCExc_InternalError,
581			"PyObjCRT_SkipTypeSpec: Unhandled type '%#x'", *type);
582		return NULL;
583	}
584
585	/* The compiler inserts a number after the actual signature,
586	 * this number may or may not be usefull depending on the compiler
587	 * version. We never use it.
588	 */
589	while (type && *type && isdigit(*type)) type++;
590	return type;
591}
592
593/*
594Return the alignment of an object specified by type
595*/
596
597/*
598*  On MacOS X, the elements of a struct are aligned differently inside the
599*  struct than outside. That is, the maximum alignment of any struct field
600*  (except the first) is 4, doubles outside of a struct have an alignment of
601*  8.
602*
603*  Other platform don't seem to have this inconsistency.
604*
605*  XXX: sizeof_struct, alignof_struct and {de,}pythonify_c_struct should
606*  probably be moved to platform dependend files. As long as this is the
607*  only platform dependent code this isn't worth the effort.
608*/
609
610static inline Py_ssize_t
611PyObjC_EmbeddedAlignOfType (const char*  type)
612{
613	PyObjC_Assert(type != NULL, -1);
614
615	Py_ssize_t align = PyObjCRT_AlignOfType(type);
616
617#if defined(__i386__) || defined(__x86_64__)
618	return align;
619
620#else
621	if (align < 4 || align == 16) {
622		return align;
623	} else {
624		return 4;
625	}
626#endif
627}
628
629Py_ssize_t
630PyObjCRT_AlignOfType (const char *type)
631{
632	PyObjC_Assert(type != NULL, -1);
633
634	switch (*type) {
635	case _C_VOID:  return __alignof__(char);
636	case _C_ID:    return __alignof__ (id);
637	case _C_CLASS: return __alignof__ (Class);
638	case _C_SEL:   return __alignof__ (SEL);
639	case _C_CHR:   return __alignof__ (char);
640	case _C_UCHR:  return __alignof__ (unsigned char);
641	case _C_SHT:   return __alignof__ (short);
642	case _C_USHT:  return __alignof__ (unsigned short);
643#ifdef _C_BOOL
644	case _C_BOOL:   return __alignof__ (bool);
645#endif
646	case _C_UNICHAR:	return __alignof__(UniChar);
647	case _C_CHAR_AS_TEXT:	return __alignof__(char);
648	case _C_CHAR_AS_INT:	return __alignof__(char);
649	case _C_NSBOOL:		return __alignof__(BOOL);
650	case _C_INT:   return __alignof__ (int);
651	case _C_UINT:  return __alignof__ (unsigned int);
652	case _C_LNG:   return __alignof__ (long);
653	case _C_ULNG:  return __alignof__ (unsigned long);
654	case _C_FLT:   return __alignof__ (float);
655	case _C_DBL:
656#if defined(__APPLE__) && defined(__i386__)
657		/* The ABI says natural alignment is 4 bytes, but
658		 * GCC's __alignof__ says 8. The latter is wrong.
659		 */
660		return 4;
661#else
662		return __alignof__ (double);
663#endif
664
665	case _C_CHARPTR: return __alignof__ (char *);
666#ifdef _C_ATOM
667	case _C_ATOM: return __alignof__ (char *);
668#endif
669	case _C_PTR:   return __alignof__ (void *);
670#if defined(__APPLE__) && defined(__i386__)
671		/* The ABI says natural alignment is 4 bytes, but
672		 * GCC's __alignof__ says 8. The latter is wrong.
673		 */
674	case _C_LNG_LNG: return 4;
675	case _C_ULNG_LNG: return 4;
676#else
677	case _C_LNG_LNG: return __alignof__(long long);
678	case _C_ULNG_LNG: return __alignof__(unsigned long long);
679#endif
680
681	case _C_ARY_B:
682		while (isdigit(*++type)) /* do nothing */;
683		return PyObjCRT_AlignOfType (type);
684
685	case _C_STRUCT_B:
686	{
687		struct { int x; double y; } fooalign;
688		while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
689		if (*type != _C_STRUCT_E) {
690			int have_align = 0;
691			Py_ssize_t align = 0;
692
693			while (type != NULL && *type != _C_STRUCT_E) {
694				if (*type == '"') {
695					type = strchr(type+1, '"');
696					if (type) type++;
697				}
698				if (have_align) {
699					align = MAX(align,
700					   PyObjC_EmbeddedAlignOfType(type));
701				} else {
702					align = PyObjCRT_AlignOfType(type);
703					have_align = 1;
704				}
705				type = PyObjCRT_SkipTypeSpec(type);
706			}
707			if (type == NULL) return -1;
708			return align;
709		} else {
710			return __alignof__ (fooalign);
711		}
712	}
713
714	case _C_UNION_B:
715	{
716		int maxalign = 0;
717		type++;
718		while (*type != _C_UNION_E)
719		{
720			int item_align = PyObjCRT_AlignOfType(type);
721			if (item_align == -1) return -1;
722			maxalign = MAX (maxalign, item_align);
723			type = PyObjCRT_SkipTypeSpec (type);
724		}
725		return maxalign;
726	}
727
728	case _C_CONST:
729	case _C_IN:
730	case _C_INOUT:
731	case _C_OUT:
732	case _C_BYCOPY:
733	case _C_BYREF:
734	case _C_ONEWAY:
735		return PyObjCRT_AlignOfType(type+1);
736
737	case _C_BFLD:
738		return 1;
739
740	case _C_UNDEF:
741		return __alignof__(void*);
742
743	default:
744		printf("alignoftype\n");
745		abort();
746		PyErr_Format(PyObjCExc_InternalError,
747			"PyObjCRT_AlignOfType: Unhandled type '%#x' %s", *type, type);
748		return -1;
749	}
750}
751
752/*
753The aligned size if the size rounded up to the nearest alignment.
754*/
755
756Py_ssize_t
757PyObjCRT_AlignedSize (const char *type)
758{
759	PyObjC_Assert(type != NULL, -1);
760
761	Py_ssize_t size = PyObjCRT_SizeOfType (type);
762	Py_ssize_t align = PyObjCRT_AlignOfType (type);
763
764	if (size == -1 || align == -1) return -1;
765	return ROUND(size, align);
766}
767
768/*
769return the size of an object specified by type
770*/
771
772Py_ssize_t
773PyObjCRT_SizeOfType (const char *type)
774{
775	PyObjC_Assert(type != NULL, -1);
776
777	Py_ssize_t itemSize;
778	switch (*type) {
779	case _C_VOID:    return 1; // More convenient than the correct value.
780	case _C_ID:      return sizeof(id);
781	case _C_CLASS:   return sizeof(Class);
782	case _C_SEL:     return sizeof(SEL);
783	case _C_CHR:     return sizeof(char);
784	case _C_UCHR:    return sizeof(unsigned char);
785	case _C_SHT:     return sizeof(short);
786	case _C_USHT:    return sizeof(unsigned short);
787#ifdef _C_BOOL
788	case _C_BOOL:    return sizeof(bool);
789#endif
790	case _C_INT:     return sizeof(int);
791	case _C_UINT:    return sizeof(unsigned int);
792	case _C_LNG:     return sizeof(long);
793	case _C_ULNG:    return sizeof(unsigned long);
794	case _C_FLT:     return sizeof(float);
795	case _C_DBL:     return sizeof(double);
796	case _C_LNG_LNG:  return sizeof(long long);
797	case _C_ULNG_LNG: return sizeof(unsigned long long);
798	case _C_UNICHAR:	return sizeof(UniChar);
799	case _C_CHAR_AS_TEXT:	return sizeof(char);
800	case _C_CHAR_AS_INT:	return sizeof(char);
801	case _C_NSBOOL:		return sizeof(BOOL);
802
803	case _C_PTR:
804	case _C_CHARPTR:
805#ifdef _C_ATOM
806	case _C_ATOM:
807#endif
808		return sizeof(char*);
809
810	case _C_ARY_B:
811	{
812		Py_ssize_t len = atoi(type+1);
813		Py_ssize_t item_align;
814		while (isdigit(*++type))
815			;
816		item_align = PyObjCRT_AlignedSize(type);
817		if (item_align == -1) return -1;
818		return len*item_align;
819	}
820	break;
821
822	case _C_STRUCT_B:
823	{
824		Py_ssize_t acc_size = 0;
825		int have_align =  0;
826		Py_ssize_t align;
827		Py_ssize_t max_align = 0;
828
829		/* This is an awfull hack... */
830		/*   struct sockaddr is a generic type with several supported
831		 *   specific types. Annoyingly enough not all of those have the
832		 *   same size.
833		 *   This file has crude support for this scheme as its almost
834		 *   impossible to implement this nicely using our C/Python
835		 *   API.
836		 */
837		if (strncmp(type,
838			@encode(struct sockaddr),
839			sizeof(@encode(struct sockaddr)-1)) == 0) {
840
841			return sizeof(struct sockaddr_in6);
842		}
843
844		while (*type != _C_STRUCT_E && *type++ != '=')
845			; /* skip "<name>=" */
846		while (*type != _C_STRUCT_E) {
847			if (*type == '"') {
848				type = strchr(type+1, '"');
849				if (type) type++;
850			}
851			if (have_align) {
852				align = PyObjC_EmbeddedAlignOfType(type);
853				if (align == -1) return -1;
854			} else {
855				align = PyObjCRT_AlignOfType(type);
856				if (align == -1) return -1;
857				have_align = 1;
858			}
859			max_align = MAX(align, max_align);
860			acc_size = ROUND (acc_size, align);
861
862			itemSize = PyObjCRT_SizeOfType (type);
863			if (itemSize == -1) return -1;
864			acc_size += itemSize;
865			type = PyObjCRT_SkipTypeSpec (type);
866		}
867		if (max_align) {
868			acc_size = ROUND(acc_size, max_align);
869		}
870		return acc_size;
871	}
872
873	case _C_UNION_B:
874	{
875		Py_ssize_t max_size = 0;
876		type++;
877		while (*type != _C_UNION_E) {
878			itemSize = PyObjCRT_SizeOfType (type);
879			if (itemSize == -1) return -1;
880			max_size = MAX (max_size, itemSize);
881			type = PyObjCRT_SkipTypeSpec (type);
882		}
883		return max_size;
884	}
885
886	case _C_CONST:
887	case _C_IN:
888	case _C_INOUT:
889	case _C_OUT:
890	case _C_BYCOPY:
891	case _C_BYREF:
892	case _C_ONEWAY:
893		return PyObjCRT_SizeOfType(type+1);
894
895	case _C_BFLD:
896		{
897			int i = strtol(type+1, NULL, 10);
898			return (i+7)/8;
899		}
900		break;
901
902	case _C_UNDEF:
903		return sizeof(void*);
904
905	default:
906		PyErr_Format(PyObjCExc_InternalError,
907			"PyObjCRT_SizeOfType: Unhandled type '%#x', %s", *type, type);
908		return -1;
909	}
910}
911
912PyObject *
913pythonify_c_array_nullterminated(const char* type, void* datum, BOOL alreadyRetained, BOOL alreadyCFRetained)
914{
915	PyObjC_Assert(type != NULL, NULL);
916	PyObjC_Assert(datum != NULL, NULL);
917
918	Py_ssize_t count = 0;
919	Py_ssize_t sizeofitem = PyObjCRT_SizeOfType (type);
920	unsigned char* curdatum = datum;
921
922	type = PyObjCRT_SkipTypeQualifiers(type);
923	switch (*type) {
924	case _C_CHARPTR:
925		while (*(char**)curdatum != NULL) {
926			count ++;
927			curdatum += sizeofitem;
928		}
929		break;
930
931	case _C_ID:
932		while (*(id*)curdatum != NULL) {
933			count ++;
934			curdatum += sizeofitem;
935		}
936		break;
937
938	case _C_PTR:
939		while (*(void**)curdatum != NULL) {
940			count ++;
941			curdatum += sizeofitem;
942		}
943		break;
944
945	case _C_UCHR:
946		while (*(unsigned char*)curdatum != 0) {
947			count ++;
948			curdatum += sizeofitem;
949		}
950		break;
951
952	case _C_VOID:
953	case _C_CHR:
954	case _C_CHAR_AS_TEXT:
955		return PyString_FromString((char*)curdatum);
956		break;
957
958	case _C_USHT:
959		while (*(unsigned short*)curdatum != 0) {
960			count ++;
961			curdatum += sizeofitem;
962		}
963		break;
964	case _C_SHT:
965		while (*(short*)curdatum != 0) {
966			count ++;
967			curdatum += sizeofitem;
968		}
969		break;
970
971	case _C_UINT:
972		while (*(unsigned int*)curdatum != 0) {
973			count ++;
974			curdatum += sizeofitem;
975		}
976		break;
977	case _C_INT:
978		while (*(int*)curdatum != 0) {
979			count ++;
980			curdatum += sizeofitem;
981		}
982		break;
983
984	case _C_ULNG:
985		while (*(unsigned long*)curdatum != 0) {
986			count ++;
987			curdatum += sizeofitem;
988		}
989		break;
990	case _C_LNG:
991		while (*(long*)curdatum != 0) {
992			count ++;
993			curdatum += sizeofitem;
994		}
995		break;
996
997	case _C_ULNG_LNG:
998		while (*(unsigned long long*)curdatum != 0) {
999			count ++;
1000			curdatum += sizeofitem;
1001		}
1002		break;
1003	case _C_LNG_LNG:
1004		while (*(long long*)curdatum != 0) {
1005			count ++;
1006			curdatum += sizeofitem;
1007		}
1008		break;
1009
1010	case _C_UNICHAR:
1011		while (*(UniChar*)curdatum != 0) {
1012			count ++;
1013			curdatum += sizeofitem;
1014		}
1015		break;
1016
1017	case _C_CHAR_AS_INT:
1018		while (*(char*)curdatum != 0) {
1019			count ++;
1020			curdatum += sizeofitem;
1021		}
1022		break;
1023
1024
1025	default:
1026		PyErr_Format(PyExc_TypeError,
1027			"Cannot deal with NULL-terminated array of %s",
1028			type);
1029		return NULL;
1030	}
1031
1032	return  PyObjC_CArrayToPython2(type, datum, count, alreadyRetained, alreadyCFRetained);
1033}
1034
1035
1036
1037/*#F Returns a tuple of objects representing the content of a C array
1038of type @var{type} pointed by @var{datum}. */
1039static PyObject *
1040pythonify_c_array (const char *type, void *datum)
1041{
1042	PyObjC_Assert(type != NULL, NULL);
1043	PyObjC_Assert(datum != NULL, NULL);
1044
1045	PyObject *ret;
1046	Py_ssize_t nitems, itemidx, sizeofitem;
1047	unsigned char* curdatum;
1048
1049	nitems = atoi (type+1);
1050	while (isdigit (*++type))
1051		;
1052	sizeofitem = PyObjCRT_SizeOfType (type);
1053	if (sizeofitem == -1) return NULL;
1054
1055	ret = PyTuple_New (nitems);
1056	if (!ret) return NULL;
1057
1058	curdatum = datum;
1059	for (itemidx=0; itemidx < nitems; itemidx++) {
1060		PyObject *pyitem = NULL;
1061
1062		pyitem = pythonify_c_value (type, curdatum);
1063
1064		if (pyitem) {
1065			PyTuple_SET_ITEM (ret, itemidx, pyitem);
1066		} else {
1067			Py_DECREF(ret);
1068			return NULL;
1069		}
1070
1071		curdatum += sizeofitem;
1072	}
1073
1074	return ret;
1075}
1076
1077/*#F Returns a tuple of objects representing the content of a C structure
1078of type @var{type} pointed by @var{datum}. */
1079static PyObject *
1080pythonify_c_struct (const char *type, void *datum)
1081{
1082	PyObjC_Assert(type != NULL, NULL);
1083	PyObjC_Assert(datum != NULL, NULL);
1084
1085	PyObject *ret;
1086	Py_ssize_t offset, itemidx;
1087	const char *item;
1088	int have_align = 0;
1089	Py_ssize_t align;
1090	int haveTuple;
1091	const char* type_start = type;
1092	const char* type_end = PyObjCRT_SkipTypeSpec(type);
1093	const char* type_real_start = type;
1094	Py_ssize_t type_real_length = type_end - type_start;
1095
1096	/* Hacked up support for socket addresses */
1097	if (strncmp(type, @encode(struct sockaddr), sizeof(@encode(struct sockaddr)-1)) == 0) {
1098		return PyObjC_SockAddrToPython(datum);
1099	}
1100
1101	if (IS_FSREF(type)) {
1102		return PyObjC_decode_fsref(datum);
1103	}
1104
1105	if (IS_FSSPEC(type)) {
1106		return PyObjC_decode_fsspec(datum);
1107	}
1108
1109	/* Skip back over digits at end of type in function prototypes */
1110	while (type_real_length > 0 && isdigit(type_start[type_real_length-1])) {
1111		type_real_length --;
1112	}
1113
1114	/* The compiler adds useless digits at the end of the signature */
1115	while (type_end != type_start+1 && type_end[-1] != _C_STRUCT_E) {
1116		type_end--;
1117	}
1118
1119	while (*type != _C_STRUCT_E && *type++ != '=') {
1120		/* skip "<name>=" */
1121	}
1122
1123	haveTuple = 0;
1124	const char* oc_typestr = NULL;
1125	ret = PyObjC_CreateRegisteredStruct(type_start,
1126			type_end-type_start, &oc_typestr);
1127	if (ret == NULL) {
1128		int nitems;
1129
1130		nitems = 0;
1131		item = type;
1132		while (*item != _C_STRUCT_E) {
1133			nitems ++;
1134			if (*item == '"') {
1135				item = strchr(item+1, '"');
1136				if (item) item ++;
1137			}
1138			item = PyObjCRT_SkipTypeSpec(item);
1139		}
1140
1141		haveTuple = 1;
1142		ret = PyTuple_New (nitems);
1143		if (!ret) return NULL;
1144
1145		item = type;
1146	} else {
1147		item = type;
1148
1149		if (oc_typestr != NULL) {
1150			item = oc_typestr + 1;
1151			while (*item && *item != '=') {
1152				item++;
1153			}
1154			if (*item) {
1155				item++;
1156			}
1157		}
1158	}
1159
1160
1161	offset = itemidx = 0;
1162	while (*item != _C_STRUCT_E) {
1163		PyObject *pyitem;
1164
1165		if (*item == '"') {
1166			item = strchr(item+1, '"');
1167			if (item) item ++;
1168		}
1169
1170		if (!have_align) {
1171			align = PyObjCRT_AlignOfType(item);
1172			have_align = 1;
1173		} else {
1174			align = PyObjC_EmbeddedAlignOfType(item);
1175		}
1176
1177		offset = ROUND(offset, align);
1178
1179		pyitem = pythonify_c_value (item, ((char*)datum)+offset);
1180
1181		if (pyitem) {
1182			if (haveTuple) {
1183				PyTuple_SET_ITEM (ret, itemidx, pyitem);
1184			} else {
1185				int r;
1186				r = PySequence_SetItem(ret, itemidx, pyitem);
1187				Py_DECREF(pyitem);
1188				if (r == -1) {
1189					Py_DECREF(ret);
1190					return NULL;
1191				}
1192			}
1193		} else {
1194			Py_DECREF(ret);
1195			return NULL;
1196		}
1197
1198		itemidx++;
1199		offset += PyObjCRT_SizeOfType (item);
1200		item = PyObjCRT_SkipTypeSpec (item);
1201	}
1202
1203	if (haveTuple) {
1204		PyObject *converted;
1205		converted = [OC_PythonObject __pythonifyStruct:ret withType:type_real_start length:type_real_length];
1206		Py_DECREF(ret);
1207		return converted;
1208	} else {
1209		return ret;
1210	}
1211}
1212
1213int
1214depythonify_c_return_array_count(const char* rettype, Py_ssize_t count, PyObject* arg, void* resp, BOOL already_retained, BOOL already_cfretained)
1215{
1216	PyObjC_Assert(rettype != NULL, -1);
1217	PyObjC_Assert(arg != NULL, -1);
1218	PyObjC_Assert(resp != NULL, -1);
1219
1220	/* Use an NSMutableData object to store the bytes, that way we can autorelease the data because we
1221	 * cannot free it otherwise.
1222	 */
1223	PyObject* seq = PySequence_Fast(arg, "Sequence required");
1224	if (seq == NULL) {
1225		return -1;
1226	}
1227	if (count == -1) {
1228		count = PySequence_Fast_GET_SIZE(seq);
1229	}
1230
1231	NSMutableData* data = [NSMutableData dataWithLength:count * PyObjCRT_SizeOfType(rettype)];
1232	*(void**)resp = [data mutableBytes];
1233	int r = depythonify_c_array_count(rettype, count, YES, seq, [data mutableBytes], already_retained, already_cfretained);
1234	Py_DECREF(seq);
1235
1236	return r;
1237}
1238
1239
1240int
1241depythonify_c_return_array_nullterminated(const char* rettype, PyObject* arg, void* resp, BOOL already_retained, BOOL already_cfretained)
1242{
1243	PyObjC_Assert(rettype != NULL, -1);
1244	PyObjC_Assert(arg != NULL, -1);
1245	PyObjC_Assert(resp != NULL, -1);
1246
1247	/* Use an NSMutableData object to store the bytes, that way we can autorelease the data because we
1248	 * cannot free it otherwise.
1249	 */
1250	PyObject* seq = PySequence_Fast(arg, "Sequence required");
1251	if (seq == NULL) {
1252		return -1;
1253	}
1254
1255	Py_ssize_t count = PySequence_Fast_GET_SIZE(seq);
1256
1257	/* The data is 0-filled, which means we won't have to add the terminated ourselves */
1258	NSMutableData* data = [NSMutableData dataWithLength:(count + 1) * PyObjCRT_SizeOfType(rettype)];
1259	*(void**)resp = [data mutableBytes];
1260	int result =  depythonify_c_array_count(rettype, count, YES, seq, [data mutableBytes], already_retained, already_cfretained);
1261	Py_DECREF(seq);
1262	return result;
1263}
1264
1265
1266int
1267depythonify_c_array_count(const char* type, Py_ssize_t nitems, BOOL strict, PyObject* value, void* datum, BOOL already_retained, BOOL already_cfretained)
1268{
1269	PyObjC_Assert(type != NULL, -1);
1270	PyObjC_Assert(value != NULL, -1);
1271	PyObjC_Assert(datum != NULL, -1);
1272
1273	Py_ssize_t itemidx, sizeofitem;
1274	unsigned char* curdatum;
1275	PyObject* seq;
1276
1277	sizeofitem = PyObjCRT_AlignedSize (type);
1278	if (sizeofitem == -1) {
1279		PyErr_Format(PyExc_ValueError,
1280			"cannot depythonify array of unknown type");
1281		return -1;
1282	}
1283
1284	if (sizeofitem == 1 && PyString_Check(value)) {
1285		/* Special casing for strings */
1286		if (strict) {
1287			if (PyString_Size(value) != nitems) {
1288				PyErr_Format(PyExc_ValueError,
1289					"depythonifying array of %"PY_FORMAT_SIZE_T"d items, got one of %"PY_FORMAT_SIZE_T"d",
1290					nitems, PyString_Size(value));
1291				return -1;
1292			}
1293		} else {
1294			if (PyString_Size(value) < nitems) {
1295				PyErr_Format(PyExc_ValueError,
1296					"depythonifying array of %"PY_FORMAT_SIZE_T"d items, got one of %"PY_FORMAT_SIZE_T"d",
1297					nitems, PyString_Size(value));
1298				return -1;
1299			}
1300		}
1301
1302		memcpy(datum, PyString_AS_STRING(value), nitems);
1303	}
1304
1305	seq = PySequence_Fast(value, "depythonifying array, got no sequence");
1306	if (seq == NULL) {
1307		return -1;
1308	}
1309
1310	if (strict) {
1311		if (PySequence_Fast_GET_SIZE(seq) != nitems) {
1312			PyErr_Format(PyExc_ValueError,
1313				"depythonifying array of %"PY_FORMAT_SIZE_T"d items, got one of %"PY_FORMAT_SIZE_T"d",
1314				nitems, PySequence_Fast_GET_SIZE(seq));
1315			Py_DECREF(seq);
1316			return -1;
1317		}
1318	} else {
1319		if (PySequence_Fast_GET_SIZE(seq) < nitems) {
1320			PyErr_Format(PyExc_ValueError,
1321				"depythonifying array of %"PY_FORMAT_SIZE_T"d items, got one of %"PY_FORMAT_SIZE_T"d",
1322				nitems, PySequence_Fast_GET_SIZE(seq));
1323			Py_DECREF(seq);
1324			return -1;
1325		}
1326	}
1327
1328	curdatum = datum;
1329	for (itemidx=0; itemidx < nitems; itemidx++) {
1330		PyObject *pyarg = PySequence_Fast_GET_ITEM(seq, itemidx);
1331		int err;
1332
1333		err = depythonify_c_value (type, pyarg, curdatum);
1334		if (err == -1) {
1335			Py_DECREF(seq);
1336			return err;
1337		}
1338
1339		if (already_retained) {
1340			[*(NSObject**)curdatum retain];
1341
1342		} else if (already_cfretained) {
1343			CFRetain(*(NSObject**)curdatum);
1344
1345		}
1346
1347		curdatum += sizeofitem;
1348	}
1349
1350	if (*type == _C_CHARPTR) {
1351		/* We're depythonifying a list of strings, make sure the originals stay
1352		 * around long enough.
1353		 */
1354		[OC_PythonObject newWithObject:seq];
1355	}
1356	Py_DECREF(seq);
1357	return 0;
1358}
1359
1360Py_ssize_t
1361c_array_nullterminated_size(PyObject* object, PyObject** seq)
1362{
1363	PyObjC_Assert(object != NULL, -1);
1364	PyObjC_Assert(seq != NULL, -1);
1365
1366	*seq = PySequence_Fast(object, "depythonifying array, got no sequence");
1367	if (*seq == NULL) {
1368		return -1;
1369	}
1370
1371	return PySequence_Fast_GET_SIZE(*seq) + 1;
1372}
1373
1374int
1375depythonify_c_array_nullterminated(const char* type, Py_ssize_t count, PyObject* value, void* datum, BOOL already_retained, BOOL already_cfretained)
1376{
1377	PyObjC_Assert(type != NULL, -1);
1378	PyObjC_Assert(value != NULL, -1);
1379	PyObjC_Assert(datum != NULL, -1);
1380
1381	/* XXX: we can do better than this: just clear the last item */
1382	/* Clear memory: */
1383	memset(datum, 0, count * PyObjCRT_SizeOfType(type));
1384
1385	if (count == 1) {
1386		return 0;
1387	}
1388
1389	/* Then copy the actual values */
1390	return depythonify_c_array_count(type, count-1, YES, value, datum, already_retained, already_cfretained);
1391}
1392
1393/*#F Extracts the elements from the tuple @var{arg} and fills a C array
1394of type @var{type} pointed by @var{datum}. Returns an error message, or
1395NULL on success. */
1396static int
1397depythonify_c_array (const char *type, PyObject *arg, void *datum)
1398{
1399	PyObjC_Assert(type != NULL, -1);
1400	PyObjC_Assert(arg != NULL, -1);
1401	PyObjC_Assert(datum != NULL, -1);
1402
1403	Py_ssize_t nitems, itemidx, sizeofitem;
1404	unsigned char* curdatum;
1405	PyObject* seq;
1406
1407	nitems = atoi (type+1);
1408	while (isdigit (*++type))
1409		;
1410	sizeofitem = PyObjCRT_AlignedSize (type);
1411	if (sizeofitem == -1) {
1412		PyErr_Format(PyExc_ValueError,
1413			"cannot depythonify array of unknown type");
1414		return -1;
1415	}
1416
1417	seq = PySequence_Fast(arg, "depythonifying array, got no sequence");
1418	if (seq == NULL) {
1419		return -1;
1420	}
1421
1422	if (nitems != PySequence_Fast_GET_SIZE(seq)) {
1423		PyErr_Format(PyExc_ValueError,
1424			"depythonifying array of %"PY_FORMAT_SIZE_T"d items, got one of %"PY_FORMAT_SIZE_T"d",
1425			nitems, PySequence_Fast_GET_SIZE(seq));
1426		Py_DECREF(seq);
1427		return -1;
1428	}
1429
1430	curdatum = datum;
1431	for (itemidx=0; itemidx < nitems; itemidx++) {
1432		PyObject *pyarg = PySequence_Fast_GET_ITEM(seq, itemidx);
1433		int err;
1434
1435		err = depythonify_c_value (type, pyarg, curdatum);
1436		if (err == -1) {
1437			Py_DECREF(seq);
1438			return err;
1439		}
1440
1441		curdatum += sizeofitem;
1442	}
1443
1444	Py_DECREF(seq);
1445	return 0;
1446}
1447
1448/*#F Extracts the elements from the tuple @var{arg} and fills a C structure
1449of type @var{type} pointed by @var{datum}. Returns an error message, or
1450NULL on success. */
1451static int
1452depythonify_c_struct(const char *types, PyObject *arg, void *datum)
1453{
1454	PyObjC_Assert(types != NULL, -1);
1455	PyObjC_Assert(arg != NULL, -1);
1456	PyObjC_Assert(datum != NULL, -1);
1457
1458	Py_ssize_t nitems, offset, itemidx;
1459	int have_align = 0;
1460	Py_ssize_t align;
1461	const char *type;
1462	PyObject* seq;
1463
1464	/* Hacked in support for sockaddr structs */
1465	if (strncmp(types, @encode(struct sockaddr), sizeof(@encode(struct sockaddr)-1)) == 0) {
1466		return PyObjC_SockAddrFromPython(arg, datum);
1467	}
1468
1469	if (IS_FSREF(types)) {
1470		if (PyObjC_encode_fsref(arg, datum) == 0) {
1471			return 0;
1472		}
1473		PyErr_Clear();
1474	}
1475	if (IS_FSSPEC(types)) {
1476		if (PyObjC_encode_fsspec(arg, datum) == 0) {
1477			return 0;
1478		}
1479		PyErr_Clear();
1480	}
1481
1482	while (*types != _C_STRUCT_E && *types++ != '='); /* skip "<name>=" */
1483
1484	type=types;
1485	nitems=0;
1486	while (*type != _C_STRUCT_E) {
1487		if (*type == '"') {
1488			type = strchr(type+1, '"');
1489			type++;
1490		}
1491		nitems++;
1492		type = PyObjCRT_SkipTypeSpec (type);
1493	}
1494
1495	seq = PySequence_Fast(arg, "depythonifying struct, got no sequence");
1496	if (seq == NULL) {
1497		return -1;
1498	}
1499
1500	if (nitems != PySequence_Fast_GET_SIZE(seq)) {
1501		Py_DECREF(seq);
1502		PyErr_Format(PyExc_ValueError,
1503			"depythonifying struct of %"PY_FORMAT_SIZE_T"d members, got tuple of %"PY_FORMAT_SIZE_T"d",
1504			nitems, PyTuple_Size (arg));
1505		return -1;
1506	}
1507
1508	type=types;
1509	offset = itemidx = 0;
1510
1511	while (*type != _C_STRUCT_E) {
1512		PyObject *argument;
1513
1514		if (*type == '"') {
1515			type = strchr(type+1, '"');
1516			type++;
1517		}
1518
1519
1520		argument = PySequence_Fast_GET_ITEM(seq, itemidx);
1521		int error;
1522		if (!have_align) {
1523			align = PyObjCRT_AlignOfType(type);
1524			have_align = 1;
1525		} else {
1526			align = PyObjC_EmbeddedAlignOfType(type);
1527		}
1528
1529		offset = ROUND(offset, align);
1530
1531		error = depythonify_c_value(type, argument,
1532				((char*)datum)+offset);
1533		if (error == -1) {
1534			Py_DECREF(seq);
1535			return error;
1536		}
1537
1538		itemidx++;
1539		offset += PyObjCRT_SizeOfType (type);
1540		type = PyObjCRT_SkipTypeSpec (type);
1541	}
1542	Py_DECREF(seq);
1543	return 0;
1544}
1545
1546PyObject *
1547pythonify_c_value (const char *type, void *datum)
1548{
1549	PyObjC_Assert(type != NULL, NULL);
1550	PyObjC_Assert(datum != NULL, NULL);
1551
1552	PyObject *retobject = NULL;
1553
1554	type = PyObjCRT_SkipTypeQualifiers (type);
1555
1556	switch (*type) {
1557	case _C_UNICHAR:
1558		{
1559			Py_UNICODE	c  = (Py_UNICODE)(*(UniChar*)datum);
1560			retobject = PyUnicode_FromUnicode(&c, 1);
1561		}
1562		break;
1563
1564	case _C_CHAR_AS_TEXT:
1565		retobject = PyString_FromStringAndSize((char*)datum, 1);
1566		break;
1567
1568	case _C_CHR:
1569	case _C_CHAR_AS_INT:
1570		/*
1571		 * We don't return a string because BOOL is an alias for
1572		 * char (at least on MacOS X)
1573		 */
1574		retobject = (PyObject*)PyInt_FromLong ((int)(*(char*)datum));
1575		break;
1576
1577	case _C_UCHR:
1578		retobject = (PyObject*)PyInt_FromLong (
1579			(long)(*(unsigned char*)datum));
1580		break;
1581
1582	case _C_CHARPTR:
1583#ifdef _C_ATOM
1584	case _C_ATOM:
1585#endif
1586	{
1587		char *cp = *(char **) datum;
1588
1589		if (cp == NULL) {
1590			Py_INCREF(Py_None);
1591			retobject = Py_None;
1592		} else {
1593			retobject = (PyObject*)PyString_FromString(cp);
1594		}
1595		break;
1596	}
1597
1598#ifdef _C_BOOL
1599	case _C_BOOL:
1600		retobject = (PyObject *) PyBool_FromLong (*(bool*) datum);
1601		break;
1602#endif
1603
1604	case _C_NSBOOL:
1605		retobject = (PyObject *) PyBool_FromLong (*(BOOL*) datum);
1606		break;
1607
1608	case _C_INT:
1609		retobject = (PyObject *) PyInt_FromLong (*(int*) datum);
1610		break;
1611
1612	case _C_UINT:
1613#if __LP64__
1614		retobject = (PyObject*)PyInt_FromLong (
1615			*(unsigned int *) datum);
1616
1617#else
1618		if (*(unsigned int*)datum > LONG_MAX) {
1619			retobject = (PyObject*)PyLong_FromUnsignedLongLong(
1620				*(unsigned int*)datum);
1621		} else {
1622			retobject = (PyObject*)PyInt_FromLong (
1623				*(unsigned int *) datum);
1624		}
1625#endif
1626		break;
1627
1628	case _C_SHT:
1629		retobject = (PyObject *) PyInt_FromLong (*(short *) datum);
1630		break;
1631
1632	case _C_USHT:
1633		retobject = (PyObject *) PyInt_FromLong (
1634			*(unsigned short *) datum);
1635		break;
1636
1637	case _C_LNG_LNG:
1638#ifndef __LP64__ /* else: fall-through to _C_LNG case */
1639		retobject = (PyObject*)PyLong_FromLongLong(*(long long*)datum);
1640		break;
1641#endif
1642
1643	case _C_LNG:
1644		retobject = (PyObject *) PyInt_FromLong(*(long *) datum);
1645		break;
1646
1647	case _C_ULNG_LNG:
1648#ifndef __LP64__ /* else: fallthrough to the ULNG case */
1649		retobject = (PyObject*)PyLong_FromUnsignedLongLong(
1650				*(unsigned long long*)datum);
1651		break;
1652#endif
1653
1654	case _C_ULNG:
1655		if (*(unsigned long*)datum > LONG_MAX) {
1656			retobject = (PyObject*)PyLong_FromUnsignedLongLong(
1657				*(unsigned long*)datum);
1658		} else {
1659			retobject = (PyObject*)PyInt_FromLong (
1660				*(unsigned long*) datum);
1661		}
1662		break;
1663
1664
1665
1666	case _C_FLT:
1667		retobject = (PyObject *) PyFloat_FromDouble (*(float*) datum);
1668		break;
1669
1670	case _C_DBL:
1671		retobject = (PyObject *) PyFloat_FromDouble (*(double*) datum);
1672		break;
1673
1674	case _C_ID:
1675	{
1676		id obj = *(id *) datum;
1677
1678#if 1
1679		/* In theory this is a no-op, in practice this gives us EOF 4.5
1680		 * support.
1681		 *
1682		 * EOF can return references to 'to-be-restored' objects,
1683		 * calling any method on them fully restores them, 'self' is
1684		 * the safest method to call.
1685		 */
1686		obj = [obj self];
1687#endif
1688
1689		if (obj == nil) {
1690			retobject = Py_None;
1691			Py_INCREF (retobject);
1692		} else {
1693			retobject = [obj  __pyobjc_PythonObject__];
1694		}
1695		break;
1696	}
1697
1698	case _C_SEL:
1699		if (*(SEL*)datum == NULL) {
1700			retobject = Py_None;
1701			Py_INCREF(retobject);
1702		} else {
1703			retobject = PyString_FromString(sel_getName(*(SEL*)datum));
1704		}
1705		break;
1706
1707	case _C_CLASS:
1708	{
1709		Class c = *(Class *) datum;
1710
1711		if (c == Nil) {
1712			retobject = Py_None;
1713			Py_INCREF (retobject);
1714		} else {
1715			retobject = (PyObject *) PyObjCClass_New(c);
1716		}
1717		break;
1718	}
1719
1720	case _C_PTR:
1721		if (type[1] == _C_VOID) {
1722			/* A void*. These are treated like unsigned integers. */
1723			retobject = (PyObject*)PyLong_FromUnsignedLongLong(
1724				*(unsigned long*)datum);
1725
1726		} else if (*(void**)datum == NULL) {
1727			retobject = Py_None;
1728			Py_INCREF(retobject);
1729
1730		} else {
1731			retobject = PyObjCPointerWrapper_ToPython(type, datum);
1732			if (retobject == NULL && !PyErr_Occurred()) {
1733				retobject = (PyObject*)PyObjCPointer_New(
1734					*(void**) datum, type+1);
1735			}
1736		}
1737		break;
1738
1739	case _C_UNION_B:
1740	{
1741		Py_ssize_t size = PyObjCRT_SizeOfType (type);
1742		if (size == -1) return NULL;
1743		retobject = PyString_FromStringAndSize ((void*)datum, size);
1744		break;
1745	}
1746
1747	case _C_STRUCT_B:
1748		retobject = pythonify_c_struct (type, datum);
1749		break;
1750
1751	case _C_ARY_B:
1752		retobject = pythonify_c_array (type, datum);
1753		break;
1754
1755	case _C_VOID:
1756		retobject = Py_None;
1757		Py_INCREF (retobject);
1758		break;
1759
1760	default:
1761		PyErr_Format(PyObjCExc_Error,
1762			"pythonify_c_value: unhandled value type (%c|%d|%s)",
1763			*type, *type, type);
1764		break;
1765	}
1766
1767	return retobject;
1768}
1769
1770
1771Py_ssize_t
1772PyObjCRT_SizeOfReturnType(const char* type)
1773{
1774	PyObjC_Assert(type != NULL, -1);
1775
1776#if 1 /* def __ppc__ */
1777	switch(*type) {
1778	case _C_CHR:
1779	case _C_BOOL:
1780	case _C_UCHR:
1781	case _C_SHT:
1782	case _C_USHT:
1783	case _C_UNICHAR:
1784	case _C_CHAR_AS_TEXT:
1785	case _C_CHAR_AS_INT:
1786	case _C_NSBOOL:
1787		return sizeof(long);
1788	default:
1789		return PyObjCRT_SizeOfType(type);
1790	}
1791#else
1792		return PyObjCRT_SizeOfType(type);
1793#endif
1794}
1795
1796/*
1797* Convert a python value to a basic C unsigned integer value.
1798*/
1799static int
1800depythonify_unsigned_int_value(
1801		PyObject* argument, char* descr,
1802		unsigned long long* out, unsigned long long max)
1803{
1804	PyObjC_Assert(argument != NULL, -1);
1805	PyObjC_Assert(descr != NULL, -1);
1806	PyObjC_Assert(out != NULL, -1);
1807
1808	if (PyInt_Check (argument)) {
1809		long temp = PyInt_AsLong(argument);
1810		if (PyErr_Occurred()) {
1811			return -1;
1812		}
1813#if 0
1814		/* Strict checking is nice, but a lot of constants are used
1815		 * as unsigned, but are actually negative numbers in the
1816		 * metadata files.
1817		 */
1818		if (temp < 0) {
1819			PyErr_Format(PyExc_ValueError,
1820				"depythonifying '%s', got negative '%s'",
1821					descr,
1822					argument->ob_type->tp_name);
1823			return -1;
1824
1825		} else
1826#endif
1827		if ((unsigned long long)temp > max) {
1828			PyErr_Format(PyExc_ValueError,
1829				"depythonifying '%s', got '%s' of "
1830				"wrong magnitude", descr,
1831					argument->ob_type->tp_name);
1832			return -1;
1833		}
1834		*out = temp;
1835		return 0;
1836
1837	} else if (PyLong_Check(argument)) {
1838		*out = PyLong_AsUnsignedLongLong(argument);
1839		if (PyErr_Occurred()) {
1840			PyErr_Format(PyExc_ValueError,
1841				"depythonifying '%s', got '%s' of "
1842				"wrong magnitude", descr,
1843					argument->ob_type->tp_name);
1844			return -1;
1845		}
1846
1847		if (*out > max) {
1848			PyErr_Format(PyExc_ValueError,
1849				"depythonifying '%s', got '%s' of "
1850				"wrong magnitude", descr,
1851					argument->ob_type->tp_name);
1852			return -1;
1853		}
1854		return 0;
1855
1856	} else {
1857		PyObject* tmp;
1858
1859		if (PyString_Check(argument) || PyUnicode_Check(argument)) {
1860			PyErr_Format(PyExc_ValueError,
1861				"depythonifying '%s', got '%s'",
1862					descr,
1863					argument->ob_type->tp_name);
1864			return -1;
1865		}
1866
1867		tmp = PyNumber_Long(argument);
1868		if (tmp != NULL) {
1869			*out = PyLong_AsUnsignedLongLong(tmp);
1870			if (PyErr_Occurred()) {
1871				return -1;
1872			}
1873			Py_DECREF(tmp);
1874
1875			if (*out <= max) {
1876				return 0;
1877			}
1878		}
1879
1880		PyErr_Format(PyExc_ValueError,
1881			"depythonifying '%s', got '%s'",
1882				descr,
1883				argument->ob_type->tp_name);
1884		return -1;
1885	}
1886}
1887
1888/*
1889* Convert a python value to a basic C signed integer value.
1890*/
1891static int
1892depythonify_signed_int_value(
1893		PyObject* argument, char* descr,
1894		long long* out, long long min, long long max)
1895{
1896	PyObjC_Assert(argument != NULL, -1);
1897	PyObjC_Assert(descr != NULL, -1);
1898	PyObjC_Assert(out != NULL, -1);
1899
1900	if (PyInt_Check (argument)) {
1901		*out = (long long)PyInt_AsLong(argument);
1902		if (PyErr_Occurred()) {
1903			return -1;
1904		}
1905		if (*out < min || *out > max) {
1906			PyErr_Format(PyExc_ValueError,
1907				"depythonifying '%s', got '%s' of "
1908				"wrong magnitude", descr,
1909					argument->ob_type->tp_name);
1910			return -1;
1911		}
1912		return 0;
1913
1914	} else if (PyLong_Check(argument)) {
1915		*out = PyLong_AsLongLong(argument);
1916		if (PyErr_Occurred()) {
1917			PyErr_Format(PyExc_ValueError,
1918				"depythonifying '%s', got '%s' of "
1919				"wrong magnitude", descr,
1920					argument->ob_type->tp_name);
1921			return -1;
1922		}
1923
1924		if (*out < min || *out > max) {
1925			PyErr_Format(PyExc_ValueError,
1926				"depythonifying '%s', got '%s' of "
1927				"wrong magnitude", descr,
1928					argument->ob_type->tp_name);
1929			return -1;
1930		}
1931		return 0;
1932
1933	} else {
1934		PyObject* tmp;
1935
1936		if (PyString_Check(argument) || PyUnicode_Check(argument)) {
1937			PyErr_Format(PyExc_ValueError,
1938				"depythonifying '%s', got '%s' of %"PY_FORMAT_SIZE_T"d",
1939					descr,
1940					argument->ob_type->tp_name,
1941					PyString_Size(argument));
1942			return -1;
1943		}
1944
1945
1946		tmp = PyNumber_Long(argument);
1947		if (tmp != NULL) {
1948			*out = PyLong_AsLongLong(tmp);
1949			Py_DECREF(tmp);
1950
1951			if (PyErr_Occurred()) {
1952				return -1;
1953			}
1954
1955			if (*out >= min && *out <= max) {
1956				return 0;
1957			}
1958		}
1959
1960		PyErr_Format(PyExc_ValueError,
1961			"depythonifying '%s', got '%s'",
1962				descr,
1963				argument->ob_type->tp_name);
1964		return -1;
1965	}
1966}
1967
1968int depythonify_c_return_value(
1969const char* type, PyObject* argument, void* datum)
1970{
1971	PyObjC_Assert(type != NULL, -1);
1972	PyObjC_Assert(argument != NULL, -1);
1973	PyObjC_Assert(datum != NULL, -1);
1974
1975#ifdef __ppc__
1976	long long temp;
1977	unsigned long long utemp;
1978	int       r;
1979
1980	/* Small integers are promoted to integers when returning them */
1981	switch (*type) {
1982#ifdef _C_BOOL
1983	case _C_BOOL:
1984	case _C_NSBOOL:
1985		if (PyObject_IsTrue(argument)) {
1986			*(int*) datum = YES;
1987		} else {
1988			*(int*) datum = NO;
1989		}
1990		return 0;
1991
1992#endif
1993	case _C_CHAR_AS_INT:
1994		r = depythonify_signed_int_value(argument, "char",
1995			&temp, CHAR_MIN, CHAR_MAX);
1996		if (r == 0) {
1997			*(int*)datum = temp;
1998		}
1999		return r;
2000
2001	case _C_CHAR_AS_TEXT:
2002		if (PyString_Check(argument) && PyString_Size(argument) == 1) {
2003			*(int*) datum = PyString_AsString (argument)[0];
2004			return 0;
2005		} else {
2006			PyErr_Format(PyExc_ValueError,
2007				"Expecting string of length 1");
2008			return -1;
2009		}
2010		break;
2011
2012	case _C_CHR:
2013		if (PyString_Check(argument) && PyString_Size(argument) == 1) {
2014			*(int*) datum = PyString_AsString (argument)[0];
2015			return 0;
2016		}
2017
2018		r = depythonify_signed_int_value(argument, "char",
2019			&temp, CHAR_MIN, CHAR_MAX);
2020		if (r == 0) {
2021			*(int*)datum = temp;
2022		}
2023		return r;
2024
2025	case _C_UNICHAR:
2026		if (PyUnicode_Check(argument) && PyUnicode_GetSize(argument) == 1) {
2027			*(int*)datum = (int)(*PyUnicode_AsUnicode(argument));
2028			return 0;
2029
2030		} else if (PyString_Check(argument)) {
2031			PyObject* u = PyUnicode_FromObject(argument);
2032			if (u == NULL) {
2033				return -1;
2034			}
2035			if (PyUnicode_Check(u) && PyUnicode_GetSize(u) == 1) {
2036				*(int*)datum = (int)(*PyUnicode_AsUnicode(u));
2037				Py_DECREF(u);
2038				return 0;
2039			}
2040			Py_DECREF(u);
2041		}
2042		PyErr_SetString(PyExc_ValueError, "Expecting unicode string of length 1");
2043		return -1;
2044
2045	case _C_UCHR:
2046		if (PyString_Check(argument) && PyString_Size(argument) == 1) {
2047			*(unsigned int*) datum =
2048				PyString_AsString (argument)[0];
2049			return 0;
2050		}
2051		r = depythonify_unsigned_int_value(argument, "unsigned char",
2052			&utemp, UCHAR_MAX);
2053		if (r == 0) {
2054			*(unsigned int*)datum = utemp;
2055		}
2056		return r;
2057
2058	case _C_SHT:
2059		r = depythonify_signed_int_value(argument, "short",
2060			&temp, SHRT_MIN, SHRT_MAX);
2061		if (r == 0) {
2062			*(int*)datum = temp;
2063		}
2064		return r;
2065
2066	case _C_USHT:
2067		r = depythonify_unsigned_int_value(argument, "unsigned short",
2068			&utemp, USHRT_MAX);
2069		if (r == 0) {
2070			*(unsigned int*)datum = utemp;
2071		}
2072		return r;
2073
2074	default:
2075		return depythonify_c_value(type, argument, datum);
2076	}
2077
2078#else
2079	return depythonify_c_value(type, argument, datum);
2080#endif
2081}
2082
2083PyObject *
2084pythonify_c_return_value (const char *type, void *datum)
2085{
2086	PyObjC_Assert(type != NULL, NULL);
2087	PyObjC_Assert(datum != NULL, NULL);
2088
2089#ifdef __ppc__
2090	/*
2091 	 * On PowerPC short and char return values are returned
2092 	 * as full-size ints.
2093	 */
2094	static  const char intType[] = { _C_INT, 0 };
2095	static  const char uintType[] = { _C_UINT, 0 };
2096
2097	switch(*type) {
2098	case _C_BOOL:
2099	case _C_NSBOOL:
2100		return PyBool_FromLong(*(int*)datum);
2101
2102	case _C_CHR:
2103	case _C_CHAR_AS_INT:
2104	case _C_SHT:
2105		return pythonify_c_value(intType, datum);
2106	case _C_UCHR: case _C_USHT:
2107		return pythonify_c_value(uintType, datum);
2108
2109	case _C_CHAR_AS_TEXT:
2110		{
2111			char ch = *(int*)datum;
2112			return PyString_FromStringAndSize(&ch, 1);
2113		}
2114
2115	case _C_UNICHAR:
2116		{
2117			Py_UNICODE ch = *(int*)datum;
2118			return PyUnicode_FromUnicode(&ch, 1);
2119		}
2120
2121	default:
2122		return pythonify_c_value(type, datum);
2123	}
2124
2125#else
2126	return pythonify_c_value(type, datum);
2127
2128#endif
2129}
2130
2131
2132int
2133depythonify_c_value (const char *type, PyObject *argument, void *datum)
2134{
2135	PyObjC_Assert(type != NULL, -1);
2136	PyObjC_Assert(argument != NULL, -1);
2137	PyObjC_Assert(datum != NULL, -1);
2138
2139	if (argument == NULL) abort();
2140
2141	/* Pass by reference output arguments are sometimes passed a NULL
2142	 * pointer, this surpresses a core dump.
2143	 */
2144	long long temp;
2145	unsigned long long utemp;
2146	int       r;
2147
2148	if (!datum) return 0;
2149
2150	type = PyObjCRT_SkipTypeQualifiers (type);
2151
2152	switch (*type) {
2153#ifdef _C_ATOM
2154	case _C_ATOM:
2155#endif
2156	case _C_CHARPTR:
2157		if (!PyString_Check (argument) && argument != Py_None) {
2158			PyErr_Format(PyExc_ValueError,
2159				"depythonifying 'charptr', got '%s'",
2160					argument->ob_type->tp_name);
2161			return -1;
2162		} else if (argument == Py_None) {
2163			*(char **) datum = NULL;
2164		} else {
2165			*(char **) datum = PyString_AS_STRING(
2166				(PyStringObject*)argument);
2167		}
2168		break;
2169
2170	case _C_CHR:
2171		if (PyString_Check(argument) && PyString_Size(argument) == 1) {
2172			*(char*) datum = PyString_AsString (argument)[0];
2173			return 0;
2174		}
2175
2176		r = depythonify_signed_int_value(argument, "char",
2177			&temp, CHAR_MIN, CHAR_MAX);
2178		if (r == 0) {
2179			*(char*)datum = temp;
2180		}
2181		return r;
2182
2183	case _C_CHAR_AS_INT:
2184		r = depythonify_signed_int_value(argument, "char",
2185			&temp, CHAR_MIN, CHAR_MAX);
2186		if (r == 0) {
2187			*(char*)datum = temp;
2188		}
2189		return r;
2190
2191	case _C_CHAR_AS_TEXT:
2192		if (PyString_Check(argument) && PyString_Size(argument) == 1) {
2193			*(char*) datum = PyString_AsString (argument)[0];
2194			return 0;
2195		} else {
2196			PyErr_SetString(PyExc_ValueError,
2197					"Expecting string of length 1");
2198			return -1;
2199		}
2200
2201	case _C_UCHR:
2202		if (PyString_Check(argument) && PyString_Size(argument) == 1) {
2203			*(unsigned char*) datum =
2204				PyString_AsString (argument)[0];
2205			return 0;
2206		}
2207		r = depythonify_unsigned_int_value(argument, "unsigned char",
2208			&utemp, UCHAR_MAX);
2209		if (r == 0) {
2210			*(unsigned char*)datum = utemp;
2211		}
2212		return r;
2213
2214	case _C_SHT:
2215		r = depythonify_signed_int_value(argument, "short",
2216			&temp, SHRT_MIN, SHRT_MAX);
2217		if (r == 0) {
2218			*(short*)datum = temp;
2219		}
2220		return r;
2221
2222	case _C_USHT:
2223		r = depythonify_unsigned_int_value(argument, "unsigned short",
2224			&utemp, USHRT_MAX);
2225		if (r == 0) {
2226			*(unsigned short*)datum = utemp;
2227		}
2228		return r;
2229
2230#ifdef _C_BOOL
2231	case _C_BOOL:
2232		*(bool*)datum = PyObject_IsTrue(argument);
2233		return 0;
2234#endif
2235
2236	case _C_NSBOOL:
2237		*(BOOL*)datum = PyObject_IsTrue(argument);
2238		return 0;
2239
2240	case _C_UNICHAR:
2241		if (PyUnicode_Check(argument) && PyUnicode_GetSize(argument) == 1) {
2242			*(UniChar*)datum = (UniChar)(*PyUnicode_AsUnicode(argument));
2243			return 0;
2244
2245		} else if (PyString_Check(argument)) {
2246			PyObject* u = PyUnicode_FromObject(argument);
2247			if (u == NULL) {
2248				return -1;
2249			}
2250			if (PyUnicode_Check(u) && PyUnicode_GetSize(u) == 1) {
2251				*(UniChar*)datum = (UniChar)(*PyUnicode_AsUnicode(u));
2252				Py_DECREF(u);
2253				return 0;
2254			}
2255			Py_DECREF(u);
2256		}
2257		PyErr_SetString(PyExc_ValueError, "Expecting unicode string of length 1");
2258		return -1;
2259
2260	case _C_INT:
2261		r = depythonify_signed_int_value(argument, "int",
2262			&temp, INT_MIN, INT_MAX);
2263		if (r == 0) {
2264			*(int*)datum = temp;
2265		}
2266		return r;
2267
2268	case _C_UINT:
2269		r = depythonify_unsigned_int_value(argument, "unsigned int",
2270			&utemp, UINT_MAX);
2271		if (r == 0) {
2272			*(unsigned int*)datum = utemp;
2273		}
2274		return r;
2275
2276	case _C_LNG:
2277		r = depythonify_signed_int_value(argument, "long",
2278			&temp, LONG_MIN, LONG_MAX);
2279		if (r == 0) {
2280			*(long*)datum = temp;
2281		}
2282		return r;
2283
2284	case _C_ULNG:
2285		r = depythonify_unsigned_int_value(argument, "unsigned long",
2286			&utemp, ULONG_MAX);
2287		if (r == 0) {
2288			*(unsigned long*)datum = utemp;
2289		}
2290		return r;
2291
2292	case _C_LNG_LNG:
2293		r = depythonify_signed_int_value(argument, "long long",
2294			&temp, LLONG_MIN, LLONG_MAX);
2295		if (r == 0) {
2296			*(long long*)datum = temp;
2297		}
2298		return r;
2299
2300	case _C_ULNG_LNG:
2301		r = depythonify_unsigned_int_value(argument,
2302			"unsigned long long", &utemp, ULLONG_MAX);
2303		if (r == 0) {
2304			*(unsigned long long*)datum = utemp;
2305		}
2306		return r;
2307
2308	case _C_ID:
2309		/*
2310			XXX
2311
2312			This should, for values other than Py_None, always return the same id
2313			for the same PyObject for as long as that id lives.  I think that the
2314			implementation of this should be moved to OC_PythonObject,
2315			which would itself have a map of PyObject->id.  The dealloc
2316			of each of these custom objects should notify OC_PythonObject
2317			to remove map entry.  We need to significantly change how immutable types
2318			are bridged, and create OC_PythonString, OC_PythonBool, etc. which are
2319			subclasses of what they should be from the the Objective C side.
2320
2321			If we don't do this, we break binary plist serialization, and likely
2322			other things, which assume that foo[bar] is foo[bar] for the duration of
2323			the serialization process.  I would imagine that other things also
2324			assume this kind of invariant, so we should do it here rather than in every
2325			container object.
2326		*/
2327
2328
2329		return [OC_PythonObject wrapPyObject:argument toId:(id *)datum];
2330
2331	case _C_CLASS:
2332		if (PyObjCClass_Check(argument))  {
2333			*(Class*) datum = PyObjCClass_GetClass(argument);
2334
2335		} else if (argument == Py_None) {
2336			*(Class*) datum = nil;
2337
2338		} else if (PyType_Check(argument) && PyType_IsSubtype((PyTypeObject*)argument, &PyObjCClass_Type)) {
2339			*(Class*) datum = PyObjCClass_GetClass(PyObjCClass_ClassForMetaClass(argument));
2340
2341		} else {
2342			PyErr_Format(PyExc_ValueError,
2343				"depythonifying 'Class', got '%s'",
2344					argument->ob_type->tp_name);
2345			return -1;
2346		}
2347		break;
2348
2349	case _C_SEL:
2350		if (argument == Py_None) {
2351			*(SEL*)datum = NULL;
2352		} else if (PyObjCSelector_Check (argument)) {
2353			*(SEL *) datum = PyObjCSelector_GetSelector(argument);
2354		} else if (PyString_Check(argument)) {
2355			char *selname = PyString_AsString (argument);
2356			SEL sel;
2357
2358			if (*selname == '\0') {
2359				*(SEL*)datum = NULL;
2360			} else {
2361				sel = sel_getUid (selname);
2362
2363				if (sel)  {
2364					*(SEL*) datum = sel;
2365				} else {
2366					PyErr_Format(PyExc_ValueError,
2367						"depythonifying 'SEL', cannot "
2368						"register string with runtime");
2369					return -1;
2370				}
2371			}
2372		} else {
2373			PyErr_Format(PyExc_ValueError,
2374				"depythonifying 'SEL', got '%s'",
2375					argument->ob_type->tp_name);
2376			return -1;
2377		}
2378		break;
2379
2380
2381	case _C_PTR:
2382		if (argument == Py_None) {
2383			*(void**)datum = NULL;
2384			return 0;
2385		}
2386		if (type[1] == _C_VOID) {
2387			r = depythonify_unsigned_int_value(argument,
2388				"unsigned long",
2389				&utemp, ULONG_MAX);
2390			if (r == 0) {
2391				*(void**)datum = (void*)(unsigned long)utemp;
2392			}
2393			return r;
2394
2395		}
2396		r = PyObjCPointerWrapper_FromPython(type, argument, datum);
2397		if (r == -1) {
2398			if (PyErr_Occurred()) {
2399				return -1;
2400			} else if (PyObjCPointer_Check (argument)) {
2401				*(void **) datum = PyObjCPointer_Ptr(argument);
2402			} else {
2403				PyErr_Format(PyExc_ValueError,
2404					"depythonifying 'pointer', got '%s'",
2405						argument->ob_type->tp_name);
2406				return -1;
2407			}
2408		}
2409		break;
2410
2411	case _C_FLT:
2412		if (PyFloat_Check (argument)) {
2413			*(float *) datum = (float)PyFloat_AsDouble (argument);
2414		} else if (PyInt_Check (argument)) {
2415			*(float *) datum = (float) PyInt_AsLong (argument);
2416		} else if (PyString_Check(argument) || PyUnicode_Check(argument)) {
2417			PyErr_Format(PyExc_ValueError,
2418				"depythonifying 'float', got '%s'",
2419					argument->ob_type->tp_name);
2420			return -1;
2421		} else {
2422			PyObject* tmp = PyNumber_Float(argument);
2423			if (tmp != NULL) {
2424				double dblval = PyFloat_AsDouble(tmp);
2425				Py_DECREF(tmp);
2426				*(float*) datum = dblval;
2427				return 0;
2428			}
2429
2430			PyErr_Format(PyExc_ValueError,
2431				"depythonifying 'float', got '%s'",
2432					argument->ob_type->tp_name);
2433			return -1;
2434		}
2435		break;
2436
2437	case _C_DBL:
2438		if (PyFloat_Check (argument)) {
2439			*(double *) datum = PyFloat_AsDouble (argument);
2440		} else if (PyInt_Check (argument)) {
2441			*(double *) datum = (double) PyInt_AsLong (argument);
2442		} else if (PyString_Check(argument) || PyUnicode_Check(argument)) {
2443			PyErr_Format(PyExc_ValueError,
2444				"depythonifying 'float', got '%s'",
2445					argument->ob_type->tp_name);
2446			return -1;
2447		} else {
2448			PyObject* tmp = PyNumber_Float(argument);
2449			if (tmp != NULL) {
2450				double dblval = PyFloat_AsDouble(tmp);
2451				Py_DECREF(tmp);
2452				*(double*) datum = dblval;
2453				return 0;
2454			}
2455
2456			PyErr_Format(PyExc_ValueError,
2457				"depythonifying 'double', got '%s'",
2458					argument->ob_type->tp_name);
2459			return -1;
2460		}
2461		break;
2462
2463	case _C_UNION_B:
2464		if (PyString_Check (argument)) {
2465			Py_ssize_t expected_size = PyObjCRT_SizeOfType (type);
2466
2467			if (expected_size == -1) {
2468				PyErr_Format(PyExc_ValueError,
2469					"depythonifying 'union' of "
2470					"unknown size");
2471				return -1;
2472			} else if (expected_size != PyString_Size (argument)) {
2473				PyErr_Format(PyExc_ValueError,
2474					"depythonifying 'union' of size %"PY_FORMAT_SIZE_T"d, "
2475					"got string of %"PY_FORMAT_SIZE_T"d",
2476						   expected_size,
2477						   PyString_Size (argument));
2478				return -1;
2479			} else {
2480				memcpy ((void *) datum,
2481					PyString_AS_STRING (argument),
2482				expected_size);
2483			}
2484		} else {
2485			PyErr_Format(PyExc_ValueError,
2486				"depythonifying 'union', got '%s'",
2487					argument->ob_type->tp_name);
2488			return -1;
2489		}
2490		break;
2491
2492	case _C_STRUCT_B:
2493		return depythonify_c_struct (type, argument, datum);
2494
2495	case _C_ARY_B:
2496		return depythonify_c_array (type, argument, datum);
2497
2498	default:
2499		PyErr_Format(PyExc_ValueError,
2500			"depythonifying unknown typespec %#x", *type);
2501		return -1;
2502	}
2503	return 0;
2504}
2505
2506const char*
2507PyObjCRT_RemoveFieldNames(char* buf, const char* type)
2508{
2509	PyObjC_Assert(buf != NULL, NULL);
2510	PyObjC_Assert(type != NULL, NULL);
2511
2512	const char* end;
2513	if (*type == '"') {
2514		type++;
2515		while (*type++ != '"') {}
2516	}
2517	end = PyObjCRT_SkipTypeQualifiers(type);
2518	if (end == NULL) {
2519		return NULL;
2520	}
2521	switch (*end) {
2522	case _C_STRUCT_B:
2523		/* copy struct header */
2524		while (*end && *end != '=' && *end != _C_STRUCT_E) {
2525			end++;
2526		}
2527		if (*end == '\0') {
2528			PyErr_SetString(PyExc_ValueError, "Bad type string");
2529			return NULL;
2530		}
2531		if (*end == _C_STRUCT_E) {
2532			end ++;
2533			memcpy(buf, type, end-type);
2534			buf[end-type] = '\0';
2535			return end;
2536		}
2537		end++;
2538		memcpy(buf, type, end-type);
2539		buf += end - type;
2540		type = end;
2541
2542		/* RemoveFieldNames until reaching end of struct */
2543		while (*type != _C_STRUCT_E) {
2544			end = PyObjCRT_RemoveFieldNames(buf, type);
2545			if (end == NULL) return NULL;
2546			buf += strlen(buf);
2547			type = end;
2548		}
2549		buf[0] = _C_STRUCT_E;
2550		buf[1] = '\0';
2551		return type+1;
2552
2553	case _C_ARY_B:
2554		/* copy array header */
2555		end ++;
2556		while(isdigit(*end)) { end++; }
2557
2558		memcpy(buf, type, end-type);
2559		buf += end - type;
2560		type = end;
2561		if (*type == _C_ARY_E) {
2562			buf[0] = _C_ARY_E;
2563			buf[1] = '\0';
2564			return type;
2565		}
2566
2567		/* RemoveFieldName until reaching end of array */
2568		end = PyObjCRT_RemoveFieldNames(buf, type);
2569		if (end == NULL) return NULL;
2570
2571		if (*end != _C_ARY_E) {
2572			PyErr_SetString(PyExc_ValueError, "bad type string");
2573			return NULL;
2574		}
2575
2576		buf += strlen(buf);
2577		type += end - type;
2578		buf[0] = _C_ARY_E;
2579		buf[1] = '\0';
2580		return end + 1;
2581		break;
2582
2583	default:
2584		end = PyObjCRT_SkipTypeSpec(end);
2585		if (end == NULL) return NULL;
2586
2587		memcpy(buf, type, end-type);
2588		buf[end-type] = '\0';
2589		return end;
2590	}
2591}
2592
2593
2594PyObject* PyObjCObject_NewTransient(id objc_object, int* cookie)
2595{
2596	return [(NSObject*)objc_object __pyobjc_PythonTransient__:cookie];
2597}
2598
2599void PyObjCObject_ReleaseTransient(PyObject* proxy, int cookie)
2600{
2601	if (cookie && proxy->ob_refcnt != 1) {
2602		CFRetain(PyObjCObject_GetObject(proxy));
2603		((PyObjCObject*)proxy)-> flags &= ~PyObjCObject_kSHOULD_NOT_RELEASE;
2604	}
2605	Py_DECREF(proxy);
2606}
2607