1/*
2 * A fast parser for BridgeSupport files.
3 *
4 * This file is an optimized processor for the bridgesupport files containing
5 * metadata about constants, functions, methods, ....
6 *
7 * TODO: check if we can gain further speed by moving the metadata to C
8 * structs instead of Python dictionaries (less object pressure->more speed?)
9 */
10#include "pyobjc.h"
11#include <dlfcn.h>
12
13
14/* Use the libxml2 parser */
15
16/* XXX: these are needed to avoid problems when using the system version
17 * of libxml:
18 */
19#include <libxml/xmlversion.h>
20#undef LIBXML_ICU_ENABLED
21#define ID _id
22
23#include <libxml/tree.h>
24#include <libxml/parser.h>
25
26#undef ID
27
28static PyObject* empty = NULL;
29static PyObject* empty_bytes = NULL;
30static PyObject* default_suggestion = NULL;
31static PyObject* setupCFClasses = NULL;
32static PyObject* structConvenience = NULL;
33
34
35/* Boolean attributes for argument/retval descriptors */
36static const char* gBooleanAttributes[] = {
37	"already_retained",
38	"already_cfretained",
39	"c_array_length_in_result",
40	"c_array_delimited_by_null",
41	"c_array_of_variable_length",
42	"printf_format",
43	"free_result",
44	NULL
45};
46
47/* Support for inlineTab lists */
48typedef void(*function_pointer)(void);
49struct functionlist {
50	char*    name;
51	function_pointer func;
52};
53
54static function_pointer find_function(struct functionlist* functions, char* name)
55{
56	if (functions == NULL) return NULL;
57	while (functions->name != NULL) {
58		if (strcmp(functions->name, name) == 0) {
59			return functions->func;
60		}
61		functions++;
62		}
63	return NULL;
64}
65
66/*
67 * Inline rewrite of typestrings from a metadata file.
68 * This fixes an issue with metadata files: metadata files use
69 * _C_BOOL to represent type 'BOOL', but that the string should
70 * be used to represent 'bool' which has a different size on
71 * PPC. Therefore swap usage of _C_BOOL and _C_NSBOOL in data
72 * from metadata files.
73 *
74 * returns true if given a valid typecode, false for some manner of syntax error
75 */
76static int typecode2typecode(char* buf)
77{
78	int rc;
79	/* Skip pointer declarations and anotations */
80	for (;;) {
81		switch(*buf) {
82		case _C_PTR:
83		case _C_IN:
84		case _C_OUT:
85		case _C_INOUT:
86		case _C_ONEWAY:
87		case _C_CONST:
88			buf++;
89			break;
90		default:
91		      goto exit;
92		}
93	}
94exit:
95
96	switch (*buf) {
97	case _C_BOOL:
98		*buf = _C_NSBOOL;
99		break;
100	case _C_NSBOOL:
101		*buf = _C_BOOL;
102		break;
103
104	case _C_STRUCT_B:
105		while (buf && *buf != _C_STRUCT_E && *buf && *buf++ != '=') {
106		}
107		while (buf && *buf && *buf != _C_STRUCT_E) {
108			if (*buf == '"') {
109				/* embedded field name */
110				buf = strchr(buf+1, '"');
111				if (buf == NULL) {
112					return 0;
113				}
114				buf++;
115			}
116			rc = typecode2typecode(buf);
117			buf = (char*)PyObjCRT_SkipTypeSpec(buf);
118			if (buf == NULL || rc == 0) {
119			    return 0;
120			}
121		}
122		break;
123
124	case _C_UNION_B:
125		while (buf && *buf != _C_UNION_E && *buf && *buf++ != '=') {
126		}
127		while (buf && *buf && *buf != _C_UNION_E) {
128			if (*buf == '"') {
129				/* embedded field name */
130				buf = strchr(buf+1, '"');
131				if (buf == NULL) {
132					return 0;
133				}
134				buf++;
135			}
136			rc = typecode2typecode(buf);
137			buf = (char*)PyObjCRT_SkipTypeSpec(buf);
138			if (buf == NULL || rc == 0) {
139			    return 0;
140			}
141		}
142		break;
143
144
145	case _C_ARY_B:
146		while (isdigit(*++buf));
147		return typecode2typecode(buf);
148		break;
149	}
150	return 1;
151}
152
153/* Returns true for Ok, 0 for some sort of syntax error */
154static int typestr2typestr(char* buf)
155{
156	while (buf && *buf) {
157		if (typecode2typecode(buf) == 0)
158		    return 0;
159		if (buf && *buf == '\"') {
160			PyErr_Format(PyObjCExc_InternalError,
161				"typecode2typecode: invalid typecode '%c' at \"%s\"",
162				*buf, buf);
163			*buf = '\0';
164		} else {
165			buf = (char*)PyObjCRT_SkipTypeSpec(buf);
166		}
167	}
168	return 1;
169}
170
171int
172PyObjCXML_Init(void)
173{
174	/* This kinda sucks: libxml will abort when
175	 * it decides it's version doesn't match our
176	 * version.
177	 */
178	LIBXML_TEST_VERSION
179
180	empty = PyText_InternFromString("");
181	if (empty == NULL) {
182		return -1;
183	}
184
185	empty_bytes = PyBytes_InternFromString("");
186	if (empty == NULL) {
187		return -1;
188	}
189
190	default_suggestion = PyText_InternFromString("don't use this method");
191	if (default_suggestion == NULL) {
192		return -1;
193	}
194
195
196	return 0;
197}
198
199static inline char*
200attribute_string(xmlNode* node, const char* name, char* name64
201#ifndef __LP64__
202	__attribute__((__unused__))
203#endif
204)
205{
206	char* value = (char*)xmlGetProp(node, (xmlChar*)name);
207#ifdef __LP64__
208	/* The 64-bit value defaults to the same as the 32-bit value */
209	if (name64 != NULL) {
210		char* value64 = (char*)xmlGetProp(node, (xmlChar*)name64);
211		if (value64 != NULL) {
212			if (value != NULL) {
213				xmlFree(value);
214			}
215			value = value64;
216		}
217	}
218#endif
219
220	return value;
221}
222
223static inline BOOL
224attribute_bool(xmlNode* node, const char* name, char* name64, BOOL dflt)
225{
226	char* value = attribute_string(node, name, name64);
227	if (value == NULL) {
228		return dflt;
229	}
230
231	if (strcmp(value, "true") == 0) {
232		xmlFree(value);
233		return YES;
234	} else {
235		xmlFree(value);
236		return NO;
237	}
238}
239
240static PyObject*
241xmlToArgMeta(xmlNode* node, BOOL isMethod, int* argIdx)
242{
243	if (argIdx != NULL) {
244		char* end;
245		char* v = attribute_string(node, "index", NULL);
246		if (v == NULL) {
247			PyErr_SetString(PyExc_AttributeError, "no argument index");
248			*argIdx = -1;
249			return NULL;
250		}
251		*argIdx = strtol(v, &end, 10);
252		if (end && *end != '\0') {
253			PyErr_SetString(PyExc_ValueError, v);
254		}
255		xmlFree(v);
256	}
257
258	PyObject* result = PyDict_New();
259	if (result == NULL) {
260		return NULL;
261	}
262
263	PyObject* v;
264	char* s;
265	int r;
266
267	BOOL typeIsBlock = NO;
268	s = attribute_string(node, "type", "type64");
269	typestr2typestr(s);
270
271	if (s && *s) {
272		typeIsBlock = (strcmp(s, "@?") == 0);
273		v = PyBytes_InternFromString(s);
274		if (v == NULL) {
275			xmlFree(s);
276			Py_DECREF(result);
277			return NULL;
278		}
279		r =  PyDict_SetItemString(result, "type", v);
280		Py_DECREF(v);
281		if (r == -1) {
282			xmlFree(s);
283			Py_DECREF(result);
284			return NULL;
285		}
286	}
287	if (s) xmlFree(s);
288
289	s = attribute_string(node, "type_modifier", NULL);
290	if (s && *s) {
291		v = PyBytes_InternFromString(s);
292		if (v == NULL) {
293			xmlFree(s);
294			Py_DECREF(result);
295			return NULL;
296		}
297		r =  PyDict_SetItemString(result, "type_modifier", v);
298		Py_DECREF(v);
299		if (r == -1)  {
300			xmlFree(s);
301			Py_DECREF(result);
302			return NULL;
303		}
304	}
305	if (s) xmlFree(s);
306
307	s = attribute_string(node, "sel_of_type", "sel_of_type64");
308	typestr2typestr(s);
309	if (s && *s) {
310		v = PyBytes_InternFromString(s);
311		if (v == NULL) {
312			xmlFree(s);
313			Py_DECREF(result);
314			return NULL;
315		}
316		r =  PyDict_SetItemString(result, "sel_of_type", v);
317		Py_DECREF(v);
318		if (r == -1)  {
319			xmlFree(s);
320			Py_DECREF(result);
321			return NULL;
322		}
323	}
324	if (s) xmlFree(s);
325
326	s = attribute_string(node, "c_array_of_fixed_length", NULL);
327	if (s && *s) {
328		char* end;
329		v = PyObjC_IntFromString(s, &end, 10);
330		if (v == NULL) {
331			xmlFree(s);
332			Py_DECREF(result);
333			return NULL;
334		}
335		if (end && *end != '\0') {
336			PyErr_SetString(PyExc_ValueError, s);
337			xmlFree(s);
338			Py_DECREF(result);
339			Py_DECREF(v);
340			return NULL;
341		}
342		r =  PyDict_SetItemString(result, "c_array_of_fixed_length", v);
343		Py_DECREF(v);
344		if (r == -1) {
345			xmlFree(s);
346			Py_DECREF(result);
347			return NULL;
348		}
349	}
350	if (s) xmlFree(s);
351
352	const char** bool_attrs = gBooleanAttributes;
353	for (; *bool_attrs != NULL; bool_attrs++) {
354		if (attribute_bool(node, *bool_attrs, NULL, NO)) {
355			r = PyDict_SetItemString(result, *bool_attrs, Py_True);
356			if (r == -1) {
357				Py_DECREF(result);
358				return NULL;
359			}
360#if 0
361		/* Don't store default value */
362		} else {
363			r = PyDict_SetItemString(result, *bool_attrs, Py_False);
364			if (r == -1) {
365				Py_DECREF(result);
366				return NULL;
367			}
368#endif
369		}
370	}
371
372	if (attribute_bool(node, "null_accepted", NULL, YES)) {
373#if 0
374		/* Don't store default value */
375		r = PyDict_SetItemString(result, "null_accepted", Py_True);
376#else
377		r = 0;
378#endif
379	} else {
380		r = PyDict_SetItemString(result, "null_accepted", Py_False);
381	}
382	if (r == -1) {
383		Py_DECREF(result);
384		return NULL;
385	}
386
387
388	s = attribute_string(node, "c_array_length_in_arg", NULL);
389	if (s && *s) {
390		char* end = strchr(s, ',');
391
392		if (end == NULL) {
393			int input = strtol(s, &end, 10);
394			if (end && *end != '\0') {
395				PyErr_SetString(PyExc_ValueError, s);
396				Py_DECREF(result);
397				xmlFree(s);
398				return NULL;
399			}
400
401			if (isMethod) {
402				v = PyObjC_IntFromLong(input + 2);
403			} else {
404				v = PyObjC_IntFromLong(input);
405			}
406			if (v == NULL) {
407				Py_DECREF(result);
408				xmlFree(s);
409				return NULL;
410			}
411
412			r = PyDict_SetItemString(result, "c_array_length_in_arg", v);
413			Py_DECREF(v);
414			if (r == -1) {
415				Py_DECREF(result);
416				xmlFree(s);
417				return NULL;
418			}
419		} else {
420			int input, output;
421			char* x;
422
423			input = strtol(s, &x, 10);
424			if (x != end) {
425				PyErr_SetString(PyExc_ValueError, s);
426				Py_DECREF(result);
427				xmlFree(s);
428				return NULL;
429			}
430			output = strtol(end+1, &x, 10);
431			if (*x != '\0') {
432				PyErr_SetString(PyExc_ValueError, s);
433				Py_DECREF(result);
434				xmlFree(s);
435				return NULL;
436			}
437
438			if (isMethod) {
439				v = Py_BuildValue("ii", input+2, output+2);
440			} else {
441				v = Py_BuildValue("ii", input, output);
442			}
443			if (v == NULL) {
444				Py_DECREF(result);
445				xmlFree(s);
446				return NULL;
447			}
448
449			r = PyDict_SetItemString(result, "c_array_length_in_arg", v);
450			Py_DECREF(v);
451			if (r == -1) {
452				Py_DECREF(result);
453				xmlFree(s);
454				return NULL;
455			}
456		}
457
458	}
459	if (s) xmlFree(s);
460
461	if (attribute_bool(node, "function_pointer", NULL, NO) || attribute_bool(node, "block", NULL, NO)) {
462		/* Function argument is a function pointer or a block, there are
463		 * subelements describing the full type
464		 */
465		v = PyBool_FromLong(
466				attribute_bool(node, "function_pointer_retained", NULL, YES));
467		if (v == NULL) {
468			Py_DECREF(result);
469			return NULL;
470		}
471		r = PyDict_SetItemString(result, "callable_retained", v);
472		if (r == -1) {
473			Py_DECREF(result);
474			return NULL;
475		}
476
477		PyObject* meta = PyDict_New();
478		if (meta == NULL) {
479			Py_DECREF(result);
480			return NULL;
481		}
482		r = PyDict_SetItemString(result, "callable", meta);
483		Py_DECREF(meta);
484		if (r == -1) {
485			Py_DECREF(result);
486			return NULL;
487		}
488
489		PyObject* arguments = PyDict_New();
490		if (arguments == NULL) {
491			Py_DECREF(result);
492			return NULL;
493		}
494		r = PyDict_SetItemString(meta, "arguments", arguments);
495		Py_DECREF(arguments);
496		if (r == -1) {
497			Py_DECREF(result);
498			return NULL;
499		}
500
501		xmlNode* al;
502		int idx = 0;
503		if (attribute_bool(node, "block", NULL, NO) || typeIsBlock) {
504			/* Blocks have an implict first argument, include that in the
505			 * argument list.
506			 */
507			PyObject* a = PyDict_New();
508			if (a == NULL) {
509				Py_DECREF(result);
510				return NULL;
511			}
512			PyObject* av = PyBytes_InternFromString("^v");
513			if (av == NULL) {
514				Py_DECREF(a);
515				Py_DECREF(result);
516				return NULL;
517			}
518			PyDict_SetItemString(a, "type", av);
519			Py_DECREF(av);
520
521			av = PyObjC_IntFromLong(idx++);
522			if (av == NULL) {
523				Py_DECREF(a);
524				Py_DECREF(av);
525				Py_DECREF(result);
526				return NULL;
527			}
528			r = PyDict_SetItem(arguments, av, a);
529			Py_DECREF(av); Py_DECREF(a);
530			if (r == -1) {
531				Py_DECREF(result);
532				return NULL;
533			}
534
535		}
536		for (al = node->children; al != NULL; al = al->next) {
537			if (al->type != XML_ELEMENT_NODE)  {
538				continue;
539			}
540			if (strcmp((char*)al->name, "arg") == 0) {
541				PyObject* d = PyObjC_InternValue(xmlToArgMeta(al, NO, NULL));
542				if (d == NULL) {
543					Py_DECREF(result);
544					return NULL;
545				}
546				v = PyObjC_IntFromLong(idx++);
547				if (v == NULL) {
548					Py_DECREF(d);
549					Py_DECREF(v);
550					Py_DECREF(result);
551					return NULL;
552				}
553
554				r = PyDict_SetItem(arguments, v, d);
555				Py_DECREF(v); Py_DECREF(d);
556				if (r == -1) {
557					Py_DECREF(result);
558					return NULL;
559				}
560			} else if (strcmp((char*)al->name, "retval") == 0) {
561				PyObject* d = PyObjC_InternValue(xmlToArgMeta(al, NO, NULL));
562				if (d == NULL) {
563					Py_DECREF(result);
564					return NULL;
565				}
566
567				r = PyDict_SetItemString(meta, "retval", d);
568				Py_DECREF(d);
569				if (r == -1) {
570					Py_DECREF(result);
571					return NULL;
572				}
573			}
574		}
575	}
576
577	return result;
578}
579
580static inline int
581handle_opaque(xmlNode* cur_node, PyObject* globalDict)
582{
583	char* name = attribute_string(cur_node, "name", NULL);
584	char* type = attribute_string(cur_node, "type", "type64");
585
586	typestr2typestr(type);
587
588	if (name != NULL && type != NULL && *type != '\0' ) {
589		/* We've found a valid opaque type */
590		PyObject* value = PyObjCCreateOpaquePointerType(
591			name, type, "");
592		if (value == NULL) {
593			if (name) xmlFree(name);
594			if (type) xmlFree(type);
595			return -1;
596		}
597
598		int r = PyDict_SetItemString(globalDict, name, value);
599		Py_DECREF(value);
600		if (r == -1) {
601			if (name) xmlFree(name);
602			if (type) xmlFree(type);
603			return -1;
604		}
605	}
606	if (name) xmlFree(name);
607	if (type) xmlFree(type);
608	return 0;
609}
610
611static inline int
612handle_constant(xmlNode* cur_node, PyObject* globalDict)
613{
614	char* name = attribute_string(cur_node, "name", NULL);
615	char* type = attribute_string(cur_node, "type", "type64");
616
617	typestr2typestr(type);
618
619	if (name != NULL && type != NULL && *type != '\0' ) {
620		if (type[0] == _C_STRUCT_B) {
621			/*
622			 * We do not yet correctly handle structs with embedded
623			 * function pointers, this check locates those (and
624			 * some more).
625			 */
626			char* e = strchr(type, '=');
627			if (e != NULL && strchr(e, '?') != NULL) {
628				if (name) xmlFree(name);
629				if (type) xmlFree(type);
630				return 0;
631			}
632		}
633
634		BOOL magic = attribute_bool(cur_node, "magic_cookie", NULL, NO);
635
636		void* buf = dlsym(RTLD_DEFAULT, name);
637
638		PyObject* v;
639		if (buf != NULL) {
640			if (magic) {
641				v = PyObjCCF_NewSpecial(type, buf);
642			} else {
643				v = pythonify_c_value(type, buf);
644			}
645
646			if (v == NULL) {
647				if (name) xmlFree(name);
648				if (type) xmlFree(type);
649				return -1;
650			}
651
652			v = PyObjC_InternValue(v);
653			if (v == NULL) {
654				if (name) xmlFree(name);
655				if (type) xmlFree(type);
656				return -1;
657			}
658
659			int r = PyDict_SetItemString(globalDict, name, v);
660			if (r == -1) {
661				if (name) xmlFree(name);
662				if (type) xmlFree(type);
663				return -1;
664			}
665		}
666	}
667	if (name) xmlFree(name);
668	if (type) xmlFree(type);
669	return 0;
670}
671
672static inline int
673handle_string_constant(xmlNode* cur_node, PyObject* globalDict)
674{
675	char* name = attribute_string(cur_node, "name", NULL);
676	char* value = attribute_string(cur_node, "value", "value64");
677	BOOL nsstring = attribute_bool(cur_node, "nsstring", NULL, NO);
678
679	if (name != NULL && value != NULL && *value != '\0') {
680		size_t len = strlen(value);
681		PyObject* v;
682		if (nsstring) {
683			v = PyUnicode_DecodeUTF8(value, len, "strict");
684		} else {
685			v = PyBytes_InternFromStringAndSize(value, len);
686		}
687		if (v == NULL) {
688			if (name) xmlFree(name);
689			if (value) xmlFree(value);
690			return -1;
691		}
692
693		int r = PyDict_SetItemString(globalDict, name, v);
694		Py_DECREF(v);
695		if (r == -1) {
696			if (name) xmlFree(name);
697			if (value) xmlFree(value);
698			return -1;
699		}
700	}
701
702	if (name) xmlFree(name);
703	if (value) xmlFree(value);
704	return 0;
705}
706
707static inline int
708handle_enum(xmlNode* cur_node, PyObject* globalDict)
709{
710	char* name = attribute_string(cur_node, "name", NULL);
711	char* value = attribute_string(cur_node, "value", "value64");
712
713	if (value == NULL) {
714#ifdef __BIGENDIAN__
715		value = attribute_string(cur_node, "be_value", NULL);
716#else
717		value = attribute_string(cur_node, "le_value", NULL);
718#endif
719	}
720
721	if (name != NULL && value != NULL && *value != '\0') {
722		PyObject* v;
723		char* end;
724
725		if (strchr(value, '.') != NULL) {
726			/* floating point literal */
727			PyObject* s = PyText_FromString(value);
728			if (s == NULL) {
729				v = NULL;
730
731			} else {
732#if PY_MAJOR_VERSION == 2
733				v = PyFloat_FromString(s, &end);
734#else
735				v = PyFloat_FromString(s);
736				end = NULL;
737#endif
738				Py_DECREF(s);
739			}
740		} else {
741			/* integer literal */
742			v = PyObjC_IntFromString(value, &end, 10);
743		}
744
745		if (v == NULL) {
746			if (name) xmlFree(name);
747			if (value) xmlFree(value);
748			return -1;
749		}
750		if (end && *end != '\0') {
751			/* Junk at the end of the literal */
752			PyErr_SetString(PyExc_ValueError,
753				"Junk in enum value");
754			if (name) xmlFree(name);
755			if (value) xmlFree(value);
756			Py_DECREF(v);
757			return -1;
758		}
759
760		int r  = PyDict_SetItemString(globalDict, name, v);
761		Py_DECREF(v);
762		if (r == -1) {
763			if (name) xmlFree(name);
764			if (value) xmlFree(value);
765			return -1;
766		}
767	}
768
769	if (name) xmlFree(name);
770	if (value) xmlFree(value);
771	return 0;
772}
773
774static inline int
775handle_null_const(xmlNode* cur_node, PyObject* globalDict)
776{
777	char* name = attribute_string(cur_node, "name", NULL);
778
779	if (name != NULL) {
780		int r  = PyDict_SetItemString(globalDict, name, Py_None);
781		if (r == -1) {
782			if (name) xmlFree(name);
783			return -1;
784		}
785	}
786
787	if (name) xmlFree(name);
788	return 0;
789}
790
791static inline int
792handle_function_pointer(xmlNode* cur_node, PyObject* func_aliases)
793{
794	char* name = attribute_string(cur_node, "name", NULL);
795	char* original = attribute_string(cur_node, "original", NULL);
796
797	if (name != NULL && original != NULL) {
798		PyObject* v = Py_BuildValue("ss", name, original);
799		if (v == NULL) {
800			if (name) xmlFree(name);
801			if (original) xmlFree(original);
802			return -1;
803		}
804		int r = PyList_Append(func_aliases, v);
805		Py_DECREF(v);
806		if (r == -1) {
807			if (name) xmlFree(name);
808			if (original) xmlFree(original);
809			return -1;
810		}
811	}
812
813	if (name) xmlFree(name);
814	if (original) xmlFree(original);
815	return 0;
816}
817
818
819static inline int
820handle_cftype(xmlNode* cur_node, PyObject* globalDict, PyObject* cftypes)
821{
822	char* name = attribute_string(cur_node, "name", NULL);
823	char* type = attribute_string(cur_node, "type", "type64");
824	char* funcname = attribute_string(cur_node, "gettypeid_func", NULL);
825	char* tollfree = attribute_string(cur_node, "tollfree", NULL);
826	int retval = -1;
827	PyObject* v;
828
829	if (!typestr2typestr(type)) {
830		PyErr_Format(PyExc_SyntaxError, "Syntax error for cftype %s\n", name);
831		goto end;
832	}
833
834	if (name == NULL || type == NULL || *type == '\0') {
835		retval = 0;
836		goto end;
837	}
838
839	if (tollfree == NULL && funcname == NULL) {
840		PyErr_Format(PyExc_ValueError, "cftype for '%s' must include gettypeid_func, tollfree or both", name);
841		goto end;
842	}
843
844	if (tollfree != NULL) {
845		Class cls = objc_lookUpClass(tollfree);
846		if (cls == NULL) {
847			if (tollfree[0] == '_' && tollfree[1] == '_') {
848				cls = objc_lookUpClass(tollfree+2);
849			}
850		}
851
852		if (cls == NULL) {
853			retval = 0;
854			goto end;
855		}
856		if (PyObjCPointerWrapper_RegisterID(type) == -1) {
857			goto end;
858		}
859		v = PyObjCClass_New(cls);
860
861	} else {
862		CFTypeID (*getfunc)(void) = NULL;
863
864		if (funcname != NULL) {
865			getfunc = dlsym(RTLD_DEFAULT, funcname);
866		}
867
868		if (getfunc == NULL) {
869			/* Annoyingly enough not all public CFTypes have
870			 * a GetTypeID function, proxy all those using
871			 * the generic cftype wrapper.
872			 */
873			Class cls = objc_lookUpClass("NSCFType");
874			if (cls == NULL) {
875				PyErr_SetString(PyObjCExc_NoSuchClassError,
876					"NSCFType");
877				goto end;
878			}
879			if (PyObjCPointerWrapper_RegisterID(type) == -1) {
880				goto end;
881			}
882			v = PyObjCClass_New(cls);
883		} else {
884			CFTypeID typeid = getfunc();
885
886			v = PyObjC_IntFromLong(typeid);
887			if (v == NULL) {
888				goto end;
889			}
890			int r = PyDict_SetItemString(PyObjC_TypeStr2CFTypeID, type, v);
891			Py_DECREF(v);
892			if (r == -1) {
893				goto end;
894			}
895
896			v = PyObjCCFType_New(name, type, typeid);
897
898			if (v != NULL && cftypes != NULL) {
899				PyObject* e = Py_BuildValue("ss", name, type);
900				if (e != NULL) {
901					PyList_Append(cftypes, e);
902					Py_DECREF(e);
903				}
904
905				// Ignore errors while building this list.
906				PyErr_Clear();
907			}
908
909		}
910	}
911
912	retval = 0;
913
914	if (v != NULL) {
915		retval = PyDict_SetItemString(globalDict, name, v);
916		Py_DECREF(v);
917	}
918
919end:
920	if (name) xmlFree(name);
921	if (type) xmlFree(type);
922	if (funcname) xmlFree(funcname);
923	if (tollfree) xmlFree(tollfree);
924	return retval;
925}
926
927static inline int
928handle_class(xmlNode* cur_node)
929{
930	int r;
931	char* classname = attribute_string(cur_node, "name", NULL);
932	PyObject* pyClassname = NULL;
933	if (classname == NULL) return 0;
934
935	xmlNode* method;
936	for (method = cur_node->children; method != NULL; method = method->next) {
937		if (method->type != XML_ELEMENT_NODE)  {
938			continue;
939		}
940		if (strcmp((char*)method->name, "method") != 0) {
941			/* Ignore other elements */
942			continue;
943		}
944
945
946		char* selname = attribute_string(method, "selector", NULL);
947		if (selname == NULL) continue;
948
949		BOOL variadic = attribute_bool(method, "variadic", NULL, NO);
950		BOOL c_array = attribute_bool(method, "c_array_delimited_by_null", NULL, NO);
951		char* c_length = attribute_string(method, "c_array_length_in_arg", NULL);
952		BOOL ignore = attribute_bool(method, "ignore", NULL, NO);
953
954		PyObject* metadata = PyDict_New();
955		if (metadata == NULL) {
956			Py_XDECREF(pyClassname);
957			xmlFree(selname);
958			xmlFree(classname);
959			return -1;
960		}
961
962		if (ignore) {
963			char* suggestion = attribute_string(method, "suggestion", NULL);
964			if (suggestion == NULL) {
965				r = PyDict_SetItemString(metadata, "suggestion", default_suggestion);
966				if (r == -1) {
967					Py_DECREF(metadata);
968					Py_XDECREF(pyClassname);
969					xmlFree(selname);
970					xmlFree(classname);
971					return -1;
972				}
973
974			} else {
975				PyObject* v = PyText_InternFromString(suggestion);
976				xmlFree(suggestion);
977
978				r = PyDict_SetItemString(metadata, "suggestion", v);
979				Py_DECREF(v);
980				if (r == -1) {
981					Py_DECREF(metadata);
982					Py_XDECREF(pyClassname);
983					xmlFree(selname);
984					xmlFree(classname);
985					return -1;
986				}
987			}
988		}
989
990		PyObject* v = PyBool_FromLong(variadic);
991		if (v == NULL) {
992			Py_DECREF(metadata);
993			Py_XDECREF(pyClassname);
994			xmlFree(selname);
995			xmlFree(classname);
996			return -1;
997		}
998		r = PyDict_SetItemString(metadata, "variadic", v);
999		Py_DECREF(v);
1000		if (r == -1) {
1001			Py_DECREF(metadata);
1002			Py_XDECREF(pyClassname);
1003			xmlFree(selname);
1004			xmlFree(classname);
1005			return -1;
1006		}
1007
1008		if (variadic) {
1009			v = PyBool_FromLong(c_array);
1010			if (v == NULL) {
1011				Py_DECREF(metadata);
1012				Py_XDECREF(pyClassname);
1013				xmlFree(selname);
1014				xmlFree(classname);
1015				return -1;
1016			}
1017			r = PyDict_SetItemString(metadata, "c_array_delimited_by_null", v);
1018			if (r == -1) {
1019				Py_DECREF(metadata);
1020				Py_XDECREF(pyClassname);
1021				xmlFree(selname);
1022				xmlFree(classname);
1023				return -1;
1024			}
1025
1026			if (c_length != NULL) {
1027				long cnt = strtol(c_length, NULL, 10);
1028
1029				v = PyObjC_IntFromLong(cnt);
1030				if (v == NULL) {
1031					Py_DECREF(metadata);
1032					Py_XDECREF(pyClassname);
1033					xmlFree(selname);
1034					xmlFree(classname);
1035					return -1;
1036				}
1037				r = PyDict_SetItemString(metadata, "c_array_length_in_arg", v);
1038				if (r == -1) {
1039					Py_DECREF(metadata);
1040					Py_XDECREF(pyClassname);
1041					xmlFree(selname);
1042					xmlFree(classname);
1043					return -1;
1044				}
1045			}
1046		}
1047
1048		PyObject* arguments = PyDict_New();
1049		if (arguments == NULL) {
1050			Py_DECREF(metadata);
1051			Py_XDECREF(pyClassname);
1052			xmlFree(selname);
1053			xmlFree(classname);
1054			return -1;
1055		}
1056		r = PyDict_SetItemString(metadata, "arguments", arguments);
1057		Py_DECREF(arguments);
1058		if (r == -1) {
1059			Py_DECREF(metadata);
1060			Py_XDECREF(pyClassname);
1061			xmlFree(selname);
1062			xmlFree(classname);
1063			return -1;
1064		}
1065
1066		xmlNode* al;
1067		for (al = method->children; al != NULL; al = al->next) {
1068			if (al->type != XML_ELEMENT_NODE)  {
1069				continue;
1070			}
1071
1072			if (strcmp((char*)al->name, "arg") == 0) {
1073				int argIdx;
1074				PyObject* d = PyObjC_InternValue(xmlToArgMeta(al, YES, &argIdx));
1075				if (d == NULL) {
1076					Py_DECREF(metadata);
1077					Py_XDECREF(pyClassname);
1078					xmlFree(selname);
1079					xmlFree(classname);
1080					return -1;
1081				}
1082
1083				PyObject* idx = PyObjC_IntFromLong(argIdx+2);
1084				if (idx == NULL) {
1085					Py_DECREF(d);
1086					Py_DECREF(metadata);
1087					Py_XDECREF(pyClassname);
1088					xmlFree(selname);
1089					xmlFree(classname);
1090					return -1;
1091				}
1092
1093				r = PyDict_SetItem(arguments, idx, d);
1094				Py_DECREF(idx);
1095				Py_DECREF(d);
1096				if (r == -1) {
1097					Py_DECREF(metadata);
1098					Py_XDECREF(pyClassname);
1099					xmlFree(selname);
1100					xmlFree(classname);
1101					return -1;
1102				}
1103
1104			} else if (strcmp((char*)al->name, "retval") == 0) {
1105				PyObject* d = PyObjC_InternValue(xmlToArgMeta(al, YES, NULL));
1106				if (d == NULL) {
1107					Py_DECREF(metadata);
1108					Py_XDECREF(pyClassname);
1109					xmlFree(selname);
1110					xmlFree(classname);
1111					return -1;
1112				}
1113
1114				r = PyDict_SetItemString(metadata, "retval", d);
1115				Py_DECREF(d);
1116				if (r == -1) {
1117					Py_DECREF(metadata);
1118					Py_XDECREF(pyClassname);
1119					xmlFree(selname);
1120					xmlFree(classname);
1121					return -1;
1122				}
1123			}
1124		}
1125
1126		/* Complete metadata for a method, register it */
1127		if (pyClassname == NULL) {
1128			pyClassname = PyBytes_InternFromString(classname);
1129			if (pyClassname == NULL) {
1130				Py_DECREF(metadata);
1131				xmlFree(selname);
1132				xmlFree(classname);
1133				return -1;
1134			}
1135		}
1136
1137		PyObject* pySelector = PyBytes_InternFromString(selname);
1138		xmlFree(selname);
1139		if (pySelector == NULL) {
1140			Py_DECREF(pyClassname);
1141			Py_DECREF(metadata);
1142			xmlFree(classname);
1143			return -1;
1144		}
1145
1146		metadata = PyObjC_InternValue(metadata);
1147		if (metadata == NULL) {
1148			Py_DECREF(pyClassname);
1149			Py_DECREF(pySelector);
1150			return -1;
1151		}
1152
1153
1154		r = PyObjC_registerMetaData(pyClassname, pySelector, metadata);
1155		Py_DECREF(pySelector);
1156		Py_DECREF(metadata);
1157
1158		if (r < 0) {
1159			Py_XDECREF(pyClassname);
1160			xmlFree(classname);
1161			return -1;
1162		}
1163	}
1164
1165	Py_XDECREF(pyClassname);
1166	xmlFree(classname);
1167	return 0;
1168}
1169
1170static inline int
1171handle_function(xmlNode* cur_node, PyObject* globalDict, struct functionlist* inlineTab)
1172{
1173	char* name = attribute_string(cur_node, "name", NULL);
1174	if (name == NULL) return 0;
1175
1176	void* function = dlsym(RTLD_DEFAULT, name);
1177	if (function == NULL) {
1178		/* Look in the inlineTab if we have one */
1179		function = find_function(inlineTab, name);
1180		if (function == NULL) {
1181			/* Function doesn't exist, don't bother to process
1182			 * metadata for it.
1183			 */
1184			return 0;
1185		}
1186	}
1187
1188	BOOL ignore = attribute_bool(cur_node, "ignore", NULL, NO);
1189	if (ignore) {
1190		/* Function should be ignored */
1191		if (PyDict_GetItemString(globalDict, name)) {
1192			PyDict_DelItemString(globalDict, name);
1193		}
1194		xmlFree(name);
1195		return 0;
1196	}
1197
1198
1199	/* Build the metadata for the function:
1200	 * - metdata is the actual metadata list
1201	 * - siglist is a list with signature elements
1202	 *   (retval, arg1, arg2, ...)
1203	 */
1204
1205	PyObject* metadata = PyDict_New();
1206	if (metadata == NULL) {
1207		xmlFree(name);
1208		return -1;
1209	}
1210	PyObject* arguments = PyDict_New();
1211	if (arguments == NULL) {
1212		xmlFree(name);
1213		Py_DECREF(metadata);
1214		return -1;
1215	}
1216	if (PyDict_SetItemString(metadata, "arguments", arguments) < 0)  {
1217		xmlFree(name);
1218		Py_DECREF(metadata);
1219		Py_DECREF(arguments);
1220		return -1;
1221	}
1222
1223	BOOL variadic = attribute_bool(cur_node, "variadic", NULL, NO);
1224	PyObject* v = PyBool_FromLong(variadic);
1225	if (v == NULL) {
1226		xmlFree(name);
1227		Py_DECREF(metadata);
1228		Py_DECREF(arguments);
1229		return -1;
1230	}
1231
1232	if (PyDict_SetItemString(metadata, "variadic", v) < 0)  {
1233		xmlFree(name);
1234		Py_DECREF(metadata);
1235		Py_DECREF(v);
1236		return -1;
1237	}
1238	Py_DECREF(v);
1239
1240	if (variadic) {
1241		v = PyBool_FromLong(
1242			attribute_bool(cur_node, "c_array_delimited_by_null", NULL, NO));
1243		if (v == NULL) {
1244			xmlFree(name);
1245			Py_DECREF(metadata);
1246			Py_DECREF(arguments);
1247			return -1;
1248		}
1249
1250		if (PyDict_SetItemString(metadata, "c_array_delimited_by_null", v) < 0)  {
1251			xmlFree(name);
1252			Py_DECREF(metadata);
1253			Py_DECREF(v);
1254			return -1;
1255		}
1256		Py_DECREF(v);
1257
1258		char* ch = attribute_string(cur_node, "c_array_length_in_arg", NULL);
1259		if (ch) {
1260			long count = strtol(ch, NULL, 10);
1261			v = PyObjC_IntFromLong(count);
1262			if (v == NULL) {
1263				xmlFree(name);
1264				Py_DECREF(metadata);
1265				Py_DECREF(arguments);
1266				return -1;
1267			}
1268
1269			if (PyDict_SetItemString(metadata, "c_array_length_in_arg", v) < 0)  {
1270				xmlFree(name);
1271				Py_DECREF(metadata);
1272				Py_DECREF(v);
1273				return -1;
1274			}
1275			Py_DECREF(v);
1276			xmlFree(ch);
1277		}
1278	}
1279
1280	PyObject* siglist = PyList_New(0);
1281	if (siglist == NULL) {
1282		Py_DECREF(metadata);
1283		Py_DECREF(arguments);
1284		xmlFree(name);
1285		return -1;
1286	}
1287
1288	/* Set the default result type to 'v' */
1289	v = PyBytes_InternFromString("v");
1290	if (v == NULL) goto error;
1291
1292	int r = PyList_Append(siglist, v);
1293	Py_DECREF(v);
1294	if (r == -1) goto error;
1295
1296	/* Now walk the children of this mode, that is the
1297	 * argument and retval definitions.
1298	 */
1299	xmlNode* al;
1300	for (al = cur_node->children; al != NULL; al = al->next) {
1301		if (al->type != XML_ELEMENT_NODE)  {
1302			continue;
1303		}
1304
1305		if (strcmp((char*)al->name, "arg") == 0) {
1306			PyObject* d = PyObjC_InternValue(xmlToArgMeta(al, NO, NULL));
1307			if (d == NULL) {
1308				goto error;
1309			}
1310
1311			PyObject* s = PyDict_GetItemString(d, "type");
1312			if (s == NULL) {
1313				Py_DECREF(d);
1314				goto error;
1315			}
1316
1317			if (PyList_Append(siglist, s) < 0) {
1318				Py_DECREF(d);
1319				goto error;
1320			}
1321
1322			PyObject* argIdx = PyObjC_IntFromLong(PyList_Size(siglist)-2);
1323			if (argIdx == NULL) {
1324				Py_DECREF(d);
1325				goto error;
1326			}
1327
1328			if (PyDict_SetItem(arguments, argIdx, d) < 0) {
1329				Py_DECREF(d);
1330				Py_DECREF(argIdx);
1331				goto error;
1332			}
1333			Py_DECREF(d);
1334			Py_DECREF(argIdx);
1335
1336		} else if (strcmp((char*)al->name, "retval") == 0) {
1337
1338			PyObject* d = PyObjC_InternValue(xmlToArgMeta(al, NO, NULL));
1339			if (d == NULL) {
1340				goto error;
1341			}
1342
1343			PyObject* s = PyDict_GetItemString(d, "type");
1344			if (s == NULL) {
1345				Py_DECREF(d);
1346				goto error;
1347			}
1348
1349			if (PyList_SetItem(siglist, 0, s) < 0) {
1350				Py_DECREF(d);
1351				goto error;
1352			}
1353			Py_INCREF(s); /* SetItem steals a reference */
1354
1355			if (PyDict_SetItemString(metadata, "retval", d) < 0) {
1356				Py_DECREF(d);
1357				goto error;
1358			}
1359			Py_DECREF(d);
1360		}
1361		/* else: ignore */
1362	}
1363
1364
1365	/* We have the complete metadata, now build the proxy object for it */
1366	PyObject* signature = PyObjC_InternValue(PyObject_CallMethod(empty_bytes, "join", "O", siglist));
1367	if (signature == NULL) {
1368		goto error;
1369	}
1370
1371	PyObject* nm = PyText_InternFromString(name);
1372	if (nm == NULL) {
1373		goto error;
1374	}
1375
1376	metadata = PyObjC_InternValue(metadata);
1377	if (metadata == NULL) {
1378		Py_DECREF(nm);
1379		Py_DECREF(metadata);
1380		Py_DECREF(arguments);
1381		Py_DECREF(siglist);
1382	}
1383
1384	v = PyObjCFunc_New(nm, function, PyBytes_AsString(signature), Py_None, metadata);
1385
1386	Py_DECREF(nm);
1387	Py_DECREF(metadata);
1388	Py_DECREF(arguments);
1389	Py_DECREF(siglist);
1390
1391	if (v == NULL) {
1392		xmlFree(name);
1393		return -1;
1394	}
1395
1396	if (PyDict_SetItemString(globalDict, name, v) < 0) {
1397		Py_DECREF(v);
1398		xmlFree(name);
1399		return -1;
1400	}
1401	Py_DECREF(v);
1402	xmlFree(name);
1403	return 0;
1404
1405error:
1406	Py_DECREF(siglist);
1407	Py_DECREF(arguments);
1408	Py_DECREF(metadata);
1409	xmlFree(name);
1410	return -1;
1411}
1412
1413static inline int
1414handle_informal_protocol(xmlNode* cur_node, const char* framework, PyObject* globalDict)
1415{
1416	char* name = attribute_string(cur_node, "name", NULL);
1417	PyObject* methodList = NULL;
1418
1419	if (name == NULL) {
1420		return 0;
1421	}
1422
1423	xmlNode* method;
1424
1425	for (method = cur_node->children; method != NULL; method = method->next) {
1426		if (method->type != XML_ELEMENT_NODE)  {
1427			continue;
1428		}
1429
1430		char* selector = attribute_string(method, "selector", NULL);
1431		char* type = attribute_string(method, "type", "type64");
1432		BOOL isClassMethod = attribute_bool(method, "classmethod", NULL, NO);
1433
1434		typestr2typestr(type);
1435
1436		if (selector != NULL && type != NULL) {
1437			if (methodList == NULL) {
1438				methodList = PyList_New(0);
1439				if (methodList == NULL) {
1440					xmlFree(name);
1441					return -1;
1442				}
1443			}
1444
1445			PyObject* m = PyObjCSelector_New(Py_None, sel_getUid(selector),
1446				type, isClassMethod, NULL);
1447			if (m == NULL) {
1448				Py_DECREF(methodList);
1449				xmlFree(name);
1450				return -1;
1451			}
1452			int r = PyList_Append(methodList, m);
1453			Py_DECREF(m);
1454			if (r == -1) {
1455				Py_DECREF(methodList);
1456				xmlFree(name);
1457				return -1;
1458			}
1459		}
1460
1461		if (selector) xmlFree(selector);
1462		if (type) xmlFree(type);
1463	}
1464
1465	if (methodList != NULL && PyList_Size(methodList) != 0) {
1466		PyObject* proto = PyObject_CallFunction(
1467				(PyObject*)&PyObjCInformalProtocol_Type,
1468				"sO",
1469				name, methodList);
1470		if (proto == NULL) {
1471			Py_DECREF(methodList);
1472			xmlFree(name);
1473			return -1;
1474		}
1475
1476
1477		PyObject* module;
1478		module = PyDict_GetItemString(globalDict, "protocols");
1479
1480		if (module == NULL) {
1481			char buf[1024];
1482			snprintf(buf, sizeof(buf), "%s.protocols", framework);
1483			PyObject* mod_name = PyText_InternFromString(buf);
1484			if (mod_name == NULL) {
1485				Py_DECREF(proto);
1486				Py_DECREF(methodList);
1487				xmlFree(name);
1488				return -1;
1489			}
1490
1491
1492			module = PyModule_New(buf);
1493			if (module == NULL) {
1494				Py_DECREF(mod_name);
1495				Py_DECREF(proto);
1496				Py_DECREF(methodList);
1497				xmlFree(name);
1498				return -1;
1499			}
1500
1501			int r = PyDict_SetItemString(globalDict,
1502					"protocols", module);
1503			if (r == -1) {
1504				Py_DECREF(mod_name);
1505				Py_DECREF(proto);
1506				Py_DECREF(methodList);
1507				xmlFree(name);
1508				return -1;
1509			}
1510
1511			/* Add to sys.modules as well */
1512			PyObject* sysmod = PyImport_GetModuleDict();
1513			if (sysmod == NULL) {
1514				Py_DECREF(mod_name);
1515				Py_DECREF(proto);
1516				Py_DECREF(methodList);
1517				xmlFree(name);
1518				return -1;
1519			}
1520			r = PyDict_SetItem(sysmod, mod_name, module);
1521			Py_DECREF(mod_name);
1522			if (r == -1) {
1523				Py_DECREF(proto);
1524				Py_DECREF(methodList);
1525				xmlFree(name);
1526				return -1;
1527			}
1528			Py_DECREF(module);
1529		}
1530
1531		int r = PyObject_SetAttrString(module, name, proto);
1532		Py_DECREF(proto);
1533		if (r == -1) {
1534			Py_DECREF(methodList);
1535			xmlFree(name);
1536			return -1;
1537		}
1538	}
1539
1540	xmlFree(name);
1541	Py_XDECREF(methodList);
1542	return 0;
1543}
1544
1545static inline int
1546handle_struct(xmlNode* cur_node, PyObject* globalDict)
1547{
1548	char* name = attribute_string(cur_node, "name", NULL);
1549	char* type = attribute_string(cur_node, "type", "type64");
1550	char* alias = attribute_string(cur_node, "alias", NULL);
1551	if (!typestr2typestr(type)) {
1552		PyErr_Format(PyExc_SyntaxError, "Syntax error for struct %s\n", name);
1553		return -1;
1554	}
1555
1556
1557	if (name != NULL && type != NULL && *type != '\0') {
1558		PyObject* v = NULL;
1559
1560		if (alias != NULL) {
1561			int r;
1562
1563			v = PyObjC_ImportName(alias);
1564
1565			if (v != NULL) {
1566
1567				r = PyObjC_RegisterStructAlias(type, v);
1568				if (r == -1) {
1569					Py_DECREF(v);
1570					if (name) xmlFree(name);
1571					if (type) xmlFree(type);
1572					if (alias) xmlFree(alias);
1573					return -1;
1574				}
1575			} else {
1576				/* Fall through to regular handling */
1577				PyErr_Clear();
1578			}
1579		}
1580
1581
1582		if (v == NULL) {
1583			v = PyObjC_RegisterStructType(
1584				PyObjCUtil_Strdup(type),
1585				PyObjCUtil_Strdup(name),
1586				"", NULL, -1, NULL);
1587
1588			if (v == NULL) {
1589				if (name) xmlFree(name);
1590				if (type) xmlFree(type);
1591				if (alias) xmlFree(alias);
1592				return -1;
1593			}
1594
1595			if (structConvenience != NULL) {
1596				PyObject* o = PyObject_CallFunction(
1597						structConvenience,
1598						"ss", name, type);
1599				Py_XDECREF(o);
1600				PyErr_Clear();
1601			}
1602		}
1603
1604		int r = PyDict_SetItemString(globalDict, name, v);
1605		Py_DECREF(v);
1606		if (r == -1) {
1607			if (name) xmlFree(name);
1608			if (type) xmlFree(type);
1609			if (alias) xmlFree(alias);
1610			return -1;
1611		}
1612	}
1613
1614	if (name) xmlFree(name);
1615	if (type) xmlFree(type);
1616	if (alias) xmlFree(alias);
1617	return 0;
1618}
1619
1620static int
1621expand_aliases(PyObject* globalDict, PyObject* func_aliases)
1622{
1623	Py_ssize_t i, len;
1624
1625	len = PyList_Size(func_aliases);
1626
1627	for (i = 0; i < len; i++) {
1628		PyObject* v = PyList_GET_ITEM(func_aliases, i);
1629		PyObject* name;
1630		PyObject* orig;
1631
1632		name = PyTuple_GET_ITEM(v, 0);
1633		orig = PyTuple_GET_ITEM(v, 1);
1634
1635		v = PyDict_GetItem(globalDict, orig);
1636		if (v != NULL) {
1637			int r = PyDict_SetItem(globalDict, name, v);
1638			Py_DECREF(v);
1639			if (r == -1) {
1640				PyErr_Clear();
1641			}
1642		}
1643	}
1644	return 0;
1645}
1646
1647
1648PyObject*
1649PyObjC_SetSetupCFClasses(PyObject* self __attribute__((__unused__)), PyObject* arg)
1650{
1651	Py_INCREF(arg);
1652	Py_XDECREF(setupCFClasses);
1653	setupCFClasses = arg;
1654	Py_INCREF(Py_None);
1655	return Py_None;
1656}
1657
1658PyObject*
1659PyObjC_SetStructConvenience(PyObject* self __attribute__((__unused__)), PyObject* arg)
1660{
1661	Py_INCREF(arg);
1662	Py_XDECREF(structConvenience);
1663	structConvenience = arg;
1664	Py_INCREF(Py_None);
1665	return Py_None;
1666}
1667
1668
1669int
1670PyObjC_ProcessXML(char* data, int length, PyObject* globalDict, const char* dylibPath, const char* framework, PyObject* _inlineTab)
1671{
1672	PyObject* value;
1673	PyObject* func_aliases = NULL;
1674	PyObject* cftypes = NULL;
1675
1676	if (setupCFClasses) {
1677		cftypes = PyList_New(0);
1678		if (cftypes == NULL) {
1679			return -1;
1680		}
1681	}
1682
1683
1684	xmlDoc* doc = xmlReadMemory(data, length,
1685		"noname.xml", NULL, 0 /*XML_PARSE_COMPACT*/);
1686	if (doc == NULL) {
1687		PyErr_SetString(PyObjCExc_Error, "invalid bridgesupport file");
1688		return -1;
1689	}
1690
1691	struct functionlist* inlineTab = NULL;
1692	if (_inlineTab != NULL && PyCapsule_CheckExact(_inlineTab)) {
1693		inlineTab = PyCapsule_GetPointer(_inlineTab, "objc.__inline__");
1694		if (inlineTab == NULL) {
1695			PyErr_Clear();
1696		}
1697	}
1698
1699	/* Process document here */
1700	xmlNode* root = xmlDocGetRootElement(doc);
1701	xmlNode* cur_node;
1702	if (root->type != XML_ELEMENT_NODE || strcmp((char*)root->name, "signatures") != 0) {
1703		PyErr_SetString(PyObjCExc_Error, "invalid root node in bridgesupport file");
1704		return -1;
1705	}
1706
1707	if (dylibPath) {
1708		dlopen(dylibPath, RTLD_LAZY);
1709	}
1710
1711	func_aliases = PyList_New(0);
1712	if (func_aliases == NULL) {
1713		return -1;
1714	}
1715
1716	PyObjC_UpdatingMetaData = YES;
1717
1718	for (cur_node = root->children; cur_node != NULL; cur_node = cur_node->next) {
1719		if (cur_node->type != XML_ELEMENT_NODE)  {
1720			/* We're only interested in actual elements */
1721			continue;
1722		}
1723		char* tag = (char*)cur_node->name;
1724		value = NULL;
1725		int r = 1;
1726
1727		/* Use a basic one-level tree to quickly dispatch to the right
1728		 * handler.
1729		 */
1730		switch (tag[0]) {
1731		case 'c':
1732			if (strcmp(tag, "cftype") == 0) {
1733				r = handle_cftype(cur_node, globalDict, cftypes);
1734			} else if (strcmp(tag, "constant") == 0) {
1735				r = handle_constant(cur_node, globalDict);
1736			} else if (strcmp(tag, "class") == 0) {
1737				r = handle_class(cur_node);
1738			}
1739			break;
1740
1741		case 'e':
1742			if (strcmp(tag, "enum") == 0) {
1743				r = handle_enum(cur_node, globalDict);
1744			}
1745			break;
1746
1747		case 'f':
1748			if (strcmp(tag, "function") == 0) {
1749				r = handle_function(cur_node, globalDict, inlineTab);
1750			} else if (strcmp(tag, "function_pointer") == 0) {
1751				r = handle_function_pointer(cur_node, func_aliases);
1752			}
1753			break;
1754
1755		case 'i':
1756			if (strcmp(tag, "informal_protocol") == 0) {
1757				r = handle_informal_protocol(cur_node, framework, globalDict);
1758			}
1759			break;
1760
1761		case 'n':
1762			if (strcmp(tag, "null_const") == 0) {
1763				r = handle_null_const(cur_node, globalDict);
1764			}
1765			break;
1766
1767		case 'o':
1768			if (strcmp(tag, "opaque") == 0) {
1769				r = handle_opaque(cur_node, globalDict);
1770			}
1771			break;
1772
1773		case 's':
1774			if (strcmp(tag, "struct") == 0) {
1775				r = handle_struct(cur_node, globalDict);
1776			} else if (strcmp(tag, "string_constant") == 0) {
1777				r = handle_string_constant(cur_node, globalDict);
1778			}
1779			break;
1780
1781		}
1782
1783		if (r == 1) {
1784			/* Unknown tag, ignore these to avoid breaking when
1785			 * the metadata format is upgraded.
1786			 */
1787		} else if (r == -1) {
1788			goto end;
1789		}
1790	}
1791
1792	if (PyList_Size(func_aliases) != 0) {
1793		expand_aliases(globalDict, func_aliases);
1794	}
1795
1796	if (setupCFClasses) {
1797		PyObject* o = PyObject_CallFunction(setupCFClasses, "OO",
1798			globalDict, cftypes);
1799		Py_XDECREF(o);
1800		PyErr_Clear();
1801	}
1802
1803end:
1804	PyObjC_UpdatingMetaData = NO;
1805	PyObjC_MappingCount ++;
1806
1807	Py_XDECREF(cftypes); cftypes = NULL;
1808
1809	Py_DECREF(func_aliases);
1810	xmlFreeDoc(doc);
1811	if (PyErr_Occurred()) {
1812		return -1;
1813	} else {
1814		return 0;
1815	}
1816}
1817