|
|
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: #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
48: objc_read_class (struct objc_typed_stream* stream, Class** class);
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.3 ! root 441: return objc_write_unsigned_long (stream, CLS_GETNUMBER(class));
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: {
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);
1.1.1.3 ! root 475: unsigned long key;
! 476: if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name))))
1.1 root 477: return objc_write_use_common (stream, key);
478: else
479: {
480: int length;
1.1.1.3 ! root 481: hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
1.1 root 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
1.1.1.3 ! root 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
1.1 root 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:
1.1.1.3 ! root 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:
1.1 root 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: {
1.1.1.3 ! root 728: unsigned long key = 0;
1.1 root 729:
730: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
731: {
1.1.1.3 ! root 732: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1 root 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)
1.1.1.3 ! root 742: hash_add (&stream->stream_table, LONG2PTR(key), *string);
1.1 root 743: len = (*stream->read)(stream->physical, *string, length);
744: (*string)[length] = '\0';
745: }
746: break;
747:
748: case _B_UCOMM:
749: {
1.1.1.2 root 750: char *tmp;
1.1.1.3 ! root 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);
1.1.1.2 root 754: strcpy (*string, tmp);
1.1 root 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) {
1.1.1.2 root 763: (*string) = (char*)__objc_xmalloc(nbytes+1);
1.1 root 764: if (key)
1.1.1.3 ! root 765: hash_add (&stream->stream_table, LONG2PTR(key), *string);
1.1.1.2 root 766: len = (*stream->read)(stream->physical, *string, nbytes);
1.1 root 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: {
1.1.1.3 ! root 788: SEL read_sel = sel_get_any_uid ("read:");
! 789: unsigned long key = 0;
1.1 root 790:
791: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
792: {
1.1.1.3 ! root 793: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1 root 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)
1.1.1.3 ! root 809: hash_add (&stream->object_table, LONG2PTR(key), *object);
1.1 root 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...");
1.1.1.3 ! root 825: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
! 826: (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
1.1 root 827: }
828:
829: else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
830: {
831: struct objc_list* other;
1.1.1.3 ! root 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));
1.1 root 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: {
1.1.1.3 ! root 858: unsigned long key = 0;
1.1 root 859:
860: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
861: {
1.1.1.3 ! root 862: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1 root 863: len = (*stream->read)(stream->physical, buf, 1);
864: }
865:
866: if (buf[0] == (_B_EXT | _BX_CLASS))
867: {
868: char* class_name;
1.1.1.3 ! root 869: unsigned long version;
1.1 root 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)
1.1.1.3 ! root 878: hash_add (&stream->stream_table, LONG2PTR(key), *class);
1.1 root 879:
1.1.1.3 ! root 880: objc_read_unsigned_long(stream, &version);
1.1 root 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...");
1.1.1.3 ! root 888: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
! 889: (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
1.1 root 890: if (!*class)
1.1.1.3 ! root 891: __objc_fatal("cannot find class for key %lu", key);
1.1 root 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: {
1.1.1.3 ! root 907: unsigned long key = 0;
1.1 root 908:
909: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
910: {
1.1.1.3 ! root 911: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1 root 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);
1.1.1.3 ! root 921: (*selector) = sel_get_any_uid(selector_name);
1.1 root 922: free (selector_name);
923:
924: /* register */
925: if (key)
1.1.1.3 ! root 926: hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
1.1 root 927: }
928:
929: else if ((buf[0]&_B_CODE) == _B_UCOMM)
930: {
931: if (key)
932: __objc_fatal("cannot register use upcode...");
1.1.1.3 ! root 933: len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
! 934: (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
1.1 root 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:
1.1.1.3 ! root 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:
1.1 root 1000: case _C_CHARPTR:
1.1.1.2 root 1001: return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
1.1 root 1002: break;
1003:
1004: case _C_ATOM:
1.1.1.2 root 1005: return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data));
1.1 root 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:
1.1.1.3 ! root 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:
1.1 root 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:
1.1.1.3 ! root 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:
1.1 root 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:
1.1.1.3 ! root 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:
1.1 root 1123: default:
1.1.1.2 root 1124: fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
1.1 root 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:
1.1.1.3 ! root 1148: for (c = type; *c; c = objc_skip_typespec (c))
1.1 root 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:
1.1.1.3 ! root 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:
1.1 root 1197: case _C_CHARPTR:
1198: {
1.1.1.2 root 1199: char** str = va_arg(args, char**);
1200: res = objc_write_string (stream, *str, strlen(*str));
1.1 root 1201: }
1202: break;
1203:
1204: case _C_ATOM:
1205: {
1.1.1.2 root 1206: char** str = va_arg(args, char**);
1207: res = objc_write_string_atomic (stream, *str, strlen(*str));
1.1 root 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*));
1.1.1.3 ! root 1217: t = objc_skip_typespec (t);
1.1 root 1218: if (*t != _C_ARY_E)
1219: __objc_fatal("expected `]', got: %s", t);
1220: }
1221: break;
1222:
1223: default:
1.1.1.2 root 1224: fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type);
1.1 root 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:
1.1.1.3 ! root 1247: for (c = type; *c; c = objc_skip_typespec(c))
1.1 root 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:
1.1.1.3 ! root 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:
1.1 root 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*));
1.1.1.3 ! root 1308: t = objc_skip_typespec (t);
1.1 root 1309: if (*t != _C_ARY_E)
1310: __objc_fatal("expected `]', got: %s", t);
1311: }
1312: break;
1313:
1314: default:
1.1.1.2 root 1315: fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
1.1 root 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:
1.1.1.3 ! root 1365: static void
! 1366: __objc_free (void* p)
! 1367: {
! 1368: free (p);
! 1369: }
! 1370:
1.1 root 1371: static int
1372: __objc_fread(FILE* file, char* data, int len)
1373: {
1374: return fread(data, len, 1, file);
1375: }
1376:
1377: static int
1378: __objc_fwrite(FILE* file, char* data, int len)
1379: {
1380: return fwrite(data, len, 1, file);
1381: }
1382:
1383: static int
1384: __objc_feof(FILE* file)
1385: {
1386: return feof(file);
1387: }
1388:
1389: static int
1390: __objc_no_write(FILE* file, char* data, int len)
1391: {
1392: __objc_fatal ("TypedStream not open for writing");
1393: }
1394:
1395: static int
1396: __objc_no_read(FILE* file, char* data, int len)
1397: {
1398: __objc_fatal ("TypedStream not open for reading");
1399: }
1400:
1401: static int
1402: __objc_read_typed_stream_signature (TypedStream* stream)
1403: {
1404: char buffer[80];
1405: int pos = 0;
1406: do
1407: (*stream->read)(stream->physical, buffer+pos, 1);
1408: while (buffer[pos++] != '\0');
1409: sscanf (buffer, "GNU TypedStream %d", &stream->version);
1410: if (stream->version != OBJC_TYPED_STREAM_VERSION)
1411: __objc_fatal ("cannot handle TypedStream version %d", stream->version);
1412: return 1;
1413: }
1414:
1415: static int
1416: __objc_write_typed_stream_signature (TypedStream* stream)
1417: {
1418: char buffer[80];
1419: sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
1420: stream->version = OBJC_TYPED_STREAM_VERSION;
1421: (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
1422: return 1;
1423: }
1424:
1425: static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
1426: {
1427: hash_delete (stream->object_table);
1428: stream->object_table = hash_new(64,
1429: (hash_func_type)hash_ptr,
1430: (compare_func_type)compare_ptrs);
1431: }
1432:
1433: static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
1434: {
1435: node_ptr node;
1.1.1.3 ! root 1436: struct objc_list* free_list;
! 1437: SEL awake_sel = sel_get_any_uid ("awake");
1.1 root 1438:
1439: /* resolve object forward references */
1.1.1.3 ! root 1440: free_list = list_cons(NULL, NULL);
1.1 root 1441: for (node = hash_next (stream->object_refs, NULL); node;
1442: node = hash_next (stream->object_refs, node))
1443: {
1444: struct objc_list* reflist = node->value;
1445: const void* key = node->key;
1446: id object = hash_value_for_key (stream->object_table, key);
1447: while(reflist)
1448: {
1449: *((id*)reflist->head) = object;
1.1.1.3 ! root 1450: if (list_find(&free_list, reflist) == NULL)
! 1451: free_list = list_cons (reflist, free_list);
1.1 root 1452: reflist = reflist->tail;
1453: }
1454: }
1.1.1.3 ! root 1455: list_mapcar (free_list, __objc_free);
! 1456: list_free (free_list);
1.1 root 1457:
1458: /* empty object reference table */
1459: hash_delete (stream->object_refs);
1460: stream->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1461: (compare_func_type)compare_ptrs);
1462:
1463: /* call -awake for all objects read */
1464: if (awake_sel)
1465: {
1466: for (node = hash_next (stream->object_table, NULL); node;
1467: node = hash_next (stream->object_table, node))
1468: {
1469: id object = node->value;
1470: if (__objc_responds_to (object, awake_sel))
1471: (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
1472: }
1473: }
1474:
1475: /* empty object table */
1476: hash_delete (stream->object_table);
1477: stream->object_table = hash_new(64,
1478: (hash_func_type)hash_ptr,
1479: (compare_func_type)compare_ptrs);
1480: }
1481:
1482: /*
1483: ** Open the stream PHYSICAL in MODE
1484: */
1485:
1486: TypedStream*
1487: objc_open_typed_stream (FILE* physical, int mode)
1488: {
1489: TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
1490:
1491: s->mode = mode;
1492: s->physical = physical;
1493: s->stream_table = hash_new(64,
1494: (hash_func_type)hash_ptr,
1495: (compare_func_type)compare_ptrs);
1496: s->object_table = hash_new(64,
1497: (hash_func_type)hash_ptr,
1498: (compare_func_type)compare_ptrs);
1499: s->eof = (objc_typed_eof_func)__objc_feof;
1500: s->flush = (objc_typed_flush_func)fflush;
1501: s->writing_root_p = 0;
1502: if (mode == OBJC_READONLY)
1503: {
1504: s->class_table = hash_new(8, (hash_func_type)hash_string,
1505: (compare_func_type)compare_strings);
1506: s->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1507: (compare_func_type)compare_ptrs);
1508: s->read = (objc_typed_read_func)__objc_fread;
1509: s->write = (objc_typed_write_func)__objc_no_write;
1510: __objc_read_typed_stream_signature (s);
1511: }
1512: else if (mode == OBJC_WRITEONLY)
1513: {
1514: s->class_table = 0;
1515: s->object_refs = 0;
1516: s->read = (objc_typed_read_func)__objc_no_read;
1517: s->write = (objc_typed_write_func)__objc_fwrite;
1518: __objc_write_typed_stream_signature (s);
1519: }
1520: else
1521: {
1522: objc_close_typed_stream (s);
1523: return NULL;
1524: }
1525: s->type = OBJC_FILE_STREAM;
1526: return s;
1527: }
1528:
1529: /*
1530: ** Open the file named by FILE_NAME in MODE
1531: */
1532:
1533: TypedStream*
1534: objc_open_typed_stream_for_file (const char* file_name, int mode)
1535: {
1536: FILE* file = NULL;
1537: TypedStream* s;
1538:
1539: if (mode == OBJC_READONLY)
1540: file = fopen (file_name, "r");
1541: else
1542: file = fopen (file_name, "w");
1543:
1544: if (file)
1545: {
1546: s = objc_open_typed_stream (file, mode);
1547: if (s)
1548: s->type |= OBJC_MANAGED_STREAM;
1549: return s;
1550: }
1551: else
1552: return NULL;
1553: }
1554:
1555: /*
1556: ** Close STREAM freeing the structure it self. If it was opened with
1557: ** objc_open_typed_stream_for_file, the file will also be closed.
1558: */
1559:
1560: void
1561: objc_close_typed_stream (TypedStream* stream)
1562: {
1563: if (stream->mode == OBJC_READONLY)
1564: {
1565: __objc_finish_read_root_object (stream); /* Just in case... */
1566: hash_delete (stream->class_table);
1567: hash_delete (stream->object_refs);
1568: }
1569:
1570: hash_delete (stream->stream_table);
1571: hash_delete (stream->object_table);
1572:
1573: if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1574: fclose ((FILE*)stream->physical);
1575:
1576: free (stream);
1577: }
1578:
1579: BOOL
1580: objc_end_of_typed_stream (TypedStream* stream)
1581: {
1582: return (*stream->eof)(stream->physical);
1583: }
1584:
1585: void
1586: objc_flush_typed_stream (TypedStream* stream)
1587: {
1588: (*stream->flush)(stream->physical);
1589: }
1590:
1.1.1.3 ! root 1591: long
1.1 root 1592: objc_get_stream_class_version (TypedStream* stream, Class* class)
1593: {
1594: if (stream->class_table)
1.1.1.3 ! root 1595: return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
1.1 root 1596: else
1597: return class_get_version (class);
1598: }
1599:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.