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