1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993, 1995 Free Software Foundation, Inc.
3 Contributed by Kresten Krab Thorup
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 2, or (at your option) any later version.
11 GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 You should have received a copy of the GNU General Public License along with
17 GNU CC; see the file COPYING. If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* As a special exception, if you link this library with files compiled with
21 GCC to produce an executable, this does not cause the resulting executable
22 to be covered by the GNU General Public License. This exception does not
23 however invalidate any other reasons why the executable file might be
24 covered by the GNU General Public License. */
27 #include "typedstream.h"
30 extern int fflush(FILE*);
33 ({ typeof(V) __v=(V); typeof(A) __a=(A); \
34 __a*((__v+__a-1)/__a); })
36 #define PTR2LONG(P) (((char*)(P))-(char*)0)
37 #define LONG2PTR(L) (((char*)0)+(L))
39 #define __objc_fatal(format, args...) \
40 { fprintf(stderr, "archiving: "); \
41 fprintf(stderr, format, ## args); \
42 fprintf(stderr, "\n"); abort(); }
44 /* Declare some functions... */
47 objc_read_class (struct objc_typed_stream* stream, Class* class);
49 int objc_sizeof_type(const char* type);
52 objc_write_use_common (struct objc_typed_stream* stream, unsigned long key);
55 objc_write_register_common (struct objc_typed_stream* stream,
59 objc_write_class (struct objc_typed_stream* stream,
60 struct objc_class* class);
62 const char* objc_skip_type (const char* type);
64 static void __objc_finish_write_root_object(struct objc_typed_stream*);
65 static void __objc_finish_read_root_object(struct objc_typed_stream*);
68 __objc_code_unsigned_char (unsigned char* buf, unsigned char val)
70 if ((val&_B_VALUE) == val)
77 buf[0] = _B_NINT|0x01;
84 objc_write_unsigned_char (struct objc_typed_stream* stream,
87 unsigned char buf[sizeof (unsigned char)+1];
88 int len = __objc_code_unsigned_char (buf, value);
89 return (*stream->write)(stream->physical, buf, len);
93 __objc_code_char (unsigned char* buf, char val)
96 return __objc_code_unsigned_char (buf, val);
99 buf[0] = _B_NINT|_B_SIGN|0x01;
106 objc_write_char (struct objc_typed_stream* stream, char value)
108 unsigned char buf[sizeof (char)+1];
109 int len = __objc_code_char (buf, value);
110 return (*stream->write)(stream->physical, buf, len);
113 static __inline__ int
114 __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
116 if ((val&_B_VALUE) == val)
118 buf[0] = val|_B_SINT;
127 for (c= sizeof(short); c != 0; c -= 1)
128 if (((val>>(8*(c-1)))%0x100) != 0)
133 for (b = 1; c != 0; c--, b++)
135 buf[b] = (val >> (8*(c-1)))%0x100;
143 objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short value)
145 unsigned char buf[sizeof (unsigned short)+1];
146 int len = __objc_code_unsigned_short (buf, value);
147 return (*stream->write)(stream->physical, buf, len);
150 static __inline__ int
151 __objc_code_short (unsigned char* buf, short val)
153 int sign = (val < 0);
154 int size = __objc_code_unsigned_short (buf, sign ? -val : val);
161 objc_write_short (struct objc_typed_stream* stream, short value)
163 unsigned char buf[sizeof (short)+1];
164 int len = __objc_code_short (buf, value);
165 return (*stream->write)(stream->physical, buf, len);
169 static __inline__ int
170 __objc_code_unsigned_int (unsigned char* buf, unsigned int val)
172 if ((val&_B_VALUE) == val)
174 buf[0] = val|_B_SINT;
183 for (c= sizeof(int); c != 0; c -= 1)
184 if (((val>>(8*(c-1)))%0x100) != 0)
189 for (b = 1; c != 0; c--, b++)
191 buf[b] = (val >> (8*(c-1)))%0x100;
199 objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value)
201 unsigned char buf[sizeof(unsigned int)+1];
202 int len = __objc_code_unsigned_int (buf, value);
203 return (*stream->write)(stream->physical, buf, len);
206 static __inline__ int
207 __objc_code_int (unsigned char* buf, int val)
209 int sign = (val < 0);
210 int size = __objc_code_unsigned_int (buf, sign ? -val : val);
217 objc_write_int (struct objc_typed_stream* stream, int value)
219 unsigned char buf[sizeof(int)+1];
220 int len = __objc_code_int (buf, value);
221 return (*stream->write)(stream->physical, buf, len);
224 static __inline__ int
225 __objc_code_unsigned_long (unsigned char* buf, unsigned long val)
227 if ((val&_B_VALUE) == val)
229 buf[0] = val|_B_SINT;
238 for (c= sizeof(long); c != 0; c -= 1)
239 if (((val>>(8*(c-1)))%0x100) != 0)
244 for (b = 1; c != 0; c--, b++)
246 buf[b] = (val >> (8*(c-1)))%0x100;
254 objc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value)
256 unsigned char buf[sizeof(unsigned long)+1];
257 int len = __objc_code_unsigned_long (buf, value);
258 return (*stream->write)(stream->physical, buf, len);
261 static __inline__ int
262 __objc_code_long (unsigned char* buf, long val)
264 int sign = (val < 0);
265 int size = __objc_code_unsigned_long (buf, sign ? -val : val);
272 objc_write_long (struct objc_typed_stream* stream, long value)
274 unsigned char buf[sizeof(long)+1];
275 int len = __objc_code_long (buf, value);
276 return (*stream->write)(stream->physical, buf, len);
281 objc_write_string (struct objc_typed_stream* stream,
282 const unsigned char* string, unsigned int nbytes)
284 unsigned char buf[sizeof(unsigned int)+1];
285 int len = __objc_code_unsigned_int (buf, nbytes);
287 if ((buf[0]&_B_CODE) == _B_SINT)
288 buf[0] = (buf[0]&_B_VALUE)|_B_SSTR;
291 buf[0] = (buf[0]&_B_VALUE)|_B_NSTR;
293 if ((*stream->write)(stream->physical, buf, len) != 0)
294 return (*stream->write)(stream->physical, string, nbytes);
300 objc_write_string_atomic (struct objc_typed_stream* stream,
301 unsigned char* string, unsigned int nbytes)
304 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string))))
305 return objc_write_use_common (stream, key);
309 hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string);
310 if ((length = objc_write_register_common (stream, key)))
311 return objc_write_string (stream, string, nbytes);
317 objc_write_register_common (struct objc_typed_stream* stream, unsigned long key)
319 unsigned char buf[sizeof (unsigned long)+2];
320 int len = __objc_code_unsigned_long (buf+1, key);
323 buf[0] = _B_RCOMM|0x01;
325 return (*stream->write)(stream->physical, buf, len+1);
329 buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM;
330 return (*stream->write)(stream->physical, buf+1, len);
335 objc_write_use_common (struct objc_typed_stream* stream, unsigned long key)
337 unsigned char buf[sizeof (unsigned long)+2];
338 int len = __objc_code_unsigned_long (buf+1, key);
341 buf[0] = _B_UCOMM|0x01;
343 return (*stream->write)(stream->physical, buf, 2);
347 buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM;
348 return (*stream->write)(stream->physical, buf+1, len);
352 static __inline__ int
353 __objc_write_extension (struct objc_typed_stream* stream, unsigned char code)
355 if (code <= _B_VALUE)
357 unsigned char buf = code|_B_EXT;
358 return (*stream->write)(stream->physical, &buf, 1);
365 __objc_write_object (struct objc_typed_stream* stream, id object)
367 unsigned char buf = '\0';
368 SEL write_sel = sel_get_any_uid ("write:");
371 __objc_write_extension (stream, _BX_OBJECT);
372 objc_write_class (stream, object->class_pointer);
373 (*objc_msg_lookup(object, write_sel))(object, write_sel, stream);
374 return (*stream->write)(stream->physical, &buf, 1);
377 return objc_write_use_common(stream, 0);
381 objc_write_object_reference (struct objc_typed_stream* stream, id object)
384 if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
385 return objc_write_use_common (stream, key);
387 __objc_write_extension (stream, _BX_OBJREF);
388 return objc_write_unsigned_long (stream, PTR2LONG (object));
392 objc_write_root_object (struct objc_typed_stream* stream, id object)
395 if (stream->writing_root_p)
396 __objc_fatal ("objc_write_root_object called recursively")
399 stream->writing_root_p = 1;
400 __objc_write_extension (stream, _BX_OBJROOT);
401 if((len = objc_write_object (stream, object)))
402 __objc_finish_write_root_object(stream);
403 stream->writing_root_p = 0;
409 objc_write_object (struct objc_typed_stream* stream, id object)
412 if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
413 return objc_write_use_common (stream, key);
415 else if (object == nil)
416 return objc_write_use_common(stream, 0);
421 hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object);
422 if ((length = objc_write_register_common (stream, key)))
423 return __objc_write_object (stream, object);
429 extern int atoi (const char*);
430 extern size_t strlen(const char*);
431 extern size_t strcpy(char*, const char*);
435 __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class)
437 __objc_write_extension (stream, _BX_CLASS);
438 objc_write_string_atomic(stream, (char*)class->name,
439 strlen((char*)class->name));
440 return objc_write_unsigned_long (stream, CLS_GETNUMBER(class));
445 objc_write_class (struct objc_typed_stream* stream,
446 struct objc_class* class)
449 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class))))
450 return objc_write_use_common (stream, key);
454 hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class);
455 if ((length = objc_write_register_common (stream, key)))
456 return __objc_write_class (stream, class);
463 __objc_write_selector (struct objc_typed_stream* stream, SEL selector)
465 const char* sel_name = sel_get_name (selector);
466 __objc_write_extension (stream, _BX_SEL);
467 return objc_write_string (stream, sel_name, strlen ((char*)sel_name));
471 objc_write_selector (struct objc_typed_stream* stream, SEL selector)
473 const char* sel_name = sel_get_name (selector);
475 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name))))
476 return objc_write_use_common (stream, key);
480 hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
481 if ((length = objc_write_register_common (stream, key)))
482 return __objc_write_selector (stream, selector);
494 objc_read_char (struct objc_typed_stream* stream, char* val)
498 len = (*stream->read)(stream->physical, &buf, 1);
501 if ((buf & _B_CODE) == _B_SINT)
502 (*val) = (buf & _B_VALUE);
504 else if ((buf & _B_NUMBER) == 1)
506 len = (*stream->read)(stream->physical, val, 1);
512 __objc_fatal("expected 8bit signed int, got %dbit int",
513 (int)(buf&_B_NUMBER)*8);
520 objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val)
524 if ((len = (*stream->read)(stream->physical, &buf, 1)))
526 if ((buf & _B_CODE) == _B_SINT)
527 (*val) = (buf & _B_VALUE);
529 else if ((buf & _B_NUMBER) == 1)
530 len = (*stream->read)(stream->physical, val, 1);
533 __objc_fatal("expected 8bit unsigned int, got %dbit int",
534 (int)(buf&_B_NUMBER)*8);
540 objc_read_short (struct objc_typed_stream* stream, short* value)
542 unsigned char buf[sizeof(short)+1];
544 if ((len = (*stream->read)(stream->physical, buf, 1)))
546 if ((buf[0] & _B_CODE) == _B_SINT)
547 (*value) = (buf[0] & _B_VALUE);
552 int nbytes = buf[0] & _B_NUMBER;
553 if (nbytes > sizeof (short))
554 __objc_fatal("expected short, got bigger (%dbits)", nbytes*8);
555 len = (*stream->read)(stream->physical, buf+1, nbytes);
557 while (pos <= nbytes)
558 (*value) = ((*value)*0x100) + buf[pos++];
559 if (buf[0] & _B_SIGN)
560 (*value) = -(*value);
567 objc_read_unsigned_short (struct objc_typed_stream* stream,
568 unsigned short* value)
570 unsigned char buf[sizeof(unsigned short)+1];
572 if ((len = (*stream->read)(stream->physical, buf, 1)))
574 if ((buf[0] & _B_CODE) == _B_SINT)
575 (*value) = (buf[0] & _B_VALUE);
580 int nbytes = buf[0] & _B_NUMBER;
581 if (nbytes > sizeof (short))
582 __objc_fatal("expected short, got int or bigger");
583 len = (*stream->read)(stream->physical, buf+1, nbytes);
585 while (pos <= nbytes)
586 (*value) = ((*value)*0x100) + buf[pos++];
594 objc_read_int (struct objc_typed_stream* stream, int* value)
596 unsigned char buf[sizeof(int)+1];
598 if ((len = (*stream->read)(stream->physical, buf, 1)))
600 if ((buf[0] & _B_CODE) == _B_SINT)
601 (*value) = (buf[0] & _B_VALUE);
606 int nbytes = buf[0] & _B_NUMBER;
607 if (nbytes > sizeof (int))
608 __objc_fatal("expected int, got bigger");
609 len = (*stream->read)(stream->physical, buf+1, nbytes);
611 while (pos <= nbytes)
612 (*value) = ((*value)*0x100) + buf[pos++];
613 if (buf[0] & _B_SIGN)
614 (*value) = -(*value);
621 objc_read_long (struct objc_typed_stream* stream, long* value)
623 unsigned char buf[sizeof(long)+1];
625 if ((len = (*stream->read)(stream->physical, buf, 1)))
627 if ((buf[0] & _B_CODE) == _B_SINT)
628 (*value) = (buf[0] & _B_VALUE);
633 int nbytes = buf[0] & _B_NUMBER;
634 if (nbytes > sizeof (long))
635 __objc_fatal("expected long, got bigger");
636 len = (*stream->read)(stream->physical, buf+1, nbytes);
638 while (pos <= nbytes)
639 (*value) = ((*value)*0x100) + buf[pos++];
640 if (buf[0] & _B_SIGN)
641 (*value) = -(*value);
648 __objc_read_nbyte_uint (struct objc_typed_stream* stream,
649 unsigned int nbytes, unsigned int* val)
652 unsigned char buf[sizeof(unsigned int)+1];
654 if (nbytes > sizeof (int))
655 __objc_fatal("expected int, got bigger");
657 len = (*stream->read)(stream->physical, buf, nbytes);
660 (*val) = ((*val)*0x100) + buf[pos++];
666 objc_read_unsigned_int (struct objc_typed_stream* stream,
669 unsigned char buf[sizeof(unsigned int)+1];
671 if ((len = (*stream->read)(stream->physical, buf, 1)))
673 if ((buf[0] & _B_CODE) == _B_SINT)
674 (*value) = (buf[0] & _B_VALUE);
677 len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value);
684 __objc_read_nbyte_ulong (struct objc_typed_stream* stream,
685 unsigned int nbytes, unsigned long* val)
688 unsigned char buf[sizeof(unsigned long)+1];
690 if (nbytes > sizeof (long))
691 __objc_fatal("expected long, got bigger");
693 len = (*stream->read)(stream->physical, buf, nbytes);
696 (*val) = ((*val)*0x100) + buf[pos++];
702 objc_read_unsigned_long (struct objc_typed_stream* stream,
703 unsigned long* value)
705 unsigned char buf[sizeof(unsigned long)+1];
707 if ((len = (*stream->read)(stream->physical, buf, 1)))
709 if ((buf[0] & _B_CODE) == _B_SINT)
710 (*value) = (buf[0] & _B_VALUE);
713 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value);
720 objc_read_string (struct objc_typed_stream* stream,
723 unsigned char buf[sizeof(unsigned int)+1];
725 if ((len = (*stream->read)(stream->physical, buf, 1)))
727 unsigned long key = 0;
729 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
731 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
732 len = (*stream->read)(stream->physical, buf, 1);
735 switch (buf[0]&_B_CODE) {
738 int length = buf[0]&_B_VALUE;
739 (*string) = (char*)__objc_xmalloc(length+1);
741 hash_add (&stream->stream_table, LONG2PTR(key), *string);
742 len = (*stream->read)(stream->physical, *string, length);
743 (*string)[length] = '\0';
750 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
751 tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key));
752 *string = __objc_xmalloc (strlen(tmp) + 1);
753 strcpy (*string, tmp);
759 unsigned int nbytes = buf[0]&_B_VALUE;
760 len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
762 (*string) = (char*)__objc_xmalloc(nbytes+1);
764 hash_add (&stream->stream_table, LONG2PTR(key), *string);
765 len = (*stream->read)(stream->physical, *string, nbytes);
766 (*string)[nbytes] = '\0';
772 __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE));
781 objc_read_object (struct objc_typed_stream* stream, id* object)
783 unsigned char buf[sizeof (unsigned int)];
785 if ((len = (*stream->read)(stream->physical, buf, 1)))
787 SEL read_sel = sel_get_any_uid ("read:");
788 unsigned long key = 0;
790 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
792 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
793 len = (*stream->read)(stream->physical, buf, 1);
796 if (buf[0] == (_B_EXT | _BX_OBJECT))
801 len = objc_read_class (stream, &class);
803 /* create instance */
804 (*object) = class_create_instance(class);
808 hash_add (&stream->object_table, LONG2PTR(key), *object);
811 if (__objc_responds_to (*object, read_sel))
812 (*get_imp(class, read_sel))(*object, read_sel, stream);
814 /* check null-byte */
815 len = (*stream->read)(stream->physical, buf, 1);
817 __objc_fatal("expected null-byte, got opcode %c", buf[0]);
820 else if ((buf[0]&_B_CODE) == _B_UCOMM)
823 __objc_fatal("cannot register use upcode...");
824 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
825 (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
828 else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
830 struct objc_list* other;
831 len = objc_read_unsigned_long (stream, &key);
832 other = (struct objc_list*)hash_value_for_key (stream->object_refs, LONG2PTR(key));
833 hash_add (&stream->object_refs, LONG2PTR(key), (void*)list_cons(object, other));
836 else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
839 __objc_fatal("cannot register root object...");
840 len = objc_read_object (stream, object);
841 __objc_finish_read_root_object (stream);
845 __objc_fatal("expected object, got opcode %c", buf[0]);
851 objc_read_class (struct objc_typed_stream* stream, Class* class)
853 unsigned char buf[sizeof (unsigned int)];
855 if ((len = (*stream->read)(stream->physical, buf, 1)))
857 unsigned long key = 0;
859 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
861 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
862 len = (*stream->read)(stream->physical, buf, 1);
865 if (buf[0] == (_B_EXT | _BX_CLASS))
868 unsigned long version;
871 len = objc_read_string (stream, &class_name);
872 (*class) = objc_get_class(class_name);
877 hash_add (&stream->stream_table, LONG2PTR(key), *class);
879 objc_read_unsigned_long(stream, &version);
880 hash_add (&stream->class_table, (*class)->name, (void*)version);
883 else if ((buf[0]&_B_CODE) == _B_UCOMM)
886 __objc_fatal("cannot register use upcode...");
887 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
888 (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
890 __objc_fatal("cannot find class for key %lu", key);
894 __objc_fatal("expected class, got opcode %c", buf[0]);
900 objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
902 unsigned char buf[sizeof (unsigned int)];
904 if ((len = (*stream->read)(stream->physical, buf, 1)))
906 unsigned long key = 0;
908 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
910 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
911 len = (*stream->read)(stream->physical, buf, 1);
914 if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
919 len = objc_read_string (stream, &selector_name);
920 (*selector) = sel_get_any_uid(selector_name);
921 free (selector_name);
925 hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
928 else if ((buf[0]&_B_CODE) == _B_UCOMM)
931 __objc_fatal("cannot register use upcode...");
932 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
933 (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
937 __objc_fatal("expected selector, got opcode %c", buf[0]);
943 ** USER LEVEL FUNCTIONS
947 ** Write one object, encoded in TYPE and pointed to by DATA to the
948 ** typed stream STREAM.
952 objc_write_type(TypedStream* stream, const char* type, const void* data)
956 return objc_write_object (stream, *(id*)data);
960 return objc_write_class (stream, *(Class*)data);
964 return objc_write_selector (stream, *(SEL*)data);
968 return objc_write_char(stream, *(char*)data);
972 return objc_write_unsigned_char(stream, *(unsigned char*)data);
976 return objc_write_short(stream, *(short*)data);
980 return objc_write_unsigned_short(stream, *(unsigned short*)data);
984 return objc_write_int(stream, *(int*)data);
988 return objc_write_unsigned_int(stream, *(unsigned int*)data);
992 return objc_write_long(stream, *(long*)data);
996 return objc_write_unsigned_long(stream, *(unsigned long*)data);
1000 return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
1004 return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data));
1009 int len = atoi(type+1);
1010 while (isdigit(*++type));
1011 return objc_write_array (stream, type, len, data);
1019 while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
1020 while (*type != _C_STRUCT_E);
1022 align = objc_alignof_type (type); /* padd to alignment */
1023 acc_size += ROUND (acc_size, align);
1024 objc_write_type (stream, type, ((char*)data)+acc_size);
1025 acc_size += objc_sizeof_type (type); /* add component size */
1026 type = objc_skip_typespec (type); /* skip component */
1032 fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
1038 ** Read one object, encoded in TYPE and pointed to by DATA to the
1039 ** typed stream STREAM. DATA specifies the address of the types to
1040 ** read. Expected type is checked against the type actually present
1045 objc_read_type(TypedStream* stream, const char* type, void* data)
1050 return objc_read_object (stream, (id*)data);
1054 return objc_read_class (stream, (Class*)data);
1058 return objc_read_selector (stream, (SEL*)data);
1062 return objc_read_char (stream, (char*)data);
1066 return objc_read_unsigned_char (stream, (unsigned char*)data);
1070 return objc_read_short (stream, (short*)data);
1074 return objc_read_unsigned_short (stream, (unsigned short*)data);
1078 return objc_read_int (stream, (int*)data);
1082 return objc_read_unsigned_int (stream, (unsigned int*)data);
1086 return objc_read_long (stream, (long*)data);
1090 return objc_read_unsigned_long (stream, (unsigned long*)data);
1095 return objc_read_string (stream, (char**)data);
1100 int len = atoi(type+1);
1101 while (isdigit(*++type));
1102 return objc_read_array (stream, type, len, data);
1110 while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
1111 while (*type != _C_STRUCT_E);
1113 align = objc_alignof_type (type); /* padd to alignment */
1114 acc_size += ROUND (acc_size, align);
1115 objc_read_type (stream, type, ((char*)data)+acc_size);
1116 acc_size += objc_sizeof_type (type); /* add component size */
1117 type = objc_skip_typespec (type); /* skip component */
1123 fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
1129 ** Write the object specified by the template TYPE to STREAM. Last
1130 ** arguments specify addresses of values to be written. It might
1131 ** seem surprising to specify values by address, but this is extremely
1132 ** convenient for copy-paste with objc_read_types calls. A more
1133 ** down-to-the-earth cause for this passing of addresses is that values
1134 ** of arbitrary size is not well supported in ANSI C for functions with
1135 ** variable number of arguments.
1139 objc_write_types (TypedStream* stream, const char* type, ...)
1145 va_start(args, type);
1147 for (c = type; *c; c = objc_skip_typespec (c))
1151 res = objc_write_object (stream, *va_arg (args, id*));
1155 res = objc_write_class (stream, *va_arg(args, Class*));
1159 res = objc_write_selector (stream, *va_arg(args, SEL*));
1163 res = objc_write_char (stream, *va_arg (args, char*));
1167 res = objc_write_unsigned_char (stream,
1168 *va_arg (args, unsigned char*));
1172 res = objc_write_short (stream, *va_arg(args, short*));
1176 res = objc_write_unsigned_short (stream,
1177 *va_arg(args, unsigned short*));
1181 res = objc_write_int(stream, *va_arg(args, int*));
1185 res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
1189 res = objc_write_long(stream, *va_arg(args, long*));
1193 res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*));
1198 char** str = va_arg(args, char**);
1199 res = objc_write_string (stream, *str, strlen(*str));
1205 char** str = va_arg(args, char**);
1206 res = objc_write_string_atomic (stream, *str, strlen(*str));
1212 int len = atoi(c+1);
1214 while (isdigit(*++t));
1215 res = objc_write_array (stream, t, len, va_arg(args, void*));
1216 t = objc_skip_typespec (t);
1218 __objc_fatal("expected `]', got: %s", t);
1223 fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type);
1233 ** Last arguments specify addresses of values to be read. Expected
1234 ** type is checked against the type actually present on the stream.
1238 objc_read_types(TypedStream* stream, const char* type, ...)
1244 va_start(args, type);
1246 for (c = type; *c; c = objc_skip_typespec(c))
1250 res = objc_read_object(stream, va_arg(args, id*));
1254 res = objc_read_class(stream, va_arg(args, Class*));
1258 res = objc_read_selector(stream, va_arg(args, SEL*));
1262 res = objc_read_char(stream, va_arg(args, char*));
1266 res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
1270 res = objc_read_short(stream, va_arg(args, short*));
1274 res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
1278 res = objc_read_int(stream, va_arg(args, int*));
1282 res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
1286 res = objc_read_long(stream, va_arg(args, long*));
1290 res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*));
1296 char** str = va_arg(args, char**);
1297 res = objc_read_string (stream, str);
1303 int len = atoi(c+1);
1305 while (isdigit(*++t));
1306 res = objc_read_array (stream, t, len, va_arg(args, void*));
1307 t = objc_skip_typespec (t);
1309 __objc_fatal("expected `]', got: %s", t);
1314 fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
1323 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1324 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1328 objc_write_array (TypedStream* stream, const char* type,
1329 int count, const void* data)
1331 int off = objc_sizeof_type(type);
1332 const char* where = data;
1336 objc_write_type(stream, type, where);
1343 ** Read an array of COUNT elements of TYPE into the memory address
1344 ** DATA. The memory pointed to by data is supposed to be allocated
1345 ** by the callee. This is equivalent of
1346 ** objc_read_type (stream, "[N<type>]", data)
1350 objc_read_array (TypedStream* stream, const char* type,
1351 int count, void* data)
1353 int off = objc_sizeof_type(type);
1354 char* where = (char*)data;
1358 objc_read_type(stream, type, where);
1365 __objc_free (void* p)
1371 __objc_fread(FILE* file, char* data, int len)
1373 return fread(data, len, 1, file);
1377 __objc_fwrite(FILE* file, char* data, int len)
1379 return fwrite(data, len, 1, file);
1383 __objc_feof(FILE* file)
1389 __objc_no_write(FILE* file, char* data, int len)
1391 __objc_fatal ("TypedStream not open for writing");
1395 __objc_no_read(FILE* file, char* data, int len)
1397 __objc_fatal ("TypedStream not open for reading");
1401 __objc_read_typed_stream_signature (TypedStream* stream)
1406 (*stream->read)(stream->physical, buffer+pos, 1);
1407 while (buffer[pos++] != '\0');
1408 sscanf (buffer, "GNU TypedStream %d", &stream->version);
1409 if (stream->version != OBJC_TYPED_STREAM_VERSION)
1410 __objc_fatal ("cannot handle TypedStream version %d", stream->version);
1415 __objc_write_typed_stream_signature (TypedStream* stream)
1418 sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
1419 stream->version = OBJC_TYPED_STREAM_VERSION;
1420 (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
1424 static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
1426 hash_delete (stream->object_table);
1427 stream->object_table = hash_new(64,
1428 (hash_func_type)hash_ptr,
1429 (compare_func_type)compare_ptrs);
1432 static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
1435 struct objc_list* free_list;
1436 SEL awake_sel = sel_get_any_uid ("awake");
1438 /* resolve object forward references */
1439 free_list = list_cons(NULL, NULL);
1440 for (node = hash_next (stream->object_refs, NULL); node;
1441 node = hash_next (stream->object_refs, node))
1443 struct objc_list* reflist = node->value;
1444 const void* key = node->key;
1445 id object = hash_value_for_key (stream->object_table, key);
1448 *((id*)reflist->head) = object;
1449 if (list_find(&free_list, reflist) == NULL)
1450 free_list = list_cons (reflist, free_list);
1451 reflist = reflist->tail;
1454 list_mapcar (free_list, __objc_free);
1455 list_free (free_list);
1457 /* empty object reference table */
1458 hash_delete (stream->object_refs);
1459 stream->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1460 (compare_func_type)compare_ptrs);
1462 /* call -awake for all objects read */
1465 for (node = hash_next (stream->object_table, NULL); node;
1466 node = hash_next (stream->object_table, node))
1468 id object = node->value;
1469 if (__objc_responds_to (object, awake_sel))
1470 (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
1474 /* empty object table */
1475 hash_delete (stream->object_table);
1476 stream->object_table = hash_new(64,
1477 (hash_func_type)hash_ptr,
1478 (compare_func_type)compare_ptrs);
1482 ** Open the stream PHYSICAL in MODE
1486 objc_open_typed_stream (FILE* physical, int mode)
1488 TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
1491 s->physical = physical;
1492 s->stream_table = hash_new(64,
1493 (hash_func_type)hash_ptr,
1494 (compare_func_type)compare_ptrs);
1495 s->object_table = hash_new(64,
1496 (hash_func_type)hash_ptr,
1497 (compare_func_type)compare_ptrs);
1498 s->eof = (objc_typed_eof_func)__objc_feof;
1499 s->flush = (objc_typed_flush_func)fflush;
1500 s->writing_root_p = 0;
1501 if (mode == OBJC_READONLY)
1503 s->class_table = hash_new(8, (hash_func_type)hash_string,
1504 (compare_func_type)compare_strings);
1505 s->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1506 (compare_func_type)compare_ptrs);
1507 s->read = (objc_typed_read_func)__objc_fread;
1508 s->write = (objc_typed_write_func)__objc_no_write;
1509 __objc_read_typed_stream_signature (s);
1511 else if (mode == OBJC_WRITEONLY)
1515 s->read = (objc_typed_read_func)__objc_no_read;
1516 s->write = (objc_typed_write_func)__objc_fwrite;
1517 __objc_write_typed_stream_signature (s);
1521 objc_close_typed_stream (s);
1524 s->type = OBJC_FILE_STREAM;
1529 ** Open the file named by FILE_NAME in MODE
1533 objc_open_typed_stream_for_file (const char* file_name, int mode)
1538 if (mode == OBJC_READONLY)
1539 file = fopen (file_name, "r");
1541 file = fopen (file_name, "w");
1545 s = objc_open_typed_stream (file, mode);
1547 s->type |= OBJC_MANAGED_STREAM;
1555 ** Close STREAM freeing the structure it self. If it was opened with
1556 ** objc_open_typed_stream_for_file, the file will also be closed.
1560 objc_close_typed_stream (TypedStream* stream)
1562 if (stream->mode == OBJC_READONLY)
1564 __objc_finish_read_root_object (stream); /* Just in case... */
1565 hash_delete (stream->class_table);
1566 hash_delete (stream->object_refs);
1569 hash_delete (stream->stream_table);
1570 hash_delete (stream->object_table);
1572 if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1573 fclose ((FILE*)stream->physical);
1579 objc_end_of_typed_stream (TypedStream* stream)
1581 return (*stream->eof)(stream->physical);
1585 objc_flush_typed_stream (TypedStream* stream)
1587 (*stream->flush)(stream->physical);
1591 objc_get_stream_class_version (TypedStream* stream, Class class)
1593 if (stream->class_table)
1594 return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
1596 return class_get_version (class);