1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993, 1995, 1996 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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
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. */
28 #include "typedstream.h"
31 extern int fflush(FILE*);
34 ({ typeof(V) __v=(V); typeof(A) __a=(A); \
35 __a*((__v+__a-1)/__a); })
37 #define PTR2LONG(P) (((char*)(P))-(char*)0)
38 #define LONG2PTR(L) (((char*)0)+(L))
40 #define __objc_fatal(format, args...) \
41 { fprintf(stderr, "archiving: "); \
42 fprintf(stderr, format, ## args); \
43 fprintf(stderr, "\n"); abort(); }
45 /* Declare some functions... */
48 objc_read_class (struct objc_typed_stream
* stream
, Class
* class);
50 int objc_sizeof_type(const char* type
);
53 objc_write_use_common (struct objc_typed_stream
* stream
, unsigned long key
);
56 objc_write_register_common (struct objc_typed_stream
* stream
,
60 objc_write_class (struct objc_typed_stream
* stream
,
61 struct objc_class
* class);
63 const char* objc_skip_type (const char* type
);
65 static void __objc_finish_write_root_object(struct objc_typed_stream
*);
66 static void __objc_finish_read_root_object(struct objc_typed_stream
*);
69 __objc_code_unsigned_char (unsigned char* buf
, unsigned char val
)
71 if ((val
&_B_VALUE
) == val
)
78 buf
[0] = _B_NINT
|0x01;
85 objc_write_unsigned_char (struct objc_typed_stream
* stream
,
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
);
94 __objc_code_char (unsigned char* buf
, char val
)
97 return __objc_code_unsigned_char (buf
, val
);
100 buf
[0] = _B_NINT
|_B_SIGN
|0x01;
107 objc_write_char (struct objc_typed_stream
* stream
, char value
)
109 unsigned char buf
[sizeof (char)+1];
110 int len
= __objc_code_char (buf
, value
);
111 return (*stream
->write
)(stream
->physical
, buf
, len
);
114 static __inline__
int
115 __objc_code_unsigned_short (unsigned char* buf
, unsigned short val
)
117 if ((val
&_B_VALUE
) == val
)
119 buf
[0] = val
|_B_SINT
;
128 for (c
= sizeof(short); c
!= 0; c
-= 1)
129 if (((val
>>(8*(c
-1)))%0x100) != 0)
134 for (b
= 1; c
!= 0; c
--, b
++)
136 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
144 objc_write_unsigned_short (struct objc_typed_stream
* stream
, unsigned short value
)
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
);
151 static __inline__
int
152 __objc_code_short (unsigned char* buf
, short val
)
154 int sign
= (val
< 0);
155 int size
= __objc_code_unsigned_short (buf
, sign
? -val
: val
);
162 objc_write_short (struct objc_typed_stream
* stream
, short value
)
164 unsigned char buf
[sizeof (short)+1];
165 int len
= __objc_code_short (buf
, value
);
166 return (*stream
->write
)(stream
->physical
, buf
, len
);
170 static __inline__
int
171 __objc_code_unsigned_int (unsigned char* buf
, unsigned int val
)
173 if ((val
&_B_VALUE
) == val
)
175 buf
[0] = val
|_B_SINT
;
184 for (c
= sizeof(int); c
!= 0; c
-= 1)
185 if (((val
>>(8*(c
-1)))%0x100) != 0)
190 for (b
= 1; c
!= 0; c
--, b
++)
192 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
200 objc_write_unsigned_int (struct objc_typed_stream
* stream
, unsigned int value
)
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
);
207 static __inline__
int
208 __objc_code_int (unsigned char* buf
, int val
)
210 int sign
= (val
< 0);
211 int size
= __objc_code_unsigned_int (buf
, sign
? -val
: val
);
218 objc_write_int (struct objc_typed_stream
* stream
, int value
)
220 unsigned char buf
[sizeof(int)+1];
221 int len
= __objc_code_int (buf
, value
);
222 return (*stream
->write
)(stream
->physical
, buf
, len
);
225 static __inline__
int
226 __objc_code_unsigned_long (unsigned char* buf
, unsigned long val
)
228 if ((val
&_B_VALUE
) == val
)
230 buf
[0] = val
|_B_SINT
;
239 for (c
= sizeof(long); c
!= 0; c
-= 1)
240 if (((val
>>(8*(c
-1)))%0x100) != 0)
245 for (b
= 1; c
!= 0; c
--, b
++)
247 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
255 objc_write_unsigned_long (struct objc_typed_stream
* stream
, unsigned long value
)
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
);
262 static __inline__
int
263 __objc_code_long (unsigned char* buf
, long val
)
265 int sign
= (val
< 0);
266 int size
= __objc_code_unsigned_long (buf
, sign
? -val
: val
);
273 objc_write_long (struct objc_typed_stream
* stream
, long value
)
275 unsigned char buf
[sizeof(long)+1];
276 int len
= __objc_code_long (buf
, value
);
277 return (*stream
->write
)(stream
->physical
, buf
, len
);
282 objc_write_string (struct objc_typed_stream
* stream
,
283 const unsigned char* string
, unsigned int nbytes
)
285 unsigned char buf
[sizeof(unsigned int)+1];
286 int len
= __objc_code_unsigned_int (buf
, nbytes
);
288 if ((buf
[0]&_B_CODE
) == _B_SINT
)
289 buf
[0] = (buf
[0]&_B_VALUE
)|_B_SSTR
;
292 buf
[0] = (buf
[0]&_B_VALUE
)|_B_NSTR
;
294 if ((*stream
->write
)(stream
->physical
, buf
, len
) != 0)
295 return (*stream
->write
)(stream
->physical
, string
, nbytes
);
301 objc_write_string_atomic (struct objc_typed_stream
* stream
,
302 unsigned char* string
, unsigned int nbytes
)
305 if ((key
= PTR2LONG(hash_value_for_key (stream
->stream_table
, string
))))
306 return objc_write_use_common (stream
, key
);
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
);
318 objc_write_register_common (struct objc_typed_stream
* stream
, unsigned long key
)
320 unsigned char buf
[sizeof (unsigned long)+2];
321 int len
= __objc_code_unsigned_long (buf
+1, key
);
324 buf
[0] = _B_RCOMM
|0x01;
326 return (*stream
->write
)(stream
->physical
, buf
, len
+1);
330 buf
[1] = (buf
[1]&_B_VALUE
)|_B_RCOMM
;
331 return (*stream
->write
)(stream
->physical
, buf
+1, len
);
336 objc_write_use_common (struct objc_typed_stream
* stream
, unsigned long key
)
338 unsigned char buf
[sizeof (unsigned long)+2];
339 int len
= __objc_code_unsigned_long (buf
+1, key
);
342 buf
[0] = _B_UCOMM
|0x01;
344 return (*stream
->write
)(stream
->physical
, buf
, 2);
348 buf
[1] = (buf
[1]&_B_VALUE
)|_B_UCOMM
;
349 return (*stream
->write
)(stream
->physical
, buf
+1, len
);
353 static __inline__
int
354 __objc_write_extension (struct objc_typed_stream
* stream
, unsigned char code
)
356 if (code
<= _B_VALUE
)
358 unsigned char buf
= code
|_B_EXT
;
359 return (*stream
->write
)(stream
->physical
, &buf
, 1);
366 __objc_write_object (struct objc_typed_stream
* stream
, id object
)
368 unsigned char buf
= '\0';
369 SEL write_sel
= sel_get_any_uid ("write:");
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);
378 return objc_write_use_common(stream
, 0);
382 objc_write_object_reference (struct objc_typed_stream
* stream
, id object
)
385 if ((key
= PTR2LONG(hash_value_for_key (stream
->object_table
, object
))))
386 return objc_write_use_common (stream
, key
);
388 __objc_write_extension (stream
, _BX_OBJREF
);
389 return objc_write_unsigned_long (stream
, PTR2LONG (object
));
393 objc_write_root_object (struct objc_typed_stream
* stream
, id object
)
396 if (stream
->writing_root_p
)
397 __objc_fatal ("objc_write_root_object called recursively")
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;
410 objc_write_object (struct objc_typed_stream
* stream
, id object
)
413 if ((key
= PTR2LONG(hash_value_for_key (stream
->object_table
, object
))))
414 return objc_write_use_common (stream
, key
);
416 else if (object
== nil
)
417 return objc_write_use_common(stream
, 0);
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
);
430 extern int atoi (const char*);
431 extern size_t strlen(const char*);
432 extern size_t strcpy(char*, const char*);
436 __objc_write_class (struct objc_typed_stream
* stream
, struct objc_class
* class)
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
, class->version
);
446 objc_write_class (struct objc_typed_stream
* stream
,
447 struct objc_class
* class)
450 if ((key
= PTR2LONG(hash_value_for_key (stream
->stream_table
, class))))
451 return objc_write_use_common (stream
, key
);
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);
464 __objc_write_selector (struct objc_typed_stream
* stream
, SEL selector
)
466 const char* sel_name
;
467 __objc_write_extension (stream
, _BX_SEL
);
468 /* to handle NULL selectors */
469 if ((SEL
)0 == selector
)
470 return objc_write_string (stream
, "", 0);
471 sel_name
= sel_get_name (selector
);
472 return objc_write_string (stream
, sel_name
, strlen ((char*)sel_name
));
476 objc_write_selector (struct objc_typed_stream
* stream
, SEL selector
)
478 const char* sel_name
;
481 /* to handle NULL selectors */
482 if ((SEL
)0 == selector
)
483 return __objc_write_selector (stream
, selector
);
485 sel_name
= sel_get_name (selector
);
486 if ((key
= PTR2LONG(hash_value_for_key (stream
->stream_table
, sel_name
))))
487 return objc_write_use_common (stream
, key
);
491 hash_add (&stream
->stream_table
, LONG2PTR(key
=PTR2LONG(sel_name
)), (char*)sel_name
);
492 if ((length
= objc_write_register_common (stream
, key
)))
493 return __objc_write_selector (stream
, selector
);
505 objc_read_char (struct objc_typed_stream
* stream
, char* val
)
509 len
= (*stream
->read
)(stream
->physical
, &buf
, 1);
512 if ((buf
& _B_CODE
) == _B_SINT
)
513 (*val
) = (buf
& _B_VALUE
);
515 else if ((buf
& _B_NUMBER
) == 1)
517 len
= (*stream
->read
)(stream
->physical
, val
, 1);
523 __objc_fatal("expected 8bit signed int, got %dbit int",
524 (int)(buf
&_B_NUMBER
)*8);
531 objc_read_unsigned_char (struct objc_typed_stream
* stream
, unsigned char* val
)
535 if ((len
= (*stream
->read
)(stream
->physical
, &buf
, 1)))
537 if ((buf
& _B_CODE
) == _B_SINT
)
538 (*val
) = (buf
& _B_VALUE
);
540 else if ((buf
& _B_NUMBER
) == 1)
541 len
= (*stream
->read
)(stream
->physical
, val
, 1);
544 __objc_fatal("expected 8bit unsigned int, got %dbit int",
545 (int)(buf
&_B_NUMBER
)*8);
551 objc_read_short (struct objc_typed_stream
* stream
, short* value
)
553 unsigned char buf
[sizeof(short)+1];
555 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
557 if ((buf
[0] & _B_CODE
) == _B_SINT
)
558 (*value
) = (buf
[0] & _B_VALUE
);
563 int nbytes
= buf
[0] & _B_NUMBER
;
564 if (nbytes
> sizeof (short))
565 __objc_fatal("expected short, got bigger (%dbits)", nbytes
*8);
566 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
568 while (pos
<= nbytes
)
569 (*value
) = ((*value
)*0x100) + buf
[pos
++];
570 if (buf
[0] & _B_SIGN
)
571 (*value
) = -(*value
);
578 objc_read_unsigned_short (struct objc_typed_stream
* stream
,
579 unsigned short* value
)
581 unsigned char buf
[sizeof(unsigned short)+1];
583 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
585 if ((buf
[0] & _B_CODE
) == _B_SINT
)
586 (*value
) = (buf
[0] & _B_VALUE
);
591 int nbytes
= buf
[0] & _B_NUMBER
;
592 if (nbytes
> sizeof (short))
593 __objc_fatal("expected short, got int or bigger");
594 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
596 while (pos
<= nbytes
)
597 (*value
) = ((*value
)*0x100) + buf
[pos
++];
605 objc_read_int (struct objc_typed_stream
* stream
, int* value
)
607 unsigned char buf
[sizeof(int)+1];
609 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
611 if ((buf
[0] & _B_CODE
) == _B_SINT
)
612 (*value
) = (buf
[0] & _B_VALUE
);
617 int nbytes
= buf
[0] & _B_NUMBER
;
618 if (nbytes
> sizeof (int))
619 __objc_fatal("expected int, got bigger");
620 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
622 while (pos
<= nbytes
)
623 (*value
) = ((*value
)*0x100) + buf
[pos
++];
624 if (buf
[0] & _B_SIGN
)
625 (*value
) = -(*value
);
632 objc_read_long (struct objc_typed_stream
* stream
, long* value
)
634 unsigned char buf
[sizeof(long)+1];
636 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
638 if ((buf
[0] & _B_CODE
) == _B_SINT
)
639 (*value
) = (buf
[0] & _B_VALUE
);
644 int nbytes
= buf
[0] & _B_NUMBER
;
645 if (nbytes
> sizeof (long))
646 __objc_fatal("expected long, got bigger");
647 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
649 while (pos
<= nbytes
)
650 (*value
) = ((*value
)*0x100) + buf
[pos
++];
651 if (buf
[0] & _B_SIGN
)
652 (*value
) = -(*value
);
659 __objc_read_nbyte_uint (struct objc_typed_stream
* stream
,
660 unsigned int nbytes
, unsigned int* val
)
663 unsigned char buf
[sizeof(unsigned int)+1];
665 if (nbytes
> sizeof (int))
666 __objc_fatal("expected int, got bigger");
668 len
= (*stream
->read
)(stream
->physical
, buf
, nbytes
);
671 (*val
) = ((*val
)*0x100) + buf
[pos
++];
677 objc_read_unsigned_int (struct objc_typed_stream
* stream
,
680 unsigned char buf
[sizeof(unsigned int)+1];
682 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
684 if ((buf
[0] & _B_CODE
) == _B_SINT
)
685 (*value
) = (buf
[0] & _B_VALUE
);
688 len
= __objc_read_nbyte_uint (stream
, (buf
[0] & _B_VALUE
), value
);
695 __objc_read_nbyte_ulong (struct objc_typed_stream
* stream
,
696 unsigned int nbytes
, unsigned long* val
)
699 unsigned char buf
[sizeof(unsigned long)+1];
701 if (nbytes
> sizeof (long))
702 __objc_fatal("expected long, got bigger");
704 len
= (*stream
->read
)(stream
->physical
, buf
, nbytes
);
707 (*val
) = ((*val
)*0x100) + buf
[pos
++];
713 objc_read_unsigned_long (struct objc_typed_stream
* stream
,
714 unsigned long* value
)
716 unsigned char buf
[sizeof(unsigned long)+1];
718 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
720 if ((buf
[0] & _B_CODE
) == _B_SINT
)
721 (*value
) = (buf
[0] & _B_VALUE
);
724 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), value
);
731 objc_read_string (struct objc_typed_stream
* stream
,
734 unsigned char buf
[sizeof(unsigned int)+1];
736 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
738 unsigned long key
= 0;
740 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
742 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
743 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
746 switch (buf
[0]&_B_CODE
) {
749 int length
= buf
[0]&_B_VALUE
;
750 (*string
) = (char*)__objc_xmalloc(length
+1);
752 hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
753 len
= (*stream
->read
)(stream
->physical
, *string
, length
);
754 (*string
)[length
] = '\0';
761 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
762 tmp
= hash_value_for_key (stream
->stream_table
, LONG2PTR (key
));
763 *string
= __objc_xmalloc (strlen(tmp
) + 1);
764 strcpy (*string
, tmp
);
770 unsigned int nbytes
= buf
[0]&_B_VALUE
;
771 len
= __objc_read_nbyte_uint(stream
, nbytes
, &nbytes
);
773 (*string
) = (char*)__objc_xmalloc(nbytes
+1);
775 hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
776 len
= (*stream
->read
)(stream
->physical
, *string
, nbytes
);
777 (*string
)[nbytes
] = '\0';
783 __objc_fatal("expected string, got opcode %c\n", (buf
[0]&_B_CODE
));
792 objc_read_object (struct objc_typed_stream
* stream
, id
* object
)
794 unsigned char buf
[sizeof (unsigned int)];
796 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
798 SEL read_sel
= sel_get_any_uid ("read:");
799 unsigned long key
= 0;
801 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register common */
803 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
804 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
807 if (buf
[0] == (_B_EXT
| _BX_OBJECT
))
812 len
= objc_read_class (stream
, &class);
814 /* create instance */
815 (*object
) = class_create_instance(class);
819 hash_add (&stream
->object_table
, LONG2PTR(key
), *object
);
822 if (__objc_responds_to (*object
, read_sel
))
823 (*get_imp(class, read_sel
))(*object
, read_sel
, stream
);
825 /* check null-byte */
826 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
828 __objc_fatal("expected null-byte, got opcode %c", buf
[0]);
831 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
834 __objc_fatal("cannot register use upcode...");
835 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
836 (*object
) = hash_value_for_key (stream
->object_table
, LONG2PTR(key
));
839 else if (buf
[0] == (_B_EXT
| _BX_OBJREF
)) /* a forward reference */
841 struct objc_list
* other
;
842 len
= objc_read_unsigned_long (stream
, &key
);
843 other
= (struct objc_list
*)hash_value_for_key (stream
->object_refs
, LONG2PTR(key
));
844 hash_add (&stream
->object_refs
, LONG2PTR(key
), (void*)list_cons(object
, other
));
847 else if (buf
[0] == (_B_EXT
| _BX_OBJROOT
)) /* a root object */
850 __objc_fatal("cannot register root object...");
851 len
= objc_read_object (stream
, object
);
852 __objc_finish_read_root_object (stream
);
856 __objc_fatal("expected object, got opcode %c", buf
[0]);
862 objc_read_class (struct objc_typed_stream
* stream
, Class
* class)
864 unsigned char buf
[sizeof (unsigned int)];
866 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
868 unsigned long key
= 0;
870 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
872 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
873 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
876 if (buf
[0] == (_B_EXT
| _BX_CLASS
))
879 unsigned long version
;
882 len
= objc_read_string (stream
, &class_name
);
883 (*class) = objc_get_class(class_name
);
888 hash_add (&stream
->stream_table
, LONG2PTR(key
), *class);
890 objc_read_unsigned_long(stream
, &version
);
891 hash_add (&stream
->class_table
, (*class)->name
, (void*)version
);
894 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
897 __objc_fatal("cannot register use upcode...");
898 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
899 (*class) = hash_value_for_key (stream
->stream_table
, LONG2PTR(key
));
901 __objc_fatal("cannot find class for key %lu", key
);
905 __objc_fatal("expected class, got opcode %c", buf
[0]);
911 objc_read_selector (struct objc_typed_stream
* stream
, SEL
* selector
)
913 unsigned char buf
[sizeof (unsigned int)];
915 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
917 unsigned long key
= 0;
919 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
921 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
922 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
925 if (buf
[0] == (_B_EXT
|_BX_SEL
)) /* selector! */
930 len
= objc_read_string (stream
, &selector_name
);
931 /* To handle NULL selectors */
932 if (0 == strlen(selector_name
))
934 (*selector
) = (SEL
)0;
938 (*selector
) = sel_get_any_uid(selector_name
);
939 free (selector_name
);
943 hash_add (&stream
->stream_table
, LONG2PTR(key
), (void*)*selector
);
946 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
949 __objc_fatal("cannot register use upcode...");
950 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
951 (*selector
) = hash_value_for_key (stream
->stream_table
, LONG2PTR(key
));
955 __objc_fatal("expected selector, got opcode %c", buf
[0]);
961 ** USER LEVEL FUNCTIONS
965 ** Write one object, encoded in TYPE and pointed to by DATA to the
966 ** typed stream STREAM.
970 objc_write_type(TypedStream
* stream
, const char* type
, const void* data
)
974 return objc_write_object (stream
, *(id
*)data
);
978 return objc_write_class (stream
, *(Class
*)data
);
982 return objc_write_selector (stream
, *(SEL
*)data
);
986 return objc_write_char(stream
, *(char*)data
);
990 return objc_write_unsigned_char(stream
, *(unsigned char*)data
);
994 return objc_write_short(stream
, *(short*)data
);
998 return objc_write_unsigned_short(stream
, *(unsigned short*)data
);
1002 return objc_write_int(stream
, *(int*)data
);
1006 return objc_write_unsigned_int(stream
, *(unsigned int*)data
);
1010 return objc_write_long(stream
, *(long*)data
);
1014 return objc_write_unsigned_long(stream
, *(unsigned long*)data
);
1018 return objc_write_string (stream
, *(char**)data
, strlen(*(char**)data
));
1022 return objc_write_string_atomic (stream
, *(char**)data
, strlen(*(char**)data
));
1027 int len
= atoi(type
+1);
1028 while (isdigit(*++type
))
1030 return objc_write_array (stream
, type
, len
, data
);
1038 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1039 ; /* skip "<name>=" */
1040 while (*type
!= _C_STRUCT_E
)
1042 align
= objc_alignof_type (type
); /* padd to alignment */
1043 acc_size
+= ROUND (acc_size
, align
);
1044 objc_write_type (stream
, type
, ((char*)data
)+acc_size
);
1045 acc_size
+= objc_sizeof_type (type
); /* add component size */
1046 type
= objc_skip_typespec (type
); /* skip component */
1052 fprintf(stderr
, "objc_write_type: cannot parse typespec: %s\n", type
);
1058 ** Read one object, encoded in TYPE and pointed to by DATA to the
1059 ** typed stream STREAM. DATA specifies the address of the types to
1060 ** read. Expected type is checked against the type actually present
1065 objc_read_type(TypedStream
* stream
, const char* type
, void* data
)
1070 return objc_read_object (stream
, (id
*)data
);
1074 return objc_read_class (stream
, (Class
*)data
);
1078 return objc_read_selector (stream
, (SEL
*)data
);
1082 return objc_read_char (stream
, (char*)data
);
1086 return objc_read_unsigned_char (stream
, (unsigned char*)data
);
1090 return objc_read_short (stream
, (short*)data
);
1094 return objc_read_unsigned_short (stream
, (unsigned short*)data
);
1098 return objc_read_int (stream
, (int*)data
);
1102 return objc_read_unsigned_int (stream
, (unsigned int*)data
);
1106 return objc_read_long (stream
, (long*)data
);
1110 return objc_read_unsigned_long (stream
, (unsigned long*)data
);
1115 return objc_read_string (stream
, (char**)data
);
1120 int len
= atoi(type
+1);
1121 while (isdigit(*++type
))
1123 return objc_read_array (stream
, type
, len
, data
);
1131 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1132 ; /* skip "<name>=" */
1133 while (*type
!= _C_STRUCT_E
)
1135 align
= objc_alignof_type (type
); /* padd to alignment */
1136 acc_size
+= ROUND (acc_size
, align
);
1137 objc_read_type (stream
, type
, ((char*)data
)+acc_size
);
1138 acc_size
+= objc_sizeof_type (type
); /* add component size */
1139 type
= objc_skip_typespec (type
); /* skip component */
1145 fprintf(stderr
, "objc_read_type: cannot parse typespec: %s\n", type
);
1151 ** Write the object specified by the template TYPE to STREAM. Last
1152 ** arguments specify addresses of values to be written. It might
1153 ** seem surprising to specify values by address, but this is extremely
1154 ** convenient for copy-paste with objc_read_types calls. A more
1155 ** down-to-the-earth cause for this passing of addresses is that values
1156 ** of arbitrary size is not well supported in ANSI C for functions with
1157 ** variable number of arguments.
1161 objc_write_types (TypedStream
* stream
, const char* type
, ...)
1167 va_start(args
, type
);
1169 for (c
= type
; *c
; c
= objc_skip_typespec (c
))
1173 res
= objc_write_object (stream
, *va_arg (args
, id
*));
1177 res
= objc_write_class (stream
, *va_arg(args
, Class
*));
1181 res
= objc_write_selector (stream
, *va_arg(args
, SEL
*));
1185 res
= objc_write_char (stream
, *va_arg (args
, char*));
1189 res
= objc_write_unsigned_char (stream
,
1190 *va_arg (args
, unsigned char*));
1194 res
= objc_write_short (stream
, *va_arg(args
, short*));
1198 res
= objc_write_unsigned_short (stream
,
1199 *va_arg(args
, unsigned short*));
1203 res
= objc_write_int(stream
, *va_arg(args
, int*));
1207 res
= objc_write_unsigned_int(stream
, *va_arg(args
, unsigned int*));
1211 res
= objc_write_long(stream
, *va_arg(args
, long*));
1215 res
= objc_write_unsigned_long(stream
, *va_arg(args
, unsigned long*));
1220 char** str
= va_arg(args
, char**);
1221 res
= objc_write_string (stream
, *str
, strlen(*str
));
1227 char** str
= va_arg(args
, char**);
1228 res
= objc_write_string_atomic (stream
, *str
, strlen(*str
));
1234 int len
= atoi(c
+1);
1236 while (isdigit(*++t
))
1238 res
= objc_write_array (stream
, t
, len
, va_arg(args
, void*));
1239 t
= objc_skip_typespec (t
);
1241 __objc_fatal("expected `]', got: %s", t
);
1246 fprintf(stderr
, "objc_write_types: cannot parse typespec: %s\n", type
);
1256 ** Last arguments specify addresses of values to be read. Expected
1257 ** type is checked against the type actually present on the stream.
1261 objc_read_types(TypedStream
* stream
, const char* type
, ...)
1267 va_start(args
, type
);
1269 for (c
= type
; *c
; c
= objc_skip_typespec(c
))
1273 res
= objc_read_object(stream
, va_arg(args
, id
*));
1277 res
= objc_read_class(stream
, va_arg(args
, Class
*));
1281 res
= objc_read_selector(stream
, va_arg(args
, SEL
*));
1285 res
= objc_read_char(stream
, va_arg(args
, char*));
1289 res
= objc_read_unsigned_char(stream
, va_arg(args
, unsigned char*));
1293 res
= objc_read_short(stream
, va_arg(args
, short*));
1297 res
= objc_read_unsigned_short(stream
, va_arg(args
, unsigned short*));
1301 res
= objc_read_int(stream
, va_arg(args
, int*));
1305 res
= objc_read_unsigned_int(stream
, va_arg(args
, unsigned int*));
1309 res
= objc_read_long(stream
, va_arg(args
, long*));
1313 res
= objc_read_unsigned_long(stream
, va_arg(args
, unsigned long*));
1319 char** str
= va_arg(args
, char**);
1320 res
= objc_read_string (stream
, str
);
1326 int len
= atoi(c
+1);
1328 while (isdigit(*++t
))
1330 res
= objc_read_array (stream
, t
, len
, va_arg(args
, void*));
1331 t
= objc_skip_typespec (t
);
1333 __objc_fatal("expected `]', got: %s", t
);
1338 fprintf(stderr
, "objc_read_types: cannot parse typespec: %s\n", type
);
1347 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1348 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1352 objc_write_array (TypedStream
* stream
, const char* type
,
1353 int count
, const void* data
)
1355 int off
= objc_sizeof_type(type
);
1356 const char* where
= data
;
1360 objc_write_type(stream
, type
, where
);
1367 ** Read an array of COUNT elements of TYPE into the memory address
1368 ** DATA. The memory pointed to by data is supposed to be allocated
1369 ** by the callee. This is equivalent of
1370 ** objc_read_type (stream, "[N<type>]", data)
1374 objc_read_array (TypedStream
* stream
, const char* type
,
1375 int count
, void* data
)
1377 int off
= objc_sizeof_type(type
);
1378 char* where
= (char*)data
;
1382 objc_read_type(stream
, type
, where
);
1389 __objc_free (void* p
)
1395 __objc_fread(FILE* file
, char* data
, int len
)
1397 return fread(data
, len
, 1, file
);
1401 __objc_fwrite(FILE* file
, char* data
, int len
)
1403 return fwrite(data
, len
, 1, file
);
1407 __objc_feof(FILE* file
)
1413 __objc_no_write(FILE* file
, char* data
, int len
)
1415 __objc_fatal ("TypedStream not open for writing");
1419 __objc_no_read(FILE* file
, char* data
, int len
)
1421 __objc_fatal ("TypedStream not open for reading");
1425 __objc_read_typed_stream_signature (TypedStream
* stream
)
1430 (*stream
->read
)(stream
->physical
, buffer
+pos
, 1);
1431 while (buffer
[pos
++] != '\0')
1433 sscanf (buffer
, "GNU TypedStream %d", &stream
->version
);
1434 if (stream
->version
!= OBJC_TYPED_STREAM_VERSION
)
1435 __objc_fatal ("cannot handle TypedStream version %d", stream
->version
);
1440 __objc_write_typed_stream_signature (TypedStream
* stream
)
1443 sprintf(buffer
, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION
);
1444 stream
->version
= OBJC_TYPED_STREAM_VERSION
;
1445 (*stream
->write
)(stream
->physical
, buffer
, strlen(buffer
)+1);
1449 static void __objc_finish_write_root_object(struct objc_typed_stream
* stream
)
1451 hash_delete (stream
->object_table
);
1452 stream
->object_table
= hash_new(64,
1453 (hash_func_type
)hash_ptr
,
1454 (compare_func_type
)compare_ptrs
);
1457 static void __objc_finish_read_root_object(struct objc_typed_stream
* stream
)
1460 struct objc_list
* free_list
;
1461 SEL awake_sel
= sel_get_any_uid ("awake");
1463 /* resolve object forward references */
1464 free_list
= list_cons(NULL
, NULL
);
1465 for (node
= hash_next (stream
->object_refs
, NULL
); node
;
1466 node
= hash_next (stream
->object_refs
, node
))
1468 struct objc_list
* reflist
= node
->value
;
1469 const void* key
= node
->key
;
1470 id object
= hash_value_for_key (stream
->object_table
, key
);
1473 *((id
*)reflist
->head
) = object
;
1474 if (list_find(&free_list
, reflist
) == NULL
)
1475 free_list
= list_cons (reflist
, free_list
);
1476 reflist
= reflist
->tail
;
1479 list_mapcar (free_list
, __objc_free
);
1480 list_free (free_list
);
1482 /* empty object reference table */
1483 hash_delete (stream
->object_refs
);
1484 stream
->object_refs
= hash_new(8, (hash_func_type
)hash_ptr
,
1485 (compare_func_type
)compare_ptrs
);
1487 /* call -awake for all objects read */
1490 for (node
= hash_next (stream
->object_table
, NULL
); node
;
1491 node
= hash_next (stream
->object_table
, node
))
1493 id object
= node
->value
;
1494 if (__objc_responds_to (object
, awake_sel
))
1495 (*objc_msg_lookup(object
, awake_sel
))(object
, awake_sel
);
1499 /* empty object table */
1500 hash_delete (stream
->object_table
);
1501 stream
->object_table
= hash_new(64,
1502 (hash_func_type
)hash_ptr
,
1503 (compare_func_type
)compare_ptrs
);
1507 ** Open the stream PHYSICAL in MODE
1511 objc_open_typed_stream (FILE* physical
, int mode
)
1513 TypedStream
* s
= (TypedStream
*)__objc_xmalloc(sizeof(TypedStream
));
1516 s
->physical
= physical
;
1517 s
->stream_table
= hash_new(64,
1518 (hash_func_type
)hash_ptr
,
1519 (compare_func_type
)compare_ptrs
);
1520 s
->object_table
= hash_new(64,
1521 (hash_func_type
)hash_ptr
,
1522 (compare_func_type
)compare_ptrs
);
1523 s
->eof
= (objc_typed_eof_func
)__objc_feof
;
1524 s
->flush
= (objc_typed_flush_func
)fflush
;
1525 s
->writing_root_p
= 0;
1526 if (mode
== OBJC_READONLY
)
1528 s
->class_table
= hash_new(8, (hash_func_type
)hash_string
,
1529 (compare_func_type
)compare_strings
);
1530 s
->object_refs
= hash_new(8, (hash_func_type
)hash_ptr
,
1531 (compare_func_type
)compare_ptrs
);
1532 s
->read
= (objc_typed_read_func
)__objc_fread
;
1533 s
->write
= (objc_typed_write_func
)__objc_no_write
;
1534 __objc_read_typed_stream_signature (s
);
1536 else if (mode
== OBJC_WRITEONLY
)
1540 s
->read
= (objc_typed_read_func
)__objc_no_read
;
1541 s
->write
= (objc_typed_write_func
)__objc_fwrite
;
1542 __objc_write_typed_stream_signature (s
);
1546 objc_close_typed_stream (s
);
1549 s
->type
= OBJC_FILE_STREAM
;
1554 ** Open the file named by FILE_NAME in MODE
1558 objc_open_typed_stream_for_file (const char* file_name
, int mode
)
1563 if (mode
== OBJC_READONLY
)
1564 file
= fopen (file_name
, "r");
1566 file
= fopen (file_name
, "w");
1570 s
= objc_open_typed_stream (file
, mode
);
1572 s
->type
|= OBJC_MANAGED_STREAM
;
1580 ** Close STREAM freeing the structure it self. If it was opened with
1581 ** objc_open_typed_stream_for_file, the file will also be closed.
1585 objc_close_typed_stream (TypedStream
* stream
)
1587 if (stream
->mode
== OBJC_READONLY
)
1589 __objc_finish_read_root_object (stream
); /* Just in case... */
1590 hash_delete (stream
->class_table
);
1591 hash_delete (stream
->object_refs
);
1594 hash_delete (stream
->stream_table
);
1595 hash_delete (stream
->object_table
);
1597 if (stream
->type
== (OBJC_MANAGED_STREAM
| OBJC_FILE_STREAM
))
1598 fclose ((FILE*)stream
->physical
);
1604 objc_end_of_typed_stream (TypedStream
* stream
)
1606 return (*stream
->eof
)(stream
->physical
);
1610 objc_flush_typed_stream (TypedStream
* stream
)
1612 (*stream
->flush
)(stream
->physical
);
1616 objc_get_stream_class_version (TypedStream
* stream
, Class
class)
1618 if (stream
->class_table
)
1619 return PTR2LONG(hash_value_for_key (stream
->class_table
, class->name
));
1621 return class_get_version (class);