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