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