|
|
1.1 ! root 1: /* GNU Objective C Runtime archiving ! 2: Copyright (C) 1993, 1994 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: #include "runtime.h" ! 28: #include "typedstream.h" ! 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)) ! 39: ! 40: #define __objc_fatal(format, args...) \ ! 41: { fprintf(stderr, "archiving: "); \ ! 42: fprintf(stderr, format, ## args); \ ! 43: fprintf(stderr, "\n"); abort(); } ! 44: ! 45: /* Declare some functions... */ ! 46: ! 47: static int ! 48: objc_read_class (struct objc_typed_stream* stream, Class** class); ! 49: ! 50: int objc_sizeof_type(const char* type); ! 51: ! 52: static int ! 53: objc_write_use_common (struct objc_typed_stream* stream, unsigned long key); ! 54: ! 55: static int ! 56: objc_write_register_common (struct objc_typed_stream* stream, ! 57: unsigned long key); ! 58: ! 59: static int ! 60: objc_write_class (struct objc_typed_stream* stream, ! 61: struct objc_class* class); ! 62: ! 63: const char* objc_skip_type (const char* type); ! 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: { ! 117: if ((val&_B_VALUE) == val) ! 118: { ! 119: buf[0] = val|_B_SINT; ! 120: return 1; ! 121: } ! 122: else ! 123: { ! 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; ! 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: { ! 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; ! 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: { ! 173: if ((val&_B_VALUE) == val) ! 174: { ! 175: buf[0] = val|_B_SINT; ! 176: return 1; ! 177: } ! 178: else ! 179: { ! 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; ! 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: { ! 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: } ! 216: ! 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: } ! 224: ! 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: } ! 233: else ! 234: { ! 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; ! 251: } ! 252: } ! 253: ! 254: int ! 255: objc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value) ! 256: { ! 257: unsigned char buf[sizeof(unsigned long)+1]; ! 258: int len = __objc_code_unsigned_long (buf, value); ! 259: return (*stream->write)(stream->physical, buf, len); ! 260: } ! 261: ! 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: ! 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: { ! 304: unsigned long key; ! 305: if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string)))) ! 306: return objc_write_use_common (stream, key); ! 307: else ! 308: { ! 309: int length; ! 310: hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string); ! 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 ! 318: objc_write_register_common (struct objc_typed_stream* stream, unsigned long key) ! 319: { ! 320: unsigned char buf[sizeof (unsigned long)+2]; ! 321: int len = __objc_code_unsigned_long (buf+1, key); ! 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 ! 336: objc_write_use_common (struct objc_typed_stream* stream, unsigned long key) ! 337: { ! 338: unsigned char buf[sizeof (unsigned long)+2]; ! 339: int len = __objc_code_unsigned_long (buf+1, key); ! 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'; ! 369: SEL write_sel = sel_get_uid ("write:"); ! 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: { ! 384: unsigned long key; ! 385: if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object)))) ! 386: return objc_write_use_common (stream, key); ! 387: ! 388: __objc_write_extension (stream, _BX_OBJREF); ! 389: return objc_write_unsigned_long (stream, PTR2LONG (object)); ! 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: { ! 412: unsigned long key; ! 413: if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object)))) ! 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; ! 422: hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object); ! 423: if ((length = objc_write_register_common (stream, key))) ! 424: return __objc_write_object (stream, object); ! 425: return length; ! 426: } ! 427: } ! 428: ! 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: ! 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)); ! 441: return objc_write_unsigned_long (stream, CLS_GETNUMBER(class)); ! 442: } ! 443: ! 444: ! 445: static int ! 446: objc_write_class (struct objc_typed_stream* stream, ! 447: struct objc_class* class) ! 448: { ! 449: unsigned long key; ! 450: if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class)))) ! 451: return objc_write_use_common (stream, key); ! 452: else ! 453: { ! 454: int length; ! 455: hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class); ! 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: { ! 466: const char* sel_name = sel_get_name (selector); ! 467: __objc_write_extension (stream, _BX_SEL); ! 468: return objc_write_string (stream, sel_name, strlen ((char*)sel_name)); ! 469: } ! 470: ! 471: int ! 472: objc_write_selector (struct objc_typed_stream* stream, SEL selector) ! 473: { ! 474: const char* sel_name = sel_get_name (selector); ! 475: unsigned long key; ! 476: if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name)))) ! 477: return objc_write_use_common (stream, key); ! 478: else ! 479: { ! 480: int length; ! 481: hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name); ! 482: if ((length = objc_write_register_common (stream, key))) ! 483: return __objc_write_selector (stream, selector); ! 484: return length; ! 485: } ! 486: } ! 487: ! 488: ! 489: ! 490: /* ! 491: ** Read operations ! 492: */ ! 493: ! 494: __inline__ int ! 495: objc_read_char (struct objc_typed_stream* stream, char* val) ! 496: { ! 497: unsigned char buf; ! 498: int len; ! 499: len = (*stream->read)(stream->physical, &buf, 1); ! 500: if (len != 0) ! 501: { ! 502: if ((buf & _B_CODE) == _B_SINT) ! 503: (*val) = (buf & _B_VALUE); ! 504: ! 505: else if ((buf & _B_NUMBER) == 1) ! 506: { ! 507: len = (*stream->read)(stream->physical, val, 1); ! 508: if (buf&_B_SIGN) ! 509: (*val) = -1*(*val); ! 510: } ! 511: ! 512: else ! 513: __objc_fatal("expected 8bit signed int, got %dbit int", ! 514: (int)(buf&_B_NUMBER)*8); ! 515: } ! 516: return len; ! 517: } ! 518: ! 519: ! 520: __inline__ int ! 521: objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val) ! 522: { ! 523: unsigned char buf; ! 524: int len; ! 525: if ((len = (*stream->read)(stream->physical, &buf, 1))) ! 526: { ! 527: if ((buf & _B_CODE) == _B_SINT) ! 528: (*val) = (buf & _B_VALUE); ! 529: ! 530: else if ((buf & _B_NUMBER) == 1) ! 531: len = (*stream->read)(stream->physical, val, 1); ! 532: ! 533: else ! 534: __objc_fatal("expected 8bit unsigned int, got %dbit int", ! 535: (int)(buf&_B_NUMBER)*8); ! 536: } ! 537: return len; ! 538: } ! 539: ! 540: __inline__ int ! 541: objc_read_short (struct objc_typed_stream* stream, short* value) ! 542: { ! 543: unsigned char buf[sizeof(short)+1]; ! 544: int len; ! 545: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 546: { ! 547: if ((buf[0] & _B_CODE) == _B_SINT) ! 548: (*value) = (buf[0] & _B_VALUE); ! 549: ! 550: else ! 551: { ! 552: int pos = 1; ! 553: int nbytes = buf[0] & _B_NUMBER; ! 554: if (nbytes > sizeof (short)) ! 555: __objc_fatal("expected short, got bigger (%dbits)", nbytes*8); ! 556: len = (*stream->read)(stream->physical, buf+1, nbytes); ! 557: (*value) = 0; ! 558: while (pos <= nbytes) ! 559: (*value) = ((*value)*0x100) + buf[pos++]; ! 560: if (buf[0] & _B_SIGN) ! 561: (*value) = -(*value); ! 562: } ! 563: } ! 564: return len; ! 565: } ! 566: ! 567: __inline__ int ! 568: objc_read_unsigned_short (struct objc_typed_stream* stream, ! 569: unsigned short* value) ! 570: { ! 571: unsigned char buf[sizeof(unsigned short)+1]; ! 572: int len; ! 573: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 574: { ! 575: if ((buf[0] & _B_CODE) == _B_SINT) ! 576: (*value) = (buf[0] & _B_VALUE); ! 577: ! 578: else ! 579: { ! 580: int pos = 1; ! 581: int nbytes = buf[0] & _B_NUMBER; ! 582: if (nbytes > sizeof (short)) ! 583: __objc_fatal("expected short, got int or bigger"); ! 584: len = (*stream->read)(stream->physical, buf+1, nbytes); ! 585: (*value) = 0; ! 586: while (pos <= nbytes) ! 587: (*value) = ((*value)*0x100) + buf[pos++]; ! 588: } ! 589: } ! 590: return len; ! 591: } ! 592: ! 593: ! 594: __inline__ int ! 595: objc_read_int (struct objc_typed_stream* stream, int* value) ! 596: { ! 597: unsigned char buf[sizeof(int)+1]; ! 598: int len; ! 599: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 600: { ! 601: if ((buf[0] & _B_CODE) == _B_SINT) ! 602: (*value) = (buf[0] & _B_VALUE); ! 603: ! 604: else ! 605: { ! 606: int pos = 1; ! 607: int nbytes = buf[0] & _B_NUMBER; ! 608: if (nbytes > sizeof (int)) ! 609: __objc_fatal("expected int, got bigger"); ! 610: len = (*stream->read)(stream->physical, buf+1, nbytes); ! 611: (*value) = 0; ! 612: while (pos <= nbytes) ! 613: (*value) = ((*value)*0x100) + buf[pos++]; ! 614: if (buf[0] & _B_SIGN) ! 615: (*value) = -(*value); ! 616: } ! 617: } ! 618: return len; ! 619: } ! 620: ! 621: __inline__ int ! 622: objc_read_long (struct objc_typed_stream* stream, long* value) ! 623: { ! 624: unsigned char buf[sizeof(long)+1]; ! 625: int len; ! 626: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 627: { ! 628: if ((buf[0] & _B_CODE) == _B_SINT) ! 629: (*value) = (buf[0] & _B_VALUE); ! 630: ! 631: else ! 632: { ! 633: int pos = 1; ! 634: int nbytes = buf[0] & _B_NUMBER; ! 635: if (nbytes > sizeof (long)) ! 636: __objc_fatal("expected long, got bigger"); ! 637: len = (*stream->read)(stream->physical, buf+1, nbytes); ! 638: (*value) = 0; ! 639: while (pos <= nbytes) ! 640: (*value) = ((*value)*0x100) + buf[pos++]; ! 641: if (buf[0] & _B_SIGN) ! 642: (*value) = -(*value); ! 643: } ! 644: } ! 645: return len; ! 646: } ! 647: ! 648: __inline__ int ! 649: __objc_read_nbyte_uint (struct objc_typed_stream* stream, ! 650: unsigned int nbytes, unsigned int* val) ! 651: { ! 652: int len, pos = 0; ! 653: unsigned char buf[sizeof(unsigned int)+1]; ! 654: ! 655: if (nbytes > sizeof (int)) ! 656: __objc_fatal("expected int, got bigger"); ! 657: ! 658: len = (*stream->read)(stream->physical, buf, nbytes); ! 659: (*val) = 0; ! 660: while (pos < nbytes) ! 661: (*val) = ((*val)*0x100) + buf[pos++]; ! 662: return len; ! 663: } ! 664: ! 665: ! 666: __inline__ int ! 667: objc_read_unsigned_int (struct objc_typed_stream* stream, ! 668: unsigned int* value) ! 669: { ! 670: unsigned char buf[sizeof(unsigned int)+1]; ! 671: int len; ! 672: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 673: { ! 674: if ((buf[0] & _B_CODE) == _B_SINT) ! 675: (*value) = (buf[0] & _B_VALUE); ! 676: ! 677: else ! 678: len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value); ! 679: ! 680: } ! 681: return len; ! 682: } ! 683: ! 684: int ! 685: __objc_read_nbyte_ulong (struct objc_typed_stream* stream, ! 686: unsigned int nbytes, unsigned long* val) ! 687: { ! 688: int len, pos = 0; ! 689: unsigned char buf[sizeof(unsigned long)+1]; ! 690: ! 691: if (nbytes > sizeof (long)) ! 692: __objc_fatal("expected long, got bigger"); ! 693: ! 694: len = (*stream->read)(stream->physical, buf, nbytes); ! 695: (*val) = 0; ! 696: while (pos < nbytes) ! 697: (*val) = ((*val)*0x100) + buf[pos++]; ! 698: return len; ! 699: } ! 700: ! 701: ! 702: __inline__ int ! 703: objc_read_unsigned_long (struct objc_typed_stream* stream, ! 704: unsigned long* value) ! 705: { ! 706: unsigned char buf[sizeof(unsigned long)+1]; ! 707: int len; ! 708: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 709: { ! 710: if ((buf[0] & _B_CODE) == _B_SINT) ! 711: (*value) = (buf[0] & _B_VALUE); ! 712: ! 713: else ! 714: len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value); ! 715: ! 716: } ! 717: return len; ! 718: } ! 719: ! 720: __inline__ int ! 721: objc_read_string (struct objc_typed_stream* stream, ! 722: char** string) ! 723: { ! 724: unsigned char buf[sizeof(unsigned int)+1]; ! 725: int len; ! 726: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 727: { ! 728: unsigned long key = 0; ! 729: ! 730: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ ! 731: { ! 732: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); ! 733: len = (*stream->read)(stream->physical, buf, 1); ! 734: } ! 735: ! 736: switch (buf[0]&_B_CODE) { ! 737: case _B_SSTR: ! 738: { ! 739: int length = buf[0]&_B_VALUE; ! 740: (*string) = (char*)__objc_xmalloc(length+1); ! 741: if (key) ! 742: hash_add (&stream->stream_table, LONG2PTR(key), *string); ! 743: len = (*stream->read)(stream->physical, *string, length); ! 744: (*string)[length] = '\0'; ! 745: } ! 746: break; ! 747: ! 748: case _B_UCOMM: ! 749: { ! 750: char *tmp; ! 751: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); ! 752: tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key)); ! 753: *string = __objc_xmalloc (strlen(tmp) + 1); ! 754: strcpy (*string, tmp); ! 755: } ! 756: break; ! 757: ! 758: case _B_NSTR: ! 759: { ! 760: unsigned int nbytes = buf[0]&_B_VALUE; ! 761: len = __objc_read_nbyte_uint(stream, nbytes, &nbytes); ! 762: if (len) { ! 763: (*string) = (char*)__objc_xmalloc(nbytes+1); ! 764: if (key) ! 765: hash_add (&stream->stream_table, LONG2PTR(key), *string); ! 766: len = (*stream->read)(stream->physical, *string, nbytes); ! 767: (*string)[nbytes] = '\0'; ! 768: } ! 769: } ! 770: break; ! 771: ! 772: default: ! 773: __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE)); ! 774: } ! 775: } ! 776: ! 777: return len; ! 778: } ! 779: ! 780: ! 781: int ! 782: objc_read_object (struct objc_typed_stream* stream, id* object) ! 783: { ! 784: unsigned char buf[sizeof (unsigned int)]; ! 785: int len; ! 786: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 787: { ! 788: SEL read_sel = sel_get_uid ("read:"); ! 789: unsigned long key = 0; ! 790: ! 791: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */ ! 792: { ! 793: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); ! 794: len = (*stream->read)(stream->physical, buf, 1); ! 795: } ! 796: ! 797: if (buf[0] == (_B_EXT | _BX_OBJECT)) ! 798: { ! 799: Class* class; ! 800: ! 801: /* get class */ ! 802: len = objc_read_class (stream, &class); ! 803: ! 804: /* create instance */ ! 805: (*object) = class_create_instance(class); ! 806: ! 807: /* register? */ ! 808: if (key) ! 809: hash_add (&stream->object_table, LONG2PTR(key), *object); ! 810: ! 811: /* send -read: */ ! 812: if (__objc_responds_to (*object, read_sel)) ! 813: (*get_imp(class, read_sel))(*object, read_sel, stream); ! 814: ! 815: /* check null-byte */ ! 816: len = (*stream->read)(stream->physical, buf, 1); ! 817: if (buf[0] != '\0') ! 818: __objc_fatal("expected null-byte, got opcode %c", buf[0]); ! 819: } ! 820: ! 821: else if ((buf[0]&_B_CODE) == _B_UCOMM) ! 822: { ! 823: if (key) ! 824: __objc_fatal("cannot register use upcode..."); ! 825: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); ! 826: (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key)); ! 827: } ! 828: ! 829: else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */ ! 830: { ! 831: struct objc_list* other; ! 832: len = objc_read_unsigned_long (stream, &key); ! 833: other = (struct objc_list*)hash_value_for_key (stream->object_refs, LONG2PTR(key)); ! 834: hash_add (&stream->object_refs, LONG2PTR(key), (void*)list_cons(object, other)); ! 835: } ! 836: ! 837: else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */ ! 838: { ! 839: if (key) ! 840: __objc_fatal("cannot register root object..."); ! 841: len = objc_read_object (stream, object); ! 842: __objc_finish_read_root_object (stream); ! 843: } ! 844: ! 845: else ! 846: __objc_fatal("expected object, got opcode %c", buf[0]); ! 847: } ! 848: return len; ! 849: } ! 850: ! 851: static int ! 852: objc_read_class (struct objc_typed_stream* stream, Class** class) ! 853: { ! 854: unsigned char buf[sizeof (unsigned int)]; ! 855: int len; ! 856: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 857: { ! 858: unsigned long key = 0; ! 859: ! 860: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ ! 861: { ! 862: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); ! 863: len = (*stream->read)(stream->physical, buf, 1); ! 864: } ! 865: ! 866: if (buf[0] == (_B_EXT | _BX_CLASS)) ! 867: { ! 868: char* class_name; ! 869: unsigned long version; ! 870: ! 871: /* get class */ ! 872: len = objc_read_string (stream, &class_name); ! 873: (*class) = objc_get_class(class_name); ! 874: free (class_name); ! 875: ! 876: /* register */ ! 877: if (key) ! 878: hash_add (&stream->stream_table, LONG2PTR(key), *class); ! 879: ! 880: objc_read_unsigned_long(stream, &version); ! 881: hash_add (&stream->class_table, (*class)->name, (void*)version); ! 882: } ! 883: ! 884: else if ((buf[0]&_B_CODE) == _B_UCOMM) ! 885: { ! 886: if (key) ! 887: __objc_fatal("cannot register use upcode..."); ! 888: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); ! 889: (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key)); ! 890: if (!*class) ! 891: __objc_fatal("cannot find class for key %lu", key); ! 892: } ! 893: ! 894: else ! 895: __objc_fatal("expected class, got opcode %c", buf[0]); ! 896: } ! 897: return len; ! 898: } ! 899: ! 900: int ! 901: objc_read_selector (struct objc_typed_stream* stream, SEL* selector) ! 902: { ! 903: unsigned char buf[sizeof (unsigned int)]; ! 904: int len; ! 905: if ((len = (*stream->read)(stream->physical, buf, 1))) ! 906: { ! 907: unsigned long key = 0; ! 908: ! 909: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ ! 910: { ! 911: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); ! 912: len = (*stream->read)(stream->physical, buf, 1); ! 913: } ! 914: ! 915: if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */ ! 916: { ! 917: char* selector_name; ! 918: ! 919: /* get selector */ ! 920: len = objc_read_string (stream, &selector_name); ! 921: (*selector) = sel_get_uid(selector_name); ! 922: free (selector_name); ! 923: ! 924: /* register */ ! 925: if (key) ! 926: hash_add (&stream->stream_table, LONG2PTR(key), *selector); ! 927: } ! 928: ! 929: else if ((buf[0]&_B_CODE) == _B_UCOMM) ! 930: { ! 931: if (key) ! 932: __objc_fatal("cannot register use upcode..."); ! 933: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); ! 934: (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key)); ! 935: } ! 936: ! 937: else ! 938: __objc_fatal("expected selector, got opcode %c", buf[0]); ! 939: } ! 940: return len; ! 941: } ! 942: ! 943: /* ! 944: ** USER LEVEL FUNCTIONS ! 945: */ ! 946: ! 947: /* ! 948: ** Write one object, encoded in TYPE and pointed to by DATA to the ! 949: ** typed stream STREAM. ! 950: */ ! 951: ! 952: int ! 953: objc_write_type(TypedStream* stream, const char* type, const void* data) ! 954: { ! 955: switch(*type) { ! 956: case _C_ID: ! 957: return objc_write_object (stream, *(id*)data); ! 958: break; ! 959: ! 960: case _C_CLASS: ! 961: return objc_write_class (stream, *(Class**)data); ! 962: break; ! 963: ! 964: case _C_SEL: ! 965: return objc_write_selector (stream, *(SEL*)data); ! 966: break; ! 967: ! 968: case _C_CHR: ! 969: return objc_write_char(stream, *(char*)data); ! 970: break; ! 971: ! 972: case _C_UCHR: ! 973: return objc_write_unsigned_char(stream, *(unsigned char*)data); ! 974: break; ! 975: ! 976: case _C_SHT: ! 977: return objc_write_short(stream, *(short*)data); ! 978: break; ! 979: ! 980: case _C_USHT: ! 981: return objc_write_unsigned_short(stream, *(unsigned short*)data); ! 982: break; ! 983: ! 984: case _C_INT: ! 985: return objc_write_int(stream, *(int*)data); ! 986: break; ! 987: ! 988: case _C_UINT: ! 989: return objc_write_unsigned_int(stream, *(unsigned int*)data); ! 990: break; ! 991: ! 992: case _C_LNG: ! 993: return objc_write_long(stream, *(long*)data); ! 994: break; ! 995: ! 996: case _C_ULNG: ! 997: return objc_write_unsigned_long(stream, *(unsigned long*)data); ! 998: break; ! 999: ! 1000: case _C_CHARPTR: ! 1001: return objc_write_string (stream, *(char**)data, strlen(*(char**)data)); ! 1002: break; ! 1003: ! 1004: case _C_ATOM: ! 1005: return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data)); ! 1006: break; ! 1007: ! 1008: case _C_ARY_B: ! 1009: { ! 1010: int len = atoi(type+1); ! 1011: while (isdigit(*++type)); ! 1012: return objc_write_array (stream, type, len, data); ! 1013: } ! 1014: break; ! 1015: ! 1016: case _C_STRUCT_B: ! 1017: { ! 1018: int acc_size = 0; ! 1019: int align; ! 1020: while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */ ! 1021: while (*type != _C_STRUCT_E); ! 1022: { ! 1023: align = objc_alignof_type (type); /* padd to alignment */ ! 1024: acc_size += ROUND (acc_size, align); ! 1025: objc_write_type (stream, type, ((char*)data)+acc_size); ! 1026: acc_size += objc_sizeof_type (type); /* add component size */ ! 1027: type = objc_skip_typespec (type); /* skip component */ ! 1028: } ! 1029: return 1; ! 1030: } ! 1031: ! 1032: default: ! 1033: fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type); ! 1034: abort(); ! 1035: } ! 1036: } ! 1037: ! 1038: /* ! 1039: ** Read one object, encoded in TYPE and pointed to by DATA to the ! 1040: ** typed stream STREAM. DATA specifies the address of the types to ! 1041: ** read. Expected type is checked against the type actually present ! 1042: ** on the stream. ! 1043: */ ! 1044: ! 1045: int ! 1046: objc_read_type(TypedStream* stream, const char* type, void* data) ! 1047: { ! 1048: char c; ! 1049: switch(c = *type) { ! 1050: case _C_ID: ! 1051: return objc_read_object (stream, (id*)data); ! 1052: break; ! 1053: ! 1054: case _C_CLASS: ! 1055: return objc_read_class (stream, (Class**)data); ! 1056: break; ! 1057: ! 1058: case _C_SEL: ! 1059: return objc_read_selector (stream, (SEL*)data); ! 1060: break; ! 1061: ! 1062: case _C_CHR: ! 1063: return objc_read_char (stream, (char*)data); ! 1064: break; ! 1065: ! 1066: case _C_UCHR: ! 1067: return objc_read_unsigned_char (stream, (unsigned char*)data); ! 1068: break; ! 1069: ! 1070: case _C_SHT: ! 1071: return objc_read_short (stream, (short*)data); ! 1072: break; ! 1073: ! 1074: case _C_USHT: ! 1075: return objc_read_unsigned_short (stream, (unsigned short*)data); ! 1076: break; ! 1077: ! 1078: case _C_INT: ! 1079: return objc_read_int (stream, (int*)data); ! 1080: break; ! 1081: ! 1082: case _C_UINT: ! 1083: return objc_read_unsigned_int (stream, (unsigned int*)data); ! 1084: break; ! 1085: ! 1086: case _C_LNG: ! 1087: return objc_read_long (stream, (long*)data); ! 1088: break; ! 1089: ! 1090: case _C_ULNG: ! 1091: return objc_read_unsigned_long (stream, (unsigned long*)data); ! 1092: break; ! 1093: ! 1094: case _C_CHARPTR: ! 1095: case _C_ATOM: ! 1096: return objc_read_string (stream, (char**)data); ! 1097: break; ! 1098: ! 1099: case _C_ARY_B: ! 1100: { ! 1101: int len = atoi(type+1); ! 1102: while (isdigit(*++type)); ! 1103: return objc_read_array (stream, type, len, data); ! 1104: } ! 1105: break; ! 1106: ! 1107: case _C_STRUCT_B: ! 1108: { ! 1109: int acc_size = 0; ! 1110: int align; ! 1111: while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */ ! 1112: while (*type != _C_STRUCT_E); ! 1113: { ! 1114: align = objc_alignof_type (type); /* padd to alignment */ ! 1115: acc_size += ROUND (acc_size, align); ! 1116: objc_read_type (stream, type, ((char*)data)+acc_size); ! 1117: acc_size += objc_sizeof_type (type); /* add component size */ ! 1118: type = objc_skip_typespec (type); /* skip component */ ! 1119: } ! 1120: return 1; ! 1121: } ! 1122: ! 1123: default: ! 1124: fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type); ! 1125: abort(); ! 1126: } ! 1127: } ! 1128: ! 1129: /* ! 1130: ** Write the object specified by the template TYPE to STREAM. Last ! 1131: ** arguments specify addresses of values to be written. It might ! 1132: ** seem surprising to specify values by address, but this is extremely ! 1133: ** convenient for copy-paste with objc_read_types calls. A more ! 1134: ** down-to-the-earth cause for this passing of addresses is that values ! 1135: ** of arbitrary size is not well supported in ANSI C for functions with ! 1136: ** variable number of arguments. ! 1137: */ ! 1138: ! 1139: int ! 1140: objc_write_types (TypedStream* stream, const char* type, ...) ! 1141: { ! 1142: va_list args; ! 1143: const char *c; ! 1144: int res = 0; ! 1145: ! 1146: va_start(args, type); ! 1147: ! 1148: for (c = type; *c; c = objc_skip_typespec (c)) ! 1149: { ! 1150: switch(*c) { ! 1151: case _C_ID: ! 1152: res = objc_write_object (stream, *va_arg (args, id*)); ! 1153: break; ! 1154: ! 1155: case _C_CLASS: ! 1156: res = objc_write_class (stream, *va_arg(args, Class**)); ! 1157: break; ! 1158: ! 1159: case _C_SEL: ! 1160: res = objc_write_selector (stream, *va_arg(args, SEL*)); ! 1161: break; ! 1162: ! 1163: case _C_CHR: ! 1164: res = objc_write_char (stream, *va_arg (args, char*)); ! 1165: break; ! 1166: ! 1167: case _C_UCHR: ! 1168: res = objc_write_unsigned_char (stream, ! 1169: *va_arg (args, unsigned char*)); ! 1170: break; ! 1171: ! 1172: case _C_SHT: ! 1173: res = objc_write_short (stream, *va_arg(args, short*)); ! 1174: break; ! 1175: ! 1176: case _C_USHT: ! 1177: res = objc_write_unsigned_short (stream, ! 1178: *va_arg(args, unsigned short*)); ! 1179: break; ! 1180: ! 1181: case _C_INT: ! 1182: res = objc_write_int(stream, *va_arg(args, int*)); ! 1183: break; ! 1184: ! 1185: case _C_UINT: ! 1186: res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*)); ! 1187: break; ! 1188: ! 1189: case _C_LNG: ! 1190: res = objc_write_long(stream, *va_arg(args, long*)); ! 1191: break; ! 1192: ! 1193: case _C_ULNG: ! 1194: res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*)); ! 1195: break; ! 1196: ! 1197: case _C_CHARPTR: ! 1198: { ! 1199: char** str = va_arg(args, char**); ! 1200: res = objc_write_string (stream, *str, strlen(*str)); ! 1201: } ! 1202: break; ! 1203: ! 1204: case _C_ATOM: ! 1205: { ! 1206: char** str = va_arg(args, char**); ! 1207: res = objc_write_string_atomic (stream, *str, strlen(*str)); ! 1208: } ! 1209: break; ! 1210: ! 1211: case _C_ARY_B: ! 1212: { ! 1213: int len = atoi(c+1); ! 1214: const char* t = c; ! 1215: while (isdigit(*++t)); ! 1216: res = objc_write_array (stream, t, len, va_arg(args, void*)); ! 1217: t = objc_skip_typespec (t); ! 1218: if (*t != _C_ARY_E) ! 1219: __objc_fatal("expected `]', got: %s", t); ! 1220: } ! 1221: break; ! 1222: ! 1223: default: ! 1224: fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type); ! 1225: abort(); ! 1226: } ! 1227: } ! 1228: va_end(args); ! 1229: return res; ! 1230: } ! 1231: ! 1232: ! 1233: /* ! 1234: ** Last arguments specify addresses of values to be read. Expected ! 1235: ** type is checked against the type actually present on the stream. ! 1236: */ ! 1237: ! 1238: int ! 1239: objc_read_types(TypedStream* stream, const char* type, ...) ! 1240: { ! 1241: va_list args; ! 1242: const char *c; ! 1243: int res = 0; ! 1244: ! 1245: va_start(args, type); ! 1246: ! 1247: for (c = type; *c; c = objc_skip_typespec(c)) ! 1248: { ! 1249: switch(*c) { ! 1250: case _C_ID: ! 1251: res = objc_read_object(stream, va_arg(args, id*)); ! 1252: break; ! 1253: ! 1254: case _C_CLASS: ! 1255: res = objc_read_class(stream, va_arg(args, Class**)); ! 1256: break; ! 1257: ! 1258: case _C_SEL: ! 1259: res = objc_read_selector(stream, va_arg(args, SEL*)); ! 1260: break; ! 1261: ! 1262: case _C_CHR: ! 1263: res = objc_read_char(stream, va_arg(args, char*)); ! 1264: break; ! 1265: ! 1266: case _C_UCHR: ! 1267: res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*)); ! 1268: break; ! 1269: ! 1270: case _C_SHT: ! 1271: res = objc_read_short(stream, va_arg(args, short*)); ! 1272: break; ! 1273: ! 1274: case _C_USHT: ! 1275: res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*)); ! 1276: break; ! 1277: ! 1278: case _C_INT: ! 1279: res = objc_read_int(stream, va_arg(args, int*)); ! 1280: break; ! 1281: ! 1282: case _C_UINT: ! 1283: res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*)); ! 1284: break; ! 1285: ! 1286: case _C_LNG: ! 1287: res = objc_read_long(stream, va_arg(args, long*)); ! 1288: break; ! 1289: ! 1290: case _C_ULNG: ! 1291: res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*)); ! 1292: break; ! 1293: ! 1294: case _C_CHARPTR: ! 1295: case _C_ATOM: ! 1296: { ! 1297: char** str = va_arg(args, char**); ! 1298: res = objc_read_string (stream, str); ! 1299: } ! 1300: break; ! 1301: ! 1302: case _C_ARY_B: ! 1303: { ! 1304: int len = atoi(c+1); ! 1305: const char* t = c; ! 1306: while (isdigit(*++t)); ! 1307: res = objc_read_array (stream, t, len, va_arg(args, void*)); ! 1308: t = objc_skip_typespec (t); ! 1309: if (*t != _C_ARY_E) ! 1310: __objc_fatal("expected `]', got: %s", t); ! 1311: } ! 1312: break; ! 1313: ! 1314: default: ! 1315: fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type); ! 1316: abort(); ! 1317: } ! 1318: } ! 1319: va_end(args); ! 1320: return res; ! 1321: } ! 1322: ! 1323: /* ! 1324: ** Write an array of COUNT elements of TYPE from the memory address DATA. ! 1325: ** This is equivalent of objc_write_type (stream, "[N<type>]", data) ! 1326: */ ! 1327: ! 1328: int ! 1329: objc_write_array (TypedStream* stream, const char* type, ! 1330: int count, const void* data) ! 1331: { ! 1332: int off = objc_sizeof_type(type); ! 1333: const char* where = data; ! 1334: ! 1335: while (count-- > 0) ! 1336: { ! 1337: objc_write_type(stream, type, where); ! 1338: where += off; ! 1339: } ! 1340: return 1; ! 1341: } ! 1342: ! 1343: /* ! 1344: ** Read an array of COUNT elements of TYPE into the memory address ! 1345: ** DATA. The memory pointed to by data is supposed to be allocated ! 1346: ** by the callee. This is equivalent of ! 1347: ** objc_read_type (stream, "[N<type>]", data) ! 1348: */ ! 1349: ! 1350: int ! 1351: objc_read_array (TypedStream* stream, const char* type, ! 1352: int count, void* data) ! 1353: { ! 1354: int off = objc_sizeof_type(type); ! 1355: char* where = (char*)data; ! 1356: ! 1357: while (count-- > 0) ! 1358: { ! 1359: objc_read_type(stream, type, where); ! 1360: where += off; ! 1361: } ! 1362: return 1; ! 1363: } ! 1364: ! 1365: static int ! 1366: __objc_fread(FILE* file, char* data, int len) ! 1367: { ! 1368: return fread(data, len, 1, file); ! 1369: } ! 1370: ! 1371: static int ! 1372: __objc_fwrite(FILE* file, char* data, int len) ! 1373: { ! 1374: return fwrite(data, len, 1, file); ! 1375: } ! 1376: ! 1377: static int ! 1378: __objc_feof(FILE* file) ! 1379: { ! 1380: return feof(file); ! 1381: } ! 1382: ! 1383: static int ! 1384: __objc_no_write(FILE* file, char* data, int len) ! 1385: { ! 1386: __objc_fatal ("TypedStream not open for writing"); ! 1387: } ! 1388: ! 1389: static int ! 1390: __objc_no_read(FILE* file, char* data, int len) ! 1391: { ! 1392: __objc_fatal ("TypedStream not open for reading"); ! 1393: } ! 1394: ! 1395: static int ! 1396: __objc_read_typed_stream_signature (TypedStream* stream) ! 1397: { ! 1398: char buffer[80]; ! 1399: int pos = 0; ! 1400: do ! 1401: (*stream->read)(stream->physical, buffer+pos, 1); ! 1402: while (buffer[pos++] != '\0'); ! 1403: sscanf (buffer, "GNU TypedStream %d", &stream->version); ! 1404: if (stream->version != OBJC_TYPED_STREAM_VERSION) ! 1405: __objc_fatal ("cannot handle TypedStream version %d", stream->version); ! 1406: return 1; ! 1407: } ! 1408: ! 1409: static int ! 1410: __objc_write_typed_stream_signature (TypedStream* stream) ! 1411: { ! 1412: char buffer[80]; ! 1413: sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION); ! 1414: stream->version = OBJC_TYPED_STREAM_VERSION; ! 1415: (*stream->write)(stream->physical, buffer, strlen(buffer)+1); ! 1416: return 1; ! 1417: } ! 1418: ! 1419: static void __objc_finish_write_root_object(struct objc_typed_stream* stream) ! 1420: { ! 1421: hash_delete (stream->object_table); ! 1422: stream->object_table = hash_new(64, ! 1423: (hash_func_type)hash_ptr, ! 1424: (compare_func_type)compare_ptrs); ! 1425: } ! 1426: ! 1427: static void __objc_finish_read_root_object(struct objc_typed_stream* stream) ! 1428: { ! 1429: node_ptr node; ! 1430: SEL awake_sel = sel_get_uid ("awake"); ! 1431: ! 1432: /* resolve object forward references */ ! 1433: for (node = hash_next (stream->object_refs, NULL); node; ! 1434: node = hash_next (stream->object_refs, node)) ! 1435: { ! 1436: struct objc_list* reflist = node->value; ! 1437: const void* key = node->key; ! 1438: id object = hash_value_for_key (stream->object_table, key); ! 1439: while(reflist) ! 1440: { ! 1441: *((id*)reflist->head) = object; ! 1442: reflist = reflist->tail; ! 1443: } ! 1444: list_free (node->value); ! 1445: } ! 1446: ! 1447: /* empty object reference table */ ! 1448: hash_delete (stream->object_refs); ! 1449: stream->object_refs = hash_new(8, (hash_func_type)hash_ptr, ! 1450: (compare_func_type)compare_ptrs); ! 1451: ! 1452: /* call -awake for all objects read */ ! 1453: if (awake_sel) ! 1454: { ! 1455: for (node = hash_next (stream->object_table, NULL); node; ! 1456: node = hash_next (stream->object_table, node)) ! 1457: { ! 1458: id object = node->value; ! 1459: if (__objc_responds_to (object, awake_sel)) ! 1460: (*objc_msg_lookup(object, awake_sel, "@"))(object, awake_sel); ! 1461: } ! 1462: } ! 1463: ! 1464: /* empty object table */ ! 1465: hash_delete (stream->object_table); ! 1466: stream->object_table = hash_new(64, ! 1467: (hash_func_type)hash_ptr, ! 1468: (compare_func_type)compare_ptrs); ! 1469: } ! 1470: ! 1471: /* ! 1472: ** Open the stream PHYSICAL in MODE ! 1473: */ ! 1474: ! 1475: TypedStream* ! 1476: objc_open_typed_stream (FILE* physical, int mode) ! 1477: { ! 1478: TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream)); ! 1479: ! 1480: s->mode = mode; ! 1481: s->physical = physical; ! 1482: s->stream_table = hash_new(64, ! 1483: (hash_func_type)hash_ptr, ! 1484: (compare_func_type)compare_ptrs); ! 1485: s->object_table = hash_new(64, ! 1486: (hash_func_type)hash_ptr, ! 1487: (compare_func_type)compare_ptrs); ! 1488: s->eof = (objc_typed_eof_func)__objc_feof; ! 1489: s->flush = (objc_typed_flush_func)fflush; ! 1490: s->writing_root_p = 0; ! 1491: if (mode == OBJC_READONLY) ! 1492: { ! 1493: s->class_table = hash_new(8, (hash_func_type)hash_string, ! 1494: (compare_func_type)compare_strings); ! 1495: s->object_refs = hash_new(8, (hash_func_type)hash_ptr, ! 1496: (compare_func_type)compare_ptrs); ! 1497: s->read = (objc_typed_read_func)__objc_fread; ! 1498: s->write = (objc_typed_write_func)__objc_no_write; ! 1499: __objc_read_typed_stream_signature (s); ! 1500: } ! 1501: else if (mode == OBJC_WRITEONLY) ! 1502: { ! 1503: s->class_table = 0; ! 1504: s->object_refs = 0; ! 1505: s->read = (objc_typed_read_func)__objc_no_read; ! 1506: s->write = (objc_typed_write_func)__objc_fwrite; ! 1507: __objc_write_typed_stream_signature (s); ! 1508: } ! 1509: else ! 1510: { ! 1511: objc_close_typed_stream (s); ! 1512: return NULL; ! 1513: } ! 1514: s->type = OBJC_FILE_STREAM; ! 1515: return s; ! 1516: } ! 1517: ! 1518: /* ! 1519: ** Open the file named by FILE_NAME in MODE ! 1520: */ ! 1521: ! 1522: TypedStream* ! 1523: objc_open_typed_stream_for_file (const char* file_name, int mode) ! 1524: { ! 1525: FILE* file = NULL; ! 1526: TypedStream* s; ! 1527: ! 1528: if (mode == OBJC_READONLY) ! 1529: file = fopen (file_name, "r"); ! 1530: else ! 1531: file = fopen (file_name, "w"); ! 1532: ! 1533: if (file) ! 1534: { ! 1535: s = objc_open_typed_stream (file, mode); ! 1536: if (s) ! 1537: s->type |= OBJC_MANAGED_STREAM; ! 1538: return s; ! 1539: } ! 1540: else ! 1541: return NULL; ! 1542: } ! 1543: ! 1544: /* ! 1545: ** Close STREAM freeing the structure it self. If it was opened with ! 1546: ** objc_open_typed_stream_for_file, the file will also be closed. ! 1547: */ ! 1548: ! 1549: void ! 1550: objc_close_typed_stream (TypedStream* stream) ! 1551: { ! 1552: if (stream->mode == OBJC_READONLY) ! 1553: { ! 1554: __objc_finish_read_root_object (stream); /* Just in case... */ ! 1555: hash_delete (stream->class_table); ! 1556: hash_delete (stream->object_refs); ! 1557: } ! 1558: ! 1559: hash_delete (stream->stream_table); ! 1560: hash_delete (stream->object_table); ! 1561: ! 1562: if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM)) ! 1563: fclose ((FILE*)stream->physical); ! 1564: ! 1565: free (stream); ! 1566: } ! 1567: ! 1568: BOOL ! 1569: objc_end_of_typed_stream (TypedStream* stream) ! 1570: { ! 1571: return (*stream->eof)(stream->physical); ! 1572: } ! 1573: ! 1574: void ! 1575: objc_flush_typed_stream (TypedStream* stream) ! 1576: { ! 1577: (*stream->flush)(stream->physical); ! 1578: } ! 1579: ! 1580: long ! 1581: objc_get_stream_class_version (TypedStream* stream, Class* class) ! 1582: { ! 1583: if (stream->class_table) ! 1584: return PTR2LONG(hash_value_for_key (stream->class_table, class->name)); ! 1585: else ! 1586: return class_get_version (class); ! 1587: } ! 1588:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.