|
|
1.1 root 1: /* GNU Objective C Runtime archiving 1.1.1.4 ! root 2: Copyright (C) 1993, 1995 Free Software Foundation, Inc. ! 3: Contributed by Kresten Krab Thorup 1.1 root 4: 5: This file is part of GNU CC. 6: 7: GNU CC is free software; you can redistribute it and/or modify it under the 1.1.1.4 ! root 8: terms of the GNU General Public License as published by the Free Software ! 9: Foundation; either version 2, or (at your option) any later version. 1.1 root 10: 11: GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY 1.1.1.4 ! root 12: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ! 13: FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ! 14: details. 1.1 root 15: 16: You should have received a copy of the GNU General Public License along with 1.1.1.4 ! root 17: GNU CC; see the file COPYING. If not, write to the Free Software ! 18: Foundation, 59 Temple Place - Suite 330, ! 19: Boston, MA 02111-1307, USA. */ 1.1 root 20: 21: /* As a special exception, if you link this library with files compiled with 22: GCC to produce an executable, this does not cause the resulting executable 23: to be covered by the GNU General Public License. This exception does not 24: however invalidate any other reasons why the executable file might be 25: covered by the GNU General Public License. */ 26: 27: #include "runtime.h" 28: #include "typedstream.h" 1.1.1.3 root 29: #include "encoding.h" 30: 31: extern int fflush(FILE*); 32: 33: #define ROUND(V, A) \ 34: ({ typeof(V) __v=(V); typeof(A) __a=(A); \ 35: __a*((__v+__a-1)/__a); }) 36: 37: #define PTR2LONG(P) (((char*)(P))-(char*)0) 38: #define LONG2PTR(L) (((char*)0)+(L)) 1.1 root 39: 40: #define __objc_fatal(format, args...) \ 1.1.1.2 root 41: { fprintf(stderr, "archiving: "); \ 1.1 root 42: fprintf(stderr, format, ## args); \ 43: fprintf(stderr, "\n"); abort(); } 44: 45: /* Declare some functions... */ 46: 47: static int 1.1.1.4 ! root 48: objc_read_class (struct objc_typed_stream* stream, Class* class); 1.1 root 49: 1.1.1.3 root 50: int objc_sizeof_type(const char* type); 1.1 root 51: 52: static int 1.1.1.3 root 53: objc_write_use_common (struct objc_typed_stream* stream, unsigned long key); 1.1 root 54: 55: static int 56: objc_write_register_common (struct objc_typed_stream* stream, 1.1.1.3 root 57: unsigned long key); 1.1 root 58: 59: static int 60: objc_write_class (struct objc_typed_stream* stream, 61: struct objc_class* class); 62: 1.1.1.3 root 63: const char* objc_skip_type (const char* type); 1.1 root 64: 65: static void __objc_finish_write_root_object(struct objc_typed_stream*); 66: static void __objc_finish_read_root_object(struct objc_typed_stream*); 67: 68: static __inline__ int 69: __objc_code_unsigned_char (unsigned char* buf, unsigned char val) 70: { 71: if ((val&_B_VALUE) == val) 72: { 73: buf[0] = val|_B_SINT; 74: return 1; 75: } 76: else 77: { 78: buf[0] = _B_NINT|0x01; 79: buf[1] = val; 80: return 2; 81: } 82: } 83: 84: int 85: objc_write_unsigned_char (struct objc_typed_stream* stream, 86: unsigned char value) 87: { 88: unsigned char buf[sizeof (unsigned char)+1]; 89: int len = __objc_code_unsigned_char (buf, value); 90: return (*stream->write)(stream->physical, buf, len); 91: } 92: 93: static __inline__ int 94: __objc_code_char (unsigned char* buf, char val) 95: { 96: if (val >= 0) 97: return __objc_code_unsigned_char (buf, val); 98: else 99: { 100: buf[0] = _B_NINT|_B_SIGN|0x01; 101: buf[1] = -val; 102: return 2; 103: } 104: } 105: 106: int 107: objc_write_char (struct objc_typed_stream* stream, char value) 108: { 109: unsigned char buf[sizeof (char)+1]; 110: int len = __objc_code_char (buf, value); 111: return (*stream->write)(stream->physical, buf, len); 112: } 113: 114: static __inline__ int 115: __objc_code_unsigned_short (unsigned char* buf, unsigned short val) 116: { 1.1.1.3 root 117: if ((val&_B_VALUE) == val) 118: { 119: buf[0] = val|_B_SINT; 120: return 1; 121: } 1.1 root 122: else 123: { 1.1.1.3 root 124: int c, b; 125: 126: buf[0] = _B_NINT; 127: 128: for (c= sizeof(short); c != 0; c -= 1) 129: if (((val>>(8*(c-1)))%0x100) != 0) 130: break; 131: 132: buf[0] |= c; 133: 134: for (b = 1; c != 0; c--, b++) 135: { 136: buf[b] = (val >> (8*(c-1)))%0x100; 137: } 138: 139: return b; 1.1 root 140: } 141: } 142: 143: int 144: objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short value) 145: { 146: unsigned char buf[sizeof (unsigned short)+1]; 147: int len = __objc_code_unsigned_short (buf, value); 148: return (*stream->write)(stream->physical, buf, len); 149: } 150: 151: static __inline__ int 152: __objc_code_short (unsigned char* buf, short val) 153: { 1.1.1.3 root 154: int sign = (val < 0); 155: int size = __objc_code_unsigned_short (buf, sign ? -val : val); 156: if (sign) 157: buf[0] |= _B_SIGN; 158: return size; 1.1 root 159: } 160: 161: int 162: objc_write_short (struct objc_typed_stream* stream, short value) 163: { 164: unsigned char buf[sizeof (short)+1]; 165: int len = __objc_code_short (buf, value); 166: return (*stream->write)(stream->physical, buf, len); 167: } 168: 169: 170: static __inline__ int 171: __objc_code_unsigned_int (unsigned char* buf, unsigned int val) 172: { 1.1.1.3 root 173: if ((val&_B_VALUE) == val) 1.1 root 174: { 1.1.1.3 root 175: buf[0] = val|_B_SINT; 176: return 1; 1.1 root 177: } 178: else 179: { 1.1.1.3 root 180: int c, b; 181: 182: buf[0] = _B_NINT; 183: 184: for (c= sizeof(int); c != 0; c -= 1) 185: if (((val>>(8*(c-1)))%0x100) != 0) 186: break; 187: 188: buf[0] |= c; 189: 190: for (b = 1; c != 0; c--, b++) 191: { 192: buf[b] = (val >> (8*(c-1)))%0x100; 193: } 194: 195: return b; 1.1 root 196: } 197: } 198: 199: int 200: objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value) 201: { 202: unsigned char buf[sizeof(unsigned int)+1]; 203: int len = __objc_code_unsigned_int (buf, value); 204: return (*stream->write)(stream->physical, buf, len); 205: } 206: 207: static __inline__ int 208: __objc_code_int (unsigned char* buf, int val) 209: { 1.1.1.3 root 210: int sign = (val < 0); 211: int size = __objc_code_unsigned_int (buf, sign ? -val : val); 212: if (sign) 213: buf[0] |= _B_SIGN; 214: return size; 215: } 1.1 root 216: 1.1.1.3 root 217: int 218: objc_write_int (struct objc_typed_stream* stream, int value) 219: { 220: unsigned char buf[sizeof(int)+1]; 221: int len = __objc_code_int (buf, value); 222: return (*stream->write)(stream->physical, buf, len); 223: } 1.1 root 224: 1.1.1.3 root 225: static __inline__ int 226: __objc_code_unsigned_long (unsigned char* buf, unsigned long val) 227: { 228: if ((val&_B_VALUE) == val) 229: { 230: buf[0] = val|_B_SINT; 231: return 1; 232: } 1.1 root 233: else 234: { 1.1.1.3 root 235: int c, b; 236: 237: buf[0] = _B_NINT; 238: 239: for (c= sizeof(long); c != 0; c -= 1) 240: if (((val>>(8*(c-1)))%0x100) != 0) 241: break; 242: 243: buf[0] |= c; 244: 245: for (b = 1; c != 0; c--, b++) 246: { 247: buf[b] = (val >> (8*(c-1)))%0x100; 248: } 249: 250: return b; 1.1 root 251: } 252: } 253: 254: int 1.1.1.3 root 255: objc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value) 1.1 root 256: { 1.1.1.3 root 257: unsigned char buf[sizeof(unsigned long)+1]; 258: int len = __objc_code_unsigned_long (buf, value); 1.1 root 259: return (*stream->write)(stream->physical, buf, len); 260: } 261: 1.1.1.3 root 262: static __inline__ int 263: __objc_code_long (unsigned char* buf, long val) 264: { 265: int sign = (val < 0); 266: int size = __objc_code_unsigned_long (buf, sign ? -val : val); 267: if (sign) 268: buf[0] |= _B_SIGN; 269: return size; 270: } 271: 272: int 273: objc_write_long (struct objc_typed_stream* stream, long value) 274: { 275: unsigned char buf[sizeof(long)+1]; 276: int len = __objc_code_long (buf, value); 277: return (*stream->write)(stream->physical, buf, len); 278: } 279: 280: 1.1 root 281: int 282: objc_write_string (struct objc_typed_stream* stream, 283: const unsigned char* string, unsigned int nbytes) 284: { 285: unsigned char buf[sizeof(unsigned int)+1]; 286: int len = __objc_code_unsigned_int (buf, nbytes); 287: 288: if ((buf[0]&_B_CODE) == _B_SINT) 289: buf[0] = (buf[0]&_B_VALUE)|_B_SSTR; 290: 291: else /* _B_NINT */ 292: buf[0] = (buf[0]&_B_VALUE)|_B_NSTR; 293: 294: if ((*stream->write)(stream->physical, buf, len) != 0) 295: return (*stream->write)(stream->physical, string, nbytes); 296: else 297: return 0; 298: } 299: 300: int 301: objc_write_string_atomic (struct objc_typed_stream* stream, 302: unsigned char* string, unsigned int nbytes) 303: { 1.1.1.3 root 304: unsigned long key; 305: if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string)))) 1.1 root 306: return objc_write_use_common (stream, key); 307: else 308: { 309: int length; 1.1.1.3 root 310: hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string); 1.1 root 311: if ((length = objc_write_register_common (stream, key))) 312: return objc_write_string (stream, string, nbytes); 313: return length; 314: } 315: } 316: 317: static int 1.1.1.3 root 318: objc_write_register_common (struct objc_typed_stream* stream, unsigned long key) 1.1 root 319: { 1.1.1.3 root 320: unsigned char buf[sizeof (unsigned long)+2]; 321: int len = __objc_code_unsigned_long (buf+1, key); 1.1 root 322: if (len == 1) 323: { 324: buf[0] = _B_RCOMM|0x01; 325: buf[1] &= _B_VALUE; 326: return (*stream->write)(stream->physical, buf, len+1); 327: } 328: else 329: { 330: buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM; 331: return (*stream->write)(stream->physical, buf+1, len); 332: } 333: } 334: 335: static int 1.1.1.3 root 336: objc_write_use_common (struct objc_typed_stream* stream, unsigned long key) 1.1 root 337: { 1.1.1.3 root 338: unsigned char buf[sizeof (unsigned long)+2]; 339: int len = __objc_code_unsigned_long (buf+1, key); 1.1 root 340: if (len == 1) 341: { 342: buf[0] = _B_UCOMM|0x01; 343: buf[1] &= _B_VALUE; 344: return (*stream->write)(stream->physical, buf, 2); 345: } 346: else 347: { 348: buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM; 349: return (*stream->write)(stream->physical, buf+1, len); 350: } 351: } 352: 353: static __inline__ int 354: __objc_write_extension (struct objc_typed_stream* stream, unsigned char code) 355: { 356: if (code <= _B_VALUE) 357: { 358: unsigned char buf = code|_B_EXT; 359: return (*stream->write)(stream->physical, &buf, 1); 360: } 361: else 362: abort(); 363: } 364: 365: __inline__ int 366: __objc_write_object (struct objc_typed_stream* stream, id object) 367: { 368: unsigned char buf = '\0'; 1.1.1.3 root 369: SEL write_sel = sel_get_any_uid ("write:"); 1.1 root 370: if (object) 371: { 372: __objc_write_extension (stream, _BX_OBJECT); 373: objc_write_class (stream, object->class_pointer); 374: (*objc_msg_lookup(object, write_sel))(object, write_sel, stream); 375: return (*stream->write)(stream->physical, &buf, 1); 376: } 377: else 378: return objc_write_use_common(stream, 0); 379: } 380: 381: int 382: objc_write_object_reference (struct objc_typed_stream* stream, id object) 383: { 1.1.1.3 root 384: unsigned long key; 385: if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object)))) 1.1 root 386: return objc_write_use_common (stream, key); 387: 388: __objc_write_extension (stream, _BX_OBJREF); 1.1.1.3 root 389: return objc_write_unsigned_long (stream, PTR2LONG (object)); 1.1 root 390: } 391: 392: int 393: objc_write_root_object (struct objc_typed_stream* stream, id object) 394: { 395: int len; 396: if (stream->writing_root_p) 397: __objc_fatal ("objc_write_root_object called recursively") 398: else 399: { 400: stream->writing_root_p = 1; 401: __objc_write_extension (stream, _BX_OBJROOT); 402: if((len = objc_write_object (stream, object))) 403: __objc_finish_write_root_object(stream); 404: stream->writing_root_p = 0; 405: } 406: return len; 407: } 408: 409: int 410: objc_write_object (struct objc_typed_stream* stream, id object) 411: { 1.1.1.3 root 412: unsigned long key; 413: if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object)))) 1.1 root 414: return objc_write_use_common (stream, key); 415: 416: else if (object == nil) 417: return objc_write_use_common(stream, 0); 418: 419: else 420: { 421: int length; 1.1.1.3 root 422: hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object); 1.1 root 423: if ((length = objc_write_register_common (stream, key))) 424: return __objc_write_object (stream, object); 425: return length; 426: } 427: } 428: 1.1.1.3 root 429: #ifdef __alpha__ 430: extern int atoi (const char*); 431: extern size_t strlen(const char*); 432: extern size_t strcpy(char*, const char*); 433: #endif 434: 1.1 root 435: __inline__ int 436: __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class) 437: { 438: __objc_write_extension (stream, _BX_CLASS); 439: objc_write_string_atomic(stream, (char*)class->name, 440: strlen((char*)class->name)); 1.1.1.4 ! root 441: return objc_write_unsigned_long (stream, class->version); 1.1 root 442: } 443: 444: 445: static int 446: objc_write_class (struct objc_typed_stream* stream, 447: struct objc_class* class) 448: { 1.1.1.3 root 449: unsigned long key; 450: if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class)))) 1.1 root 451: return objc_write_use_common (stream, key); 452: else 453: { 454: int length; 1.1.1.3 root 455: hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class); 1.1 root 456: if ((length = objc_write_register_common (stream, key))) 457: return __objc_write_class (stream, class); 458: return length; 459: } 460: } 461: 462: 463: __inline__ int 464: __objc_write_selector (struct objc_typed_stream* stream, SEL selector) 465: { 1.1.1.4 ! root 466: const char* sel_name; 1.1 root 467: __objc_write_extension (stream, _BX_SEL); 1.1.1.4 ! root 468: /* to handle NULL selectors */ ! 469: if ((SEL)0 == selector) ! 470: return objc_write_string (stream, "", 0); ! 471: sel_name = sel_get_name (selector); 1.1 root 472: return objc_write_string (stream, sel_name, strlen ((char*)sel_name)); 473: } 474: 475: int 476: objc_write_selector (struct objc_typed_stream* stream, SEL selector) 477: { 1.1.1.4 ! root 478: const char* sel_name; 1.1.1.3 root 479: unsigned long key; 1.1.1.4 ! root 480: ! 481: /* to handle NULL selectors */ ! 482: if ((SEL)0 == selector) ! 483: return __objc_write_selector (stream, selector); ! 484: ! 485: sel_name = sel_get_name (selector); 1.1.1.3 root 486: if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name)))) 1.1 root 487: return objc_write_use_common (stream, key); 488: else 489: { 490: int length; 1.1.1.3 root 491: hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name); 1.1 root 492: if ((length = objc_write_register_common (stream, key))) 493: return __objc_write_selector (stream, selector); 494: return length; 495: } 496: } 497: 498: 499: 500: /* 501: ** Read operations 502: */ 503: 504: __inline__ int 505: objc_read_char (struct objc_typed_stream* stream, char* val) 506: { 507: unsigned char buf; 508: int len; 509: len = (*stream->read)(stream->physical, &buf, 1); 510: if (len != 0) 511: { 512: if ((buf & _B_CODE) == _B_SINT) 513: (*val) = (buf & _B_VALUE); 514: 515: else if ((buf & _B_NUMBER) == 1) 516: { 517: len = (*stream->read)(stream->physical, val, 1); 518: if (buf&_B_SIGN) 519: (*val) = -1*(*val); 520: } 521: 522: else 523: __objc_fatal("expected 8bit signed int, got %dbit int", 524: (int)(buf&_B_NUMBER)*8); 525: } 526: return len; 527: } 528: 529: 530: __inline__ int 531: objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val) 532: { 533: unsigned char buf; 534: int len; 535: if ((len = (*stream->read)(stream->physical, &buf, 1))) 536: { 537: if ((buf & _B_CODE) == _B_SINT) 538: (*val) = (buf & _B_VALUE); 539: 540: else if ((buf & _B_NUMBER) == 1) 541: len = (*stream->read)(stream->physical, val, 1); 542: 543: else 544: __objc_fatal("expected 8bit unsigned int, got %dbit int", 545: (int)(buf&_B_NUMBER)*8); 546: } 547: return len; 548: } 549: 550: __inline__ int 551: objc_read_short (struct objc_typed_stream* stream, short* value) 552: { 553: unsigned char buf[sizeof(short)+1]; 554: int len; 555: if ((len = (*stream->read)(stream->physical, buf, 1))) 556: { 557: if ((buf[0] & _B_CODE) == _B_SINT) 558: (*value) = (buf[0] & _B_VALUE); 559: 560: else 561: { 562: int pos = 1; 563: int nbytes = buf[0] & _B_NUMBER; 564: if (nbytes > sizeof (short)) 565: __objc_fatal("expected short, got bigger (%dbits)", nbytes*8); 566: len = (*stream->read)(stream->physical, buf+1, nbytes); 567: (*value) = 0; 568: while (pos <= nbytes) 569: (*value) = ((*value)*0x100) + buf[pos++]; 570: if (buf[0] & _B_SIGN) 571: (*value) = -(*value); 572: } 573: } 574: return len; 575: } 576: 577: __inline__ int 578: objc_read_unsigned_short (struct objc_typed_stream* stream, 579: unsigned short* value) 580: { 581: unsigned char buf[sizeof(unsigned short)+1]; 582: int len; 583: if ((len = (*stream->read)(stream->physical, buf, 1))) 584: { 585: if ((buf[0] & _B_CODE) == _B_SINT) 586: (*value) = (buf[0] & _B_VALUE); 587: 588: else 589: { 590: int pos = 1; 591: int nbytes = buf[0] & _B_NUMBER; 592: if (nbytes > sizeof (short)) 593: __objc_fatal("expected short, got int or bigger"); 594: len = (*stream->read)(stream->physical, buf+1, nbytes); 595: (*value) = 0; 596: while (pos <= nbytes) 597: (*value) = ((*value)*0x100) + buf[pos++]; 598: } 599: } 600: return len; 601: } 602: 603: 604: __inline__ int 605: objc_read_int (struct objc_typed_stream* stream, int* value) 606: { 607: unsigned char buf[sizeof(int)+1]; 608: int len; 609: if ((len = (*stream->read)(stream->physical, buf, 1))) 610: { 611: if ((buf[0] & _B_CODE) == _B_SINT) 612: (*value) = (buf[0] & _B_VALUE); 613: 614: else 615: { 616: int pos = 1; 617: int nbytes = buf[0] & _B_NUMBER; 618: if (nbytes > sizeof (int)) 619: __objc_fatal("expected int, got bigger"); 620: len = (*stream->read)(stream->physical, buf+1, nbytes); 621: (*value) = 0; 622: while (pos <= nbytes) 623: (*value) = ((*value)*0x100) + buf[pos++]; 624: if (buf[0] & _B_SIGN) 625: (*value) = -(*value); 626: } 627: } 628: return len; 629: } 630: 631: __inline__ int 1.1.1.3 root 632: objc_read_long (struct objc_typed_stream* stream, long* value) 633: { 634: unsigned char buf[sizeof(long)+1]; 635: int len; 636: if ((len = (*stream->read)(stream->physical, buf, 1))) 637: { 638: if ((buf[0] & _B_CODE) == _B_SINT) 639: (*value) = (buf[0] & _B_VALUE); 640: 641: else 642: { 643: int pos = 1; 644: int nbytes = buf[0] & _B_NUMBER; 645: if (nbytes > sizeof (long)) 646: __objc_fatal("expected long, got bigger"); 647: len = (*stream->read)(stream->physical, buf+1, nbytes); 648: (*value) = 0; 649: while (pos <= nbytes) 650: (*value) = ((*value)*0x100) + buf[pos++]; 651: if (buf[0] & _B_SIGN) 652: (*value) = -(*value); 653: } 654: } 655: return len; 656: } 657: 658: __inline__ int 1.1 root 659: __objc_read_nbyte_uint (struct objc_typed_stream* stream, 660: unsigned int nbytes, unsigned int* val) 661: { 662: int len, pos = 0; 663: unsigned char buf[sizeof(unsigned int)+1]; 664: 665: if (nbytes > sizeof (int)) 666: __objc_fatal("expected int, got bigger"); 667: 668: len = (*stream->read)(stream->physical, buf, nbytes); 669: (*val) = 0; 670: while (pos < nbytes) 671: (*val) = ((*val)*0x100) + buf[pos++]; 672: return len; 673: } 674: 675: 676: __inline__ int 677: objc_read_unsigned_int (struct objc_typed_stream* stream, 678: unsigned int* value) 679: { 680: unsigned char buf[sizeof(unsigned int)+1]; 681: int len; 682: if ((len = (*stream->read)(stream->physical, buf, 1))) 683: { 684: if ((buf[0] & _B_CODE) == _B_SINT) 685: (*value) = (buf[0] & _B_VALUE); 686: 687: else 688: len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value); 689: 690: } 691: return len; 692: } 693: 1.1.1.3 root 694: int 695: __objc_read_nbyte_ulong (struct objc_typed_stream* stream, 696: unsigned int nbytes, unsigned long* val) 697: { 698: int len, pos = 0; 699: unsigned char buf[sizeof(unsigned long)+1]; 700: 701: if (nbytes > sizeof (long)) 702: __objc_fatal("expected long, got bigger"); 703: 704: len = (*stream->read)(stream->physical, buf, nbytes); 705: (*val) = 0; 706: while (pos < nbytes) 707: (*val) = ((*val)*0x100) + buf[pos++]; 708: return len; 709: } 710: 711: 712: __inline__ int 713: objc_read_unsigned_long (struct objc_typed_stream* stream, 714: unsigned long* value) 715: { 716: unsigned char buf[sizeof(unsigned long)+1]; 717: int len; 718: if ((len = (*stream->read)(stream->physical, buf, 1))) 719: { 720: if ((buf[0] & _B_CODE) == _B_SINT) 721: (*value) = (buf[0] & _B_VALUE); 722: 723: else 724: len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value); 725: 726: } 727: return len; 728: } 729: 1.1 root 730: __inline__ int 731: objc_read_string (struct objc_typed_stream* stream, 732: char** string) 733: { 734: unsigned char buf[sizeof(unsigned int)+1]; 735: int len; 736: if ((len = (*stream->read)(stream->physical, buf, 1))) 737: { 1.1.1.3 root 738: unsigned long key = 0; 1.1 root 739: 740: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ 741: { 1.1.1.3 root 742: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); 1.1 root 743: len = (*stream->read)(stream->physical, buf, 1); 744: } 745: 746: switch (buf[0]&_B_CODE) { 747: case _B_SSTR: 748: { 749: int length = buf[0]&_B_VALUE; 750: (*string) = (char*)__objc_xmalloc(length+1); 751: if (key) 1.1.1.3 root 752: hash_add (&stream->stream_table, LONG2PTR(key), *string); 1.1 root 753: len = (*stream->read)(stream->physical, *string, length); 754: (*string)[length] = '\0'; 755: } 756: break; 757: 758: case _B_UCOMM: 759: { 1.1.1.2 root 760: char *tmp; 1.1.1.3 root 761: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); 762: tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key)); 763: *string = __objc_xmalloc (strlen(tmp) + 1); 1.1.1.2 root 764: strcpy (*string, tmp); 1.1 root 765: } 766: break; 767: 768: case _B_NSTR: 769: { 770: unsigned int nbytes = buf[0]&_B_VALUE; 771: len = __objc_read_nbyte_uint(stream, nbytes, &nbytes); 772: if (len) { 1.1.1.2 root 773: (*string) = (char*)__objc_xmalloc(nbytes+1); 1.1 root 774: if (key) 1.1.1.3 root 775: hash_add (&stream->stream_table, LONG2PTR(key), *string); 1.1.1.2 root 776: len = (*stream->read)(stream->physical, *string, nbytes); 1.1 root 777: (*string)[nbytes] = '\0'; 778: } 779: } 780: break; 781: 782: default: 783: __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE)); 784: } 785: } 786: 787: return len; 788: } 789: 790: 791: int 792: objc_read_object (struct objc_typed_stream* stream, id* object) 793: { 794: unsigned char buf[sizeof (unsigned int)]; 795: int len; 796: if ((len = (*stream->read)(stream->physical, buf, 1))) 797: { 1.1.1.3 root 798: SEL read_sel = sel_get_any_uid ("read:"); 799: unsigned long key = 0; 1.1 root 800: 801: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */ 802: { 1.1.1.3 root 803: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); 1.1 root 804: len = (*stream->read)(stream->physical, buf, 1); 805: } 806: 807: if (buf[0] == (_B_EXT | _BX_OBJECT)) 808: { 1.1.1.4 ! root 809: Class class; 1.1 root 810: 811: /* get class */ 812: len = objc_read_class (stream, &class); 813: 814: /* create instance */ 815: (*object) = class_create_instance(class); 816: 817: /* register? */ 818: if (key) 1.1.1.3 root 819: hash_add (&stream->object_table, LONG2PTR(key), *object); 1.1 root 820: 821: /* send -read: */ 822: if (__objc_responds_to (*object, read_sel)) 823: (*get_imp(class, read_sel))(*object, read_sel, stream); 824: 825: /* check null-byte */ 826: len = (*stream->read)(stream->physical, buf, 1); 827: if (buf[0] != '\0') 828: __objc_fatal("expected null-byte, got opcode %c", buf[0]); 829: } 830: 831: else if ((buf[0]&_B_CODE) == _B_UCOMM) 832: { 833: if (key) 834: __objc_fatal("cannot register use upcode..."); 1.1.1.3 root 835: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); 836: (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key)); 1.1 root 837: } 838: 839: else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */ 840: { 841: struct objc_list* other; 1.1.1.3 root 842: len = objc_read_unsigned_long (stream, &key); 843: other = (struct objc_list*)hash_value_for_key (stream->object_refs, LONG2PTR(key)); 844: hash_add (&stream->object_refs, LONG2PTR(key), (void*)list_cons(object, other)); 1.1 root 845: } 846: 847: else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */ 848: { 849: if (key) 850: __objc_fatal("cannot register root object..."); 851: len = objc_read_object (stream, object); 852: __objc_finish_read_root_object (stream); 853: } 854: 855: else 856: __objc_fatal("expected object, got opcode %c", buf[0]); 857: } 858: return len; 859: } 860: 861: static int 1.1.1.4 ! root 862: objc_read_class (struct objc_typed_stream* stream, Class* class) 1.1 root 863: { 864: unsigned char buf[sizeof (unsigned int)]; 865: int len; 866: if ((len = (*stream->read)(stream->physical, buf, 1))) 867: { 1.1.1.3 root 868: unsigned long key = 0; 1.1 root 869: 870: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ 871: { 1.1.1.3 root 872: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); 1.1 root 873: len = (*stream->read)(stream->physical, buf, 1); 874: } 875: 876: if (buf[0] == (_B_EXT | _BX_CLASS)) 877: { 878: char* class_name; 1.1.1.3 root 879: unsigned long version; 1.1 root 880: 881: /* get class */ 882: len = objc_read_string (stream, &class_name); 883: (*class) = objc_get_class(class_name); 884: free (class_name); 885: 886: /* register */ 887: if (key) 1.1.1.3 root 888: hash_add (&stream->stream_table, LONG2PTR(key), *class); 1.1 root 889: 1.1.1.3 root 890: objc_read_unsigned_long(stream, &version); 1.1 root 891: hash_add (&stream->class_table, (*class)->name, (void*)version); 892: } 893: 894: else if ((buf[0]&_B_CODE) == _B_UCOMM) 895: { 896: if (key) 897: __objc_fatal("cannot register use upcode..."); 1.1.1.3 root 898: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); 899: (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key)); 1.1 root 900: if (!*class) 1.1.1.3 root 901: __objc_fatal("cannot find class for key %lu", key); 1.1 root 902: } 903: 904: else 905: __objc_fatal("expected class, got opcode %c", buf[0]); 906: } 907: return len; 908: } 909: 910: int 911: objc_read_selector (struct objc_typed_stream* stream, SEL* selector) 912: { 913: unsigned char buf[sizeof (unsigned int)]; 914: int len; 915: if ((len = (*stream->read)(stream->physical, buf, 1))) 916: { 1.1.1.3 root 917: unsigned long key = 0; 1.1 root 918: 919: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ 920: { 1.1.1.3 root 921: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); 1.1 root 922: len = (*stream->read)(stream->physical, buf, 1); 923: } 924: 925: if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */ 926: { 927: char* selector_name; 928: 929: /* get selector */ 930: len = objc_read_string (stream, &selector_name); 1.1.1.4 ! root 931: /* To handle NULL selectors */ ! 932: if (0 == strlen(selector_name)) ! 933: { ! 934: (*selector) = (SEL)0; ! 935: return 0; ! 936: } ! 937: else ! 938: (*selector) = sel_get_any_uid(selector_name); 1.1 root 939: free (selector_name); 940: 941: /* register */ 942: if (key) 1.1.1.3 root 943: hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector); 1.1 root 944: } 945: 946: else if ((buf[0]&_B_CODE) == _B_UCOMM) 947: { 948: if (key) 949: __objc_fatal("cannot register use upcode..."); 1.1.1.3 root 950: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); 951: (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key)); 1.1 root 952: } 953: 954: else 955: __objc_fatal("expected selector, got opcode %c", buf[0]); 956: } 957: return len; 958: } 959: 960: /* 961: ** USER LEVEL FUNCTIONS 962: */ 963: 964: /* 965: ** Write one object, encoded in TYPE and pointed to by DATA to the 966: ** typed stream STREAM. 967: */ 968: 969: int 970: objc_write_type(TypedStream* stream, const char* type, const void* data) 971: { 972: switch(*type) { 973: case _C_ID: 974: return objc_write_object (stream, *(id*)data); 975: break; 976: 977: case _C_CLASS: 1.1.1.4 ! root 978: return objc_write_class (stream, *(Class*)data); 1.1 root 979: break; 980: 981: case _C_SEL: 982: return objc_write_selector (stream, *(SEL*)data); 983: break; 984: 985: case _C_CHR: 986: return objc_write_char(stream, *(char*)data); 987: break; 988: 989: case _C_UCHR: 990: return objc_write_unsigned_char(stream, *(unsigned char*)data); 991: break; 992: 993: case _C_SHT: 994: return objc_write_short(stream, *(short*)data); 995: break; 996: 997: case _C_USHT: 998: return objc_write_unsigned_short(stream, *(unsigned short*)data); 999: break; 1000: 1001: case _C_INT: 1002: return objc_write_int(stream, *(int*)data); 1003: break; 1004: 1005: case _C_UINT: 1006: return objc_write_unsigned_int(stream, *(unsigned int*)data); 1007: break; 1008: 1.1.1.3 root 1009: case _C_LNG: 1010: return objc_write_long(stream, *(long*)data); 1011: break; 1012: 1013: case _C_ULNG: 1014: return objc_write_unsigned_long(stream, *(unsigned long*)data); 1015: break; 1016: 1.1 root 1017: case _C_CHARPTR: 1.1.1.2 root 1018: return objc_write_string (stream, *(char**)data, strlen(*(char**)data)); 1.1 root 1019: break; 1020: 1021: case _C_ATOM: 1.1.1.2 root 1022: return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data)); 1.1 root 1023: break; 1024: 1025: case _C_ARY_B: 1026: { 1027: int len = atoi(type+1); 1028: while (isdigit(*++type)); 1029: return objc_write_array (stream, type, len, data); 1030: } 1031: break; 1032: 1.1.1.3 root 1033: case _C_STRUCT_B: 1034: { 1035: int acc_size = 0; 1036: int align; 1037: while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */ 1038: while (*type != _C_STRUCT_E); 1039: { 1040: align = objc_alignof_type (type); /* padd to alignment */ 1041: acc_size += ROUND (acc_size, align); 1042: objc_write_type (stream, type, ((char*)data)+acc_size); 1043: acc_size += objc_sizeof_type (type); /* add component size */ 1044: type = objc_skip_typespec (type); /* skip component */ 1045: } 1046: return 1; 1047: } 1048: 1.1 root 1049: default: 1050: fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type); 1051: abort(); 1052: } 1053: } 1054: 1055: /* 1056: ** Read one object, encoded in TYPE and pointed to by DATA to the 1057: ** typed stream STREAM. DATA specifies the address of the types to 1058: ** read. Expected type is checked against the type actually present 1059: ** on the stream. 1060: */ 1061: 1062: int 1063: objc_read_type(TypedStream* stream, const char* type, void* data) 1064: { 1065: char c; 1066: switch(c = *type) { 1067: case _C_ID: 1068: return objc_read_object (stream, (id*)data); 1069: break; 1070: 1071: case _C_CLASS: 1.1.1.4 ! root 1072: return objc_read_class (stream, (Class*)data); 1.1 root 1073: break; 1074: 1075: case _C_SEL: 1076: return objc_read_selector (stream, (SEL*)data); 1077: break; 1078: 1079: case _C_CHR: 1080: return objc_read_char (stream, (char*)data); 1081: break; 1082: 1083: case _C_UCHR: 1084: return objc_read_unsigned_char (stream, (unsigned char*)data); 1085: break; 1086: 1087: case _C_SHT: 1088: return objc_read_short (stream, (short*)data); 1089: break; 1090: 1091: case _C_USHT: 1092: return objc_read_unsigned_short (stream, (unsigned short*)data); 1093: break; 1094: 1095: case _C_INT: 1096: return objc_read_int (stream, (int*)data); 1097: break; 1098: 1099: case _C_UINT: 1100: return objc_read_unsigned_int (stream, (unsigned int*)data); 1101: break; 1102: 1.1.1.3 root 1103: case _C_LNG: 1104: return objc_read_long (stream, (long*)data); 1105: break; 1106: 1107: case _C_ULNG: 1108: return objc_read_unsigned_long (stream, (unsigned long*)data); 1109: break; 1110: 1.1 root 1111: case _C_CHARPTR: 1112: case _C_ATOM: 1113: return objc_read_string (stream, (char**)data); 1114: break; 1115: 1116: case _C_ARY_B: 1117: { 1118: int len = atoi(type+1); 1119: while (isdigit(*++type)); 1120: return objc_read_array (stream, type, len, data); 1121: } 1122: break; 1123: 1.1.1.3 root 1124: case _C_STRUCT_B: 1125: { 1126: int acc_size = 0; 1127: int align; 1128: while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */ 1129: while (*type != _C_STRUCT_E); 1130: { 1131: align = objc_alignof_type (type); /* padd to alignment */ 1132: acc_size += ROUND (acc_size, align); 1133: objc_read_type (stream, type, ((char*)data)+acc_size); 1134: acc_size += objc_sizeof_type (type); /* add component size */ 1135: type = objc_skip_typespec (type); /* skip component */ 1136: } 1137: return 1; 1138: } 1139: 1.1 root 1140: default: 1.1.1.2 root 1141: fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type); 1.1 root 1142: abort(); 1143: } 1144: } 1145: 1146: /* 1147: ** Write the object specified by the template TYPE to STREAM. Last 1148: ** arguments specify addresses of values to be written. It might 1149: ** seem surprising to specify values by address, but this is extremely 1150: ** convenient for copy-paste with objc_read_types calls. A more 1151: ** down-to-the-earth cause for this passing of addresses is that values 1152: ** of arbitrary size is not well supported in ANSI C for functions with 1153: ** variable number of arguments. 1154: */ 1155: 1156: int 1157: objc_write_types (TypedStream* stream, const char* type, ...) 1158: { 1159: va_list args; 1160: const char *c; 1161: int res = 0; 1162: 1163: va_start(args, type); 1164: 1.1.1.3 root 1165: for (c = type; *c; c = objc_skip_typespec (c)) 1.1 root 1166: { 1167: switch(*c) { 1168: case _C_ID: 1169: res = objc_write_object (stream, *va_arg (args, id*)); 1170: break; 1171: 1172: case _C_CLASS: 1.1.1.4 ! root 1173: res = objc_write_class (stream, *va_arg(args, Class*)); 1.1 root 1174: break; 1175: 1176: case _C_SEL: 1177: res = objc_write_selector (stream, *va_arg(args, SEL*)); 1178: break; 1179: 1180: case _C_CHR: 1181: res = objc_write_char (stream, *va_arg (args, char*)); 1182: break; 1183: 1184: case _C_UCHR: 1185: res = objc_write_unsigned_char (stream, 1186: *va_arg (args, unsigned char*)); 1187: break; 1188: 1189: case _C_SHT: 1190: res = objc_write_short (stream, *va_arg(args, short*)); 1191: break; 1192: 1193: case _C_USHT: 1194: res = objc_write_unsigned_short (stream, 1195: *va_arg(args, unsigned short*)); 1196: break; 1197: 1198: case _C_INT: 1199: res = objc_write_int(stream, *va_arg(args, int*)); 1200: break; 1201: 1202: case _C_UINT: 1203: res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*)); 1204: break; 1205: 1.1.1.3 root 1206: case _C_LNG: 1207: res = objc_write_long(stream, *va_arg(args, long*)); 1208: break; 1209: 1210: case _C_ULNG: 1211: res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*)); 1212: break; 1213: 1.1 root 1214: case _C_CHARPTR: 1215: { 1.1.1.2 root 1216: char** str = va_arg(args, char**); 1217: res = objc_write_string (stream, *str, strlen(*str)); 1.1 root 1218: } 1219: break; 1220: 1221: case _C_ATOM: 1222: { 1.1.1.2 root 1223: char** str = va_arg(args, char**); 1224: res = objc_write_string_atomic (stream, *str, strlen(*str)); 1.1 root 1225: } 1226: break; 1227: 1228: case _C_ARY_B: 1229: { 1230: int len = atoi(c+1); 1231: const char* t = c; 1232: while (isdigit(*++t)); 1233: res = objc_write_array (stream, t, len, va_arg(args, void*)); 1.1.1.3 root 1234: t = objc_skip_typespec (t); 1.1 root 1235: if (*t != _C_ARY_E) 1236: __objc_fatal("expected `]', got: %s", t); 1237: } 1238: break; 1239: 1240: default: 1.1.1.2 root 1241: fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type); 1.1 root 1242: abort(); 1243: } 1244: } 1245: va_end(args); 1246: return res; 1247: } 1248: 1249: 1250: /* 1251: ** Last arguments specify addresses of values to be read. Expected 1252: ** type is checked against the type actually present on the stream. 1253: */ 1254: 1255: int 1256: objc_read_types(TypedStream* stream, const char* type, ...) 1257: { 1258: va_list args; 1259: const char *c; 1260: int res = 0; 1261: 1262: va_start(args, type); 1263: 1.1.1.3 root 1264: for (c = type; *c; c = objc_skip_typespec(c)) 1.1 root 1265: { 1266: switch(*c) { 1267: case _C_ID: 1268: res = objc_read_object(stream, va_arg(args, id*)); 1269: break; 1270: 1271: case _C_CLASS: 1.1.1.4 ! root 1272: res = objc_read_class(stream, va_arg(args, Class*)); 1.1 root 1273: break; 1274: 1275: case _C_SEL: 1276: res = objc_read_selector(stream, va_arg(args, SEL*)); 1277: break; 1278: 1279: case _C_CHR: 1280: res = objc_read_char(stream, va_arg(args, char*)); 1281: break; 1282: 1283: case _C_UCHR: 1284: res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*)); 1285: break; 1286: 1287: case _C_SHT: 1288: res = objc_read_short(stream, va_arg(args, short*)); 1289: break; 1290: 1291: case _C_USHT: 1292: res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*)); 1293: break; 1294: 1295: case _C_INT: 1296: res = objc_read_int(stream, va_arg(args, int*)); 1297: break; 1298: 1299: case _C_UINT: 1300: res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*)); 1301: break; 1302: 1.1.1.3 root 1303: case _C_LNG: 1304: res = objc_read_long(stream, va_arg(args, long*)); 1305: break; 1306: 1307: case _C_ULNG: 1308: res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*)); 1309: break; 1310: 1.1 root 1311: case _C_CHARPTR: 1312: case _C_ATOM: 1313: { 1314: char** str = va_arg(args, char**); 1315: res = objc_read_string (stream, str); 1316: } 1317: break; 1318: 1319: case _C_ARY_B: 1320: { 1321: int len = atoi(c+1); 1322: const char* t = c; 1323: while (isdigit(*++t)); 1324: res = objc_read_array (stream, t, len, va_arg(args, void*)); 1.1.1.3 root 1325: t = objc_skip_typespec (t); 1.1 root 1326: if (*t != _C_ARY_E) 1327: __objc_fatal("expected `]', got: %s", t); 1328: } 1329: break; 1330: 1331: default: 1.1.1.2 root 1332: fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type); 1.1 root 1333: abort(); 1334: } 1335: } 1336: va_end(args); 1337: return res; 1338: } 1339: 1340: /* 1341: ** Write an array of COUNT elements of TYPE from the memory address DATA. 1342: ** This is equivalent of objc_write_type (stream, "[N<type>]", data) 1343: */ 1344: 1345: int 1346: objc_write_array (TypedStream* stream, const char* type, 1347: int count, const void* data) 1348: { 1349: int off = objc_sizeof_type(type); 1350: const char* where = data; 1351: 1352: while (count-- > 0) 1353: { 1354: objc_write_type(stream, type, where); 1355: where += off; 1356: } 1357: return 1; 1358: } 1359: 1360: /* 1361: ** Read an array of COUNT elements of TYPE into the memory address 1362: ** DATA. The memory pointed to by data is supposed to be allocated 1363: ** by the callee. This is equivalent of 1364: ** objc_read_type (stream, "[N<type>]", data) 1365: */ 1366: 1367: int 1368: objc_read_array (TypedStream* stream, const char* type, 1369: int count, void* data) 1370: { 1371: int off = objc_sizeof_type(type); 1372: char* where = (char*)data; 1373: 1374: while (count-- > 0) 1375: { 1376: objc_read_type(stream, type, where); 1377: where += off; 1378: } 1379: return 1; 1380: } 1381: 1.1.1.3 root 1382: static void 1383: __objc_free (void* p) 1384: { 1385: free (p); 1386: } 1387: 1.1 root 1388: static int 1389: __objc_fread(FILE* file, char* data, int len) 1390: { 1391: return fread(data, len, 1, file); 1392: } 1393: 1394: static int 1395: __objc_fwrite(FILE* file, char* data, int len) 1396: { 1397: return fwrite(data, len, 1, file); 1398: } 1399: 1400: static int 1401: __objc_feof(FILE* file) 1402: { 1403: return feof(file); 1404: } 1405: 1406: static int 1407: __objc_no_write(FILE* file, char* data, int len) 1408: { 1409: __objc_fatal ("TypedStream not open for writing"); 1410: } 1411: 1412: static int 1413: __objc_no_read(FILE* file, char* data, int len) 1414: { 1415: __objc_fatal ("TypedStream not open for reading"); 1416: } 1417: 1418: static int 1419: __objc_read_typed_stream_signature (TypedStream* stream) 1420: { 1421: char buffer[80]; 1422: int pos = 0; 1423: do 1424: (*stream->read)(stream->physical, buffer+pos, 1); 1425: while (buffer[pos++] != '\0'); 1426: sscanf (buffer, "GNU TypedStream %d", &stream->version); 1427: if (stream->version != OBJC_TYPED_STREAM_VERSION) 1428: __objc_fatal ("cannot handle TypedStream version %d", stream->version); 1429: return 1; 1430: } 1431: 1432: static int 1433: __objc_write_typed_stream_signature (TypedStream* stream) 1434: { 1435: char buffer[80]; 1436: sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION); 1437: stream->version = OBJC_TYPED_STREAM_VERSION; 1438: (*stream->write)(stream->physical, buffer, strlen(buffer)+1); 1439: return 1; 1440: } 1441: 1442: static void __objc_finish_write_root_object(struct objc_typed_stream* stream) 1443: { 1444: hash_delete (stream->object_table); 1445: stream->object_table = hash_new(64, 1446: (hash_func_type)hash_ptr, 1447: (compare_func_type)compare_ptrs); 1448: } 1449: 1450: static void __objc_finish_read_root_object(struct objc_typed_stream* stream) 1451: { 1452: node_ptr node; 1.1.1.3 root 1453: struct objc_list* free_list; 1454: SEL awake_sel = sel_get_any_uid ("awake"); 1.1 root 1455: 1456: /* resolve object forward references */ 1.1.1.3 root 1457: free_list = list_cons(NULL, NULL); 1.1 root 1458: for (node = hash_next (stream->object_refs, NULL); node; 1459: node = hash_next (stream->object_refs, node)) 1460: { 1461: struct objc_list* reflist = node->value; 1462: const void* key = node->key; 1463: id object = hash_value_for_key (stream->object_table, key); 1464: while(reflist) 1465: { 1466: *((id*)reflist->head) = object; 1.1.1.3 root 1467: if (list_find(&free_list, reflist) == NULL) 1468: free_list = list_cons (reflist, free_list); 1.1 root 1469: reflist = reflist->tail; 1470: } 1471: } 1.1.1.3 root 1472: list_mapcar (free_list, __objc_free); 1473: list_free (free_list); 1.1 root 1474: 1475: /* empty object reference table */ 1476: hash_delete (stream->object_refs); 1477: stream->object_refs = hash_new(8, (hash_func_type)hash_ptr, 1478: (compare_func_type)compare_ptrs); 1479: 1480: /* call -awake for all objects read */ 1481: if (awake_sel) 1482: { 1483: for (node = hash_next (stream->object_table, NULL); node; 1484: node = hash_next (stream->object_table, node)) 1485: { 1486: id object = node->value; 1487: if (__objc_responds_to (object, awake_sel)) 1488: (*objc_msg_lookup(object, awake_sel))(object, awake_sel); 1489: } 1490: } 1491: 1492: /* empty object table */ 1493: hash_delete (stream->object_table); 1494: stream->object_table = hash_new(64, 1495: (hash_func_type)hash_ptr, 1496: (compare_func_type)compare_ptrs); 1497: } 1498: 1499: /* 1500: ** Open the stream PHYSICAL in MODE 1501: */ 1502: 1503: TypedStream* 1504: objc_open_typed_stream (FILE* physical, int mode) 1505: { 1506: TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream)); 1507: 1508: s->mode = mode; 1509: s->physical = physical; 1510: s->stream_table = hash_new(64, 1511: (hash_func_type)hash_ptr, 1512: (compare_func_type)compare_ptrs); 1513: s->object_table = hash_new(64, 1514: (hash_func_type)hash_ptr, 1515: (compare_func_type)compare_ptrs); 1516: s->eof = (objc_typed_eof_func)__objc_feof; 1517: s->flush = (objc_typed_flush_func)fflush; 1518: s->writing_root_p = 0; 1519: if (mode == OBJC_READONLY) 1520: { 1521: s->class_table = hash_new(8, (hash_func_type)hash_string, 1522: (compare_func_type)compare_strings); 1523: s->object_refs = hash_new(8, (hash_func_type)hash_ptr, 1524: (compare_func_type)compare_ptrs); 1525: s->read = (objc_typed_read_func)__objc_fread; 1526: s->write = (objc_typed_write_func)__objc_no_write; 1527: __objc_read_typed_stream_signature (s); 1528: } 1529: else if (mode == OBJC_WRITEONLY) 1530: { 1531: s->class_table = 0; 1532: s->object_refs = 0; 1533: s->read = (objc_typed_read_func)__objc_no_read; 1534: s->write = (objc_typed_write_func)__objc_fwrite; 1535: __objc_write_typed_stream_signature (s); 1536: } 1537: else 1538: { 1539: objc_close_typed_stream (s); 1540: return NULL; 1541: } 1542: s->type = OBJC_FILE_STREAM; 1543: return s; 1544: } 1545: 1546: /* 1547: ** Open the file named by FILE_NAME in MODE 1548: */ 1549: 1550: TypedStream* 1551: objc_open_typed_stream_for_file (const char* file_name, int mode) 1552: { 1553: FILE* file = NULL; 1554: TypedStream* s; 1555: 1556: if (mode == OBJC_READONLY) 1557: file = fopen (file_name, "r"); 1558: else 1559: file = fopen (file_name, "w"); 1560: 1561: if (file) 1562: { 1563: s = objc_open_typed_stream (file, mode); 1564: if (s) 1565: s->type |= OBJC_MANAGED_STREAM; 1566: return s; 1567: } 1568: else 1569: return NULL; 1570: } 1571: 1572: /* 1573: ** Close STREAM freeing the structure it self. If it was opened with 1574: ** objc_open_typed_stream_for_file, the file will also be closed. 1575: */ 1576: 1577: void 1578: objc_close_typed_stream (TypedStream* stream) 1579: { 1580: if (stream->mode == OBJC_READONLY) 1581: { 1582: __objc_finish_read_root_object (stream); /* Just in case... */ 1583: hash_delete (stream->class_table); 1584: hash_delete (stream->object_refs); 1585: } 1586: 1587: hash_delete (stream->stream_table); 1588: hash_delete (stream->object_table); 1589: 1590: if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM)) 1591: fclose ((FILE*)stream->physical); 1592: 1593: free (stream); 1594: } 1595: 1596: BOOL 1597: objc_end_of_typed_stream (TypedStream* stream) 1598: { 1599: return (*stream->eof)(stream->physical); 1600: } 1601: 1602: void 1603: objc_flush_typed_stream (TypedStream* stream) 1604: { 1605: (*stream->flush)(stream->physical); 1606: } 1607: 1.1.1.3 root 1608: long 1.1.1.4 ! root 1609: objc_get_stream_class_version (TypedStream* stream, Class class) 1.1 root 1610: { 1611: if (stream->class_table) 1.1.1.3 root 1612: return PTR2LONG(hash_value_for_key (stream->class_table, class->name)); 1.1 root 1613: else 1614: return class_get_version (class); 1615: } 1616:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.