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