1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993, 1995, 1996, 1997 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 /* Declare some functions... */
43 objc_read_class (struct objc_typed_stream
* stream
, Class
* class);
45 int objc_sizeof_type(const char* type
);
48 objc_write_use_common (struct objc_typed_stream
* stream
, unsigned long key
);
51 objc_write_register_common (struct objc_typed_stream
* stream
,
55 objc_write_class (struct objc_typed_stream
* stream
,
56 struct objc_class
* class);
58 const char* objc_skip_type (const char* type
);
60 static void __objc_finish_write_root_object(struct objc_typed_stream
*);
61 static void __objc_finish_read_root_object(struct objc_typed_stream
*);
64 __objc_code_unsigned_char (unsigned char* buf
, unsigned char val
)
66 if ((val
&_B_VALUE
) == val
)
73 buf
[0] = _B_NINT
|0x01;
80 objc_write_unsigned_char (struct objc_typed_stream
* stream
,
83 unsigned char buf
[sizeof (unsigned char)+1];
84 int len
= __objc_code_unsigned_char (buf
, value
);
85 return (*stream
->write
)(stream
->physical
, buf
, len
);
89 __objc_code_char (unsigned char* buf
, char val
)
92 return __objc_code_unsigned_char (buf
, val
);
95 buf
[0] = _B_NINT
|_B_SIGN
|0x01;
102 objc_write_char (struct objc_typed_stream
* stream
, char value
)
104 unsigned char buf
[sizeof (char)+1];
105 int len
= __objc_code_char (buf
, value
);
106 return (*stream
->write
)(stream
->physical
, buf
, len
);
109 static __inline__
int
110 __objc_code_unsigned_short (unsigned char* buf
, unsigned short val
)
112 if ((val
&_B_VALUE
) == val
)
114 buf
[0] = val
|_B_SINT
;
123 for (c
= sizeof(short); c
!= 0; c
-= 1)
124 if (((val
>>(8*(c
-1)))%0x100) != 0)
129 for (b
= 1; c
!= 0; c
--, b
++)
131 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
139 objc_write_unsigned_short (struct objc_typed_stream
* stream
,
140 unsigned short value
)
142 unsigned char buf
[sizeof (unsigned short)+1];
143 int len
= __objc_code_unsigned_short (buf
, value
);
144 return (*stream
->write
)(stream
->physical
, buf
, len
);
147 static __inline__
int
148 __objc_code_short (unsigned char* buf
, short val
)
150 int sign
= (val
< 0);
151 int size
= __objc_code_unsigned_short (buf
, sign
? -val
: val
);
158 objc_write_short (struct objc_typed_stream
* stream
, short value
)
160 unsigned char buf
[sizeof (short)+1];
161 int len
= __objc_code_short (buf
, value
);
162 return (*stream
->write
)(stream
->physical
, buf
, len
);
166 static __inline__
int
167 __objc_code_unsigned_int (unsigned char* buf
, unsigned int val
)
169 if ((val
&_B_VALUE
) == val
)
171 buf
[0] = val
|_B_SINT
;
180 for (c
= sizeof(int); c
!= 0; c
-= 1)
181 if (((val
>>(8*(c
-1)))%0x100) != 0)
186 for (b
= 1; c
!= 0; c
--, b
++)
188 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
196 objc_write_unsigned_int (struct objc_typed_stream
* stream
, unsigned int value
)
198 unsigned char buf
[sizeof(unsigned int)+1];
199 int len
= __objc_code_unsigned_int (buf
, value
);
200 return (*stream
->write
)(stream
->physical
, buf
, len
);
203 static __inline__
int
204 __objc_code_int (unsigned char* buf
, int val
)
206 int sign
= (val
< 0);
207 int size
= __objc_code_unsigned_int (buf
, sign
? -val
: val
);
214 objc_write_int (struct objc_typed_stream
* stream
, int value
)
216 unsigned char buf
[sizeof(int)+1];
217 int len
= __objc_code_int (buf
, value
);
218 return (*stream
->write
)(stream
->physical
, buf
, len
);
221 static __inline__
int
222 __objc_code_unsigned_long (unsigned char* buf
, unsigned long val
)
224 if ((val
&_B_VALUE
) == val
)
226 buf
[0] = val
|_B_SINT
;
235 for (c
= sizeof(long); c
!= 0; c
-= 1)
236 if (((val
>>(8*(c
-1)))%0x100) != 0)
241 for (b
= 1; c
!= 0; c
--, b
++)
243 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
251 objc_write_unsigned_long (struct objc_typed_stream
* stream
,
254 unsigned char buf
[sizeof(unsigned long)+1];
255 int len
= __objc_code_unsigned_long (buf
, value
);
256 return (*stream
->write
)(stream
->physical
, buf
, len
);
259 static __inline__
int
260 __objc_code_long (unsigned char* buf
, long val
)
262 int sign
= (val
< 0);
263 int size
= __objc_code_unsigned_long (buf
, sign
? -val
: val
);
270 objc_write_long (struct objc_typed_stream
* stream
, long value
)
272 unsigned char buf
[sizeof(long)+1];
273 int len
= __objc_code_long (buf
, value
);
274 return (*stream
->write
)(stream
->physical
, buf
, len
);
279 objc_write_string (struct objc_typed_stream
* stream
,
280 const unsigned char* string
, unsigned int nbytes
)
282 unsigned char buf
[sizeof(unsigned int)+1];
283 int len
= __objc_code_unsigned_int (buf
, nbytes
);
285 if ((buf
[0]&_B_CODE
) == _B_SINT
)
286 buf
[0] = (buf
[0]&_B_VALUE
)|_B_SSTR
;
289 buf
[0] = (buf
[0]&_B_VALUE
)|_B_NSTR
;
291 if ((*stream
->write
)(stream
->physical
, buf
, len
) != 0)
292 return (*stream
->write
)(stream
->physical
, string
, nbytes
);
298 objc_write_string_atomic (struct objc_typed_stream
* stream
,
299 unsigned char* string
, unsigned int nbytes
)
302 if ((key
= PTR2LONG(hash_value_for_key (stream
->stream_table
, string
))))
303 return objc_write_use_common (stream
, key
);
307 hash_add (&stream
->stream_table
, LONG2PTR(key
=PTR2LONG(string
)), string
);
308 if ((length
= objc_write_register_common (stream
, key
)))
309 return objc_write_string (stream
, string
, nbytes
);
315 objc_write_register_common (struct objc_typed_stream
* stream
,
318 unsigned char buf
[sizeof (unsigned long)+2];
319 int len
= __objc_code_unsigned_long (buf
+1, key
);
322 buf
[0] = _B_RCOMM
|0x01;
324 return (*stream
->write
)(stream
->physical
, buf
, len
+1);
328 buf
[1] = (buf
[1]&_B_VALUE
)|_B_RCOMM
;
329 return (*stream
->write
)(stream
->physical
, buf
+1, len
);
334 objc_write_use_common (struct objc_typed_stream
* stream
, unsigned long key
)
336 unsigned char buf
[sizeof (unsigned long)+2];
337 int len
= __objc_code_unsigned_long (buf
+1, key
);
340 buf
[0] = _B_UCOMM
|0x01;
342 return (*stream
->write
)(stream
->physical
, buf
, 2);
346 buf
[1] = (buf
[1]&_B_VALUE
)|_B_UCOMM
;
347 return (*stream
->write
)(stream
->physical
, buf
+1, len
);
351 static __inline__
int
352 __objc_write_extension (struct objc_typed_stream
* stream
, unsigned char code
)
354 if (code
<= _B_VALUE
)
356 unsigned char buf
= code
|_B_EXT
;
357 return (*stream
->write
)(stream
->physical
, &buf
, 1);
360 objc_error(nil
, OBJC_ERR_BAD_OPCODE
,
361 "__objc_write_extension: bad opcode %c\n", code
);
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_error (nil
, OBJC_ERR_RECURSE_ROOT
,
397 "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
,
492 LONG2PTR(key
=PTR2LONG(sel_name
)), (char*)sel_name
);
493 if ((length
= objc_write_register_common (stream
, key
)))
494 return __objc_write_selector (stream
, selector
);
506 objc_read_char (struct objc_typed_stream
* stream
, char* val
)
510 len
= (*stream
->read
)(stream
->physical
, &buf
, 1);
513 if ((buf
& _B_CODE
) == _B_SINT
)
514 (*val
) = (buf
& _B_VALUE
);
516 else if ((buf
& _B_NUMBER
) == 1)
518 len
= (*stream
->read
)(stream
->physical
, val
, 1);
524 objc_error(nil
, OBJC_ERR_BAD_DATA
,
525 "expected 8bit signed int, got %dbit int",
526 (int)(buf
&_B_NUMBER
)*8);
533 objc_read_unsigned_char (struct objc_typed_stream
* stream
, unsigned char* val
)
537 if ((len
= (*stream
->read
)(stream
->physical
, &buf
, 1)))
539 if ((buf
& _B_CODE
) == _B_SINT
)
540 (*val
) = (buf
& _B_VALUE
);
542 else if ((buf
& _B_NUMBER
) == 1)
543 len
= (*stream
->read
)(stream
->physical
, val
, 1);
546 objc_error(nil
, OBJC_ERR_BAD_DATA
,
547 "expected 8bit unsigned int, got %dbit int",
548 (int)(buf
&_B_NUMBER
)*8);
554 objc_read_short (struct objc_typed_stream
* stream
, short* value
)
556 unsigned char buf
[sizeof(short)+1];
558 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
560 if ((buf
[0] & _B_CODE
) == _B_SINT
)
561 (*value
) = (buf
[0] & _B_VALUE
);
566 int nbytes
= buf
[0] & _B_NUMBER
;
567 if (nbytes
> sizeof (short))
568 objc_error(nil
, OBJC_ERR_BAD_DATA
,
569 "expected short, got bigger (%dbits)", nbytes
*8);
570 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
572 while (pos
<= nbytes
)
573 (*value
) = ((*value
)*0x100) + buf
[pos
++];
574 if (buf
[0] & _B_SIGN
)
575 (*value
) = -(*value
);
582 objc_read_unsigned_short (struct objc_typed_stream
* stream
,
583 unsigned short* value
)
585 unsigned char buf
[sizeof(unsigned short)+1];
587 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
589 if ((buf
[0] & _B_CODE
) == _B_SINT
)
590 (*value
) = (buf
[0] & _B_VALUE
);
595 int nbytes
= buf
[0] & _B_NUMBER
;
596 if (nbytes
> sizeof (short))
597 objc_error(nil
, OBJC_ERR_BAD_DATA
,
598 "expected short, got int or bigger");
599 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
601 while (pos
<= nbytes
)
602 (*value
) = ((*value
)*0x100) + buf
[pos
++];
610 objc_read_int (struct objc_typed_stream
* stream
, int* value
)
612 unsigned char buf
[sizeof(int)+1];
614 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
616 if ((buf
[0] & _B_CODE
) == _B_SINT
)
617 (*value
) = (buf
[0] & _B_VALUE
);
622 int nbytes
= buf
[0] & _B_NUMBER
;
623 if (nbytes
> sizeof (int))
624 objc_error(nil
, OBJC_ERR_BAD_DATA
, "expected int, got bigger");
625 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
627 while (pos
<= nbytes
)
628 (*value
) = ((*value
)*0x100) + buf
[pos
++];
629 if (buf
[0] & _B_SIGN
)
630 (*value
) = -(*value
);
637 objc_read_long (struct objc_typed_stream
* stream
, long* value
)
639 unsigned char buf
[sizeof(long)+1];
641 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
643 if ((buf
[0] & _B_CODE
) == _B_SINT
)
644 (*value
) = (buf
[0] & _B_VALUE
);
649 int nbytes
= buf
[0] & _B_NUMBER
;
650 if (nbytes
> sizeof (long))
651 objc_error(nil
, OBJC_ERR_BAD_DATA
, "expected long, got bigger");
652 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
654 while (pos
<= nbytes
)
655 (*value
) = ((*value
)*0x100) + buf
[pos
++];
656 if (buf
[0] & _B_SIGN
)
657 (*value
) = -(*value
);
664 __objc_read_nbyte_uint (struct objc_typed_stream
* stream
,
665 unsigned int nbytes
, unsigned int* val
)
668 unsigned char buf
[sizeof(unsigned int)+1];
670 if (nbytes
> sizeof (int))
671 objc_error(nil
, OBJC_ERR_BAD_DATA
, "expected int, got bigger");
673 len
= (*stream
->read
)(stream
->physical
, buf
, nbytes
);
676 (*val
) = ((*val
)*0x100) + buf
[pos
++];
682 objc_read_unsigned_int (struct objc_typed_stream
* stream
,
685 unsigned char buf
[sizeof(unsigned int)+1];
687 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
689 if ((buf
[0] & _B_CODE
) == _B_SINT
)
690 (*value
) = (buf
[0] & _B_VALUE
);
693 len
= __objc_read_nbyte_uint (stream
, (buf
[0] & _B_VALUE
), value
);
700 __objc_read_nbyte_ulong (struct objc_typed_stream
* stream
,
701 unsigned int nbytes
, unsigned long* val
)
704 unsigned char buf
[sizeof(unsigned long)+1];
706 if (nbytes
> sizeof (long))
707 objc_error(nil
, OBJC_ERR_BAD_DATA
, "expected long, got bigger");
709 len
= (*stream
->read
)(stream
->physical
, buf
, nbytes
);
712 (*val
) = ((*val
)*0x100) + buf
[pos
++];
718 objc_read_unsigned_long (struct objc_typed_stream
* stream
,
719 unsigned long* value
)
721 unsigned char buf
[sizeof(unsigned long)+1];
723 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
725 if ((buf
[0] & _B_CODE
) == _B_SINT
)
726 (*value
) = (buf
[0] & _B_VALUE
);
729 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), value
);
736 objc_read_string (struct objc_typed_stream
* stream
,
739 unsigned char buf
[sizeof(unsigned int)+1];
741 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
743 unsigned long key
= 0;
745 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
747 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
748 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
751 switch (buf
[0]&_B_CODE
) {
754 int length
= buf
[0]&_B_VALUE
;
755 (*string
) = (char*)objc_malloc(length
+1);
757 hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
758 len
= (*stream
->read
)(stream
->physical
, *string
, length
);
759 (*string
)[length
] = '\0';
766 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
767 tmp
= hash_value_for_key (stream
->stream_table
, LONG2PTR (key
));
768 *string
= objc_malloc (strlen(tmp
) + 1);
769 strcpy (*string
, tmp
);
775 unsigned int nbytes
= buf
[0]&_B_VALUE
;
776 len
= __objc_read_nbyte_uint(stream
, nbytes
, &nbytes
);
778 (*string
) = (char*)objc_malloc(nbytes
+1);
780 hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
781 len
= (*stream
->read
)(stream
->physical
, *string
, nbytes
);
782 (*string
)[nbytes
] = '\0';
788 objc_error(nil
, OBJC_ERR_BAD_DATA
,
789 "expected string, got opcode %c\n", (buf
[0]&_B_CODE
));
798 objc_read_object (struct objc_typed_stream
* stream
, id
* object
)
800 unsigned char buf
[sizeof (unsigned int)];
802 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
804 SEL read_sel
= sel_get_any_uid ("read:");
805 unsigned long key
= 0;
807 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register common */
809 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
810 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
813 if (buf
[0] == (_B_EXT
| _BX_OBJECT
))
818 len
= objc_read_class (stream
, &class);
820 /* create instance */
821 (*object
) = class_create_instance(class);
825 hash_add (&stream
->object_table
, LONG2PTR(key
), *object
);
828 if (__objc_responds_to (*object
, read_sel
))
829 (*get_imp(class, read_sel
))(*object
, read_sel
, stream
);
831 /* check null-byte */
832 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
834 objc_error(nil
, OBJC_ERR_BAD_DATA
,
835 "expected null-byte, got opcode %c", buf
[0]);
838 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
841 objc_error(nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
842 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
843 (*object
) = hash_value_for_key (stream
->object_table
, LONG2PTR(key
));
846 else if (buf
[0] == (_B_EXT
| _BX_OBJREF
)) /* a forward reference */
848 struct objc_list
* other
;
849 len
= objc_read_unsigned_long (stream
, &key
);
850 other
= (struct objc_list
*)hash_value_for_key (stream
->object_refs
,
852 hash_add (&stream
->object_refs
, LONG2PTR(key
),
853 (void*)list_cons(object
, other
));
856 else if (buf
[0] == (_B_EXT
| _BX_OBJROOT
)) /* a root object */
859 objc_error(nil
, OBJC_ERR_BAD_KEY
,
860 "cannot register root object...");
861 len
= objc_read_object (stream
, object
);
862 __objc_finish_read_root_object (stream
);
866 objc_error(nil
, OBJC_ERR_BAD_DATA
,
867 "expected object, got opcode %c", buf
[0]);
873 objc_read_class (struct objc_typed_stream
* stream
, Class
* class)
875 unsigned char buf
[sizeof (unsigned int)];
877 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
879 unsigned long key
= 0;
881 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
883 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
884 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
887 if (buf
[0] == (_B_EXT
| _BX_CLASS
))
890 unsigned long version
;
893 len
= objc_read_string (stream
, &class_name
);
894 (*class) = objc_get_class(class_name
);
895 objc_free(class_name
);
899 hash_add (&stream
->stream_table
, LONG2PTR(key
), *class);
901 objc_read_unsigned_long(stream
, &version
);
902 hash_add (&stream
->class_table
, (*class)->name
, (void*)version
);
905 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
908 objc_error(nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
909 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
910 (*class) = hash_value_for_key (stream
->stream_table
, LONG2PTR(key
));
912 objc_error(nil
, OBJC_ERR_BAD_CLASS
,
913 "cannot find class for key %lu", key
);
917 objc_error(nil
, OBJC_ERR_BAD_DATA
,
918 "expected class, got opcode %c", buf
[0]);
924 objc_read_selector (struct objc_typed_stream
* stream
, SEL
* selector
)
926 unsigned char buf
[sizeof (unsigned int)];
928 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
930 unsigned long key
= 0;
932 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
934 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
935 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
938 if (buf
[0] == (_B_EXT
|_BX_SEL
)) /* selector! */
943 len
= objc_read_string (stream
, &selector_name
);
944 /* To handle NULL selectors */
945 if (0 == strlen(selector_name
))
947 (*selector
) = (SEL
)0;
951 (*selector
) = sel_get_any_uid(selector_name
);
952 objc_free(selector_name
);
956 hash_add (&stream
->stream_table
, LONG2PTR(key
), (void*)*selector
);
959 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
962 objc_error(nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
963 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
964 (*selector
) = hash_value_for_key (stream
->stream_table
,
969 objc_error(nil
, OBJC_ERR_BAD_DATA
,
970 "expected selector, got opcode %c", buf
[0]);
976 ** USER LEVEL FUNCTIONS
980 ** Write one object, encoded in TYPE and pointed to by DATA to the
981 ** typed stream STREAM.
985 objc_write_type(TypedStream
* stream
, const char* type
, const void* data
)
989 return objc_write_object (stream
, *(id
*)data
);
993 return objc_write_class (stream
, *(Class
*)data
);
997 return objc_write_selector (stream
, *(SEL
*)data
);
1001 return objc_write_char(stream
, *(char*)data
);
1005 return objc_write_unsigned_char(stream
, *(unsigned char*)data
);
1009 return objc_write_short(stream
, *(short*)data
);
1013 return objc_write_unsigned_short(stream
, *(unsigned short*)data
);
1017 return objc_write_int(stream
, *(int*)data
);
1021 return objc_write_unsigned_int(stream
, *(unsigned int*)data
);
1025 return objc_write_long(stream
, *(long*)data
);
1029 return objc_write_unsigned_long(stream
, *(unsigned long*)data
);
1033 return objc_write_string (stream
, *(char**)data
, strlen(*(char**)data
));
1037 return objc_write_string_atomic (stream
, *(char**)data
,
1038 strlen(*(char**)data
));
1043 int len
= atoi(type
+1);
1044 while (isdigit(*++type
))
1046 return objc_write_array (stream
, type
, len
, data
);
1054 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1055 ; /* skip "<name>=" */
1056 while (*type
!= _C_STRUCT_E
)
1058 align
= objc_alignof_type (type
); /* padd to alignment */
1059 acc_size
+= ROUND (acc_size
, align
);
1060 objc_write_type (stream
, type
, ((char*)data
)+acc_size
);
1061 acc_size
+= objc_sizeof_type (type
); /* add component size */
1062 type
= objc_skip_typespec (type
); /* skip component */
1068 objc_error(nil
, OBJC_ERR_BAD_TYPE
,
1069 "objc_write_type: cannot parse typespec: %s\n", type
);
1074 ** Read one object, encoded in TYPE and pointed to by DATA to the
1075 ** typed stream STREAM. DATA specifies the address of the types to
1076 ** read. Expected type is checked against the type actually present
1081 objc_read_type(TypedStream
* stream
, const char* type
, void* data
)
1086 return objc_read_object (stream
, (id
*)data
);
1090 return objc_read_class (stream
, (Class
*)data
);
1094 return objc_read_selector (stream
, (SEL
*)data
);
1098 return objc_read_char (stream
, (char*)data
);
1102 return objc_read_unsigned_char (stream
, (unsigned char*)data
);
1106 return objc_read_short (stream
, (short*)data
);
1110 return objc_read_unsigned_short (stream
, (unsigned short*)data
);
1114 return objc_read_int (stream
, (int*)data
);
1118 return objc_read_unsigned_int (stream
, (unsigned int*)data
);
1122 return objc_read_long (stream
, (long*)data
);
1126 return objc_read_unsigned_long (stream
, (unsigned long*)data
);
1131 return objc_read_string (stream
, (char**)data
);
1136 int len
= atoi(type
+1);
1137 while (isdigit(*++type
))
1139 return objc_read_array (stream
, type
, len
, data
);
1147 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1148 ; /* skip "<name>=" */
1149 while (*type
!= _C_STRUCT_E
)
1151 align
= objc_alignof_type (type
); /* padd to alignment */
1152 acc_size
+= ROUND (acc_size
, align
);
1153 objc_read_type (stream
, type
, ((char*)data
)+acc_size
);
1154 acc_size
+= objc_sizeof_type (type
); /* add component size */
1155 type
= objc_skip_typespec (type
); /* skip component */
1161 objc_error(nil
, OBJC_ERR_BAD_TYPE
,
1162 "objc_read_type: cannot parse typespec: %s\n", type
);
1167 ** Write the object specified by the template TYPE to STREAM. Last
1168 ** arguments specify addresses of values to be written. It might
1169 ** seem surprising to specify values by address, but this is extremely
1170 ** convenient for copy-paste with objc_read_types calls. A more
1171 ** down-to-the-earth cause for this passing of addresses is that values
1172 ** of arbitrary size is not well supported in ANSI C for functions with
1173 ** variable number of arguments.
1177 objc_write_types (TypedStream
* stream
, const char* type
, ...)
1183 va_start(args
, type
);
1185 for (c
= type
; *c
; c
= objc_skip_typespec (c
))
1189 res
= objc_write_object (stream
, *va_arg (args
, id
*));
1193 res
= objc_write_class (stream
, *va_arg(args
, Class
*));
1197 res
= objc_write_selector (stream
, *va_arg(args
, SEL
*));
1201 res
= objc_write_char (stream
, *va_arg (args
, char*));
1205 res
= objc_write_unsigned_char (stream
,
1206 *va_arg (args
, unsigned char*));
1210 res
= objc_write_short (stream
, *va_arg(args
, short*));
1214 res
= objc_write_unsigned_short (stream
,
1215 *va_arg(args
, unsigned short*));
1219 res
= objc_write_int(stream
, *va_arg(args
, int*));
1223 res
= objc_write_unsigned_int(stream
, *va_arg(args
, unsigned int*));
1227 res
= objc_write_long(stream
, *va_arg(args
, long*));
1231 res
= objc_write_unsigned_long(stream
, *va_arg(args
, unsigned long*));
1236 char** str
= va_arg(args
, char**);
1237 res
= objc_write_string (stream
, *str
, strlen(*str
));
1243 char** str
= va_arg(args
, char**);
1244 res
= objc_write_string_atomic (stream
, *str
, strlen(*str
));
1250 int len
= atoi(c
+1);
1252 while (isdigit(*++t
))
1254 res
= objc_write_array (stream
, t
, len
, va_arg(args
, void*));
1255 t
= objc_skip_typespec (t
);
1257 objc_error(nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1262 objc_error(nil
, OBJC_ERR_BAD_TYPE
,
1263 "objc_write_types: cannot parse typespec: %s\n", type
);
1272 ** Last arguments specify addresses of values to be read. Expected
1273 ** type is checked against the type actually present on the stream.
1277 objc_read_types(TypedStream
* stream
, const char* type
, ...)
1283 va_start(args
, type
);
1285 for (c
= type
; *c
; c
= objc_skip_typespec(c
))
1289 res
= objc_read_object(stream
, va_arg(args
, id
*));
1293 res
= objc_read_class(stream
, va_arg(args
, Class
*));
1297 res
= objc_read_selector(stream
, va_arg(args
, SEL
*));
1301 res
= objc_read_char(stream
, va_arg(args
, char*));
1305 res
= objc_read_unsigned_char(stream
, va_arg(args
, unsigned char*));
1309 res
= objc_read_short(stream
, va_arg(args
, short*));
1313 res
= objc_read_unsigned_short(stream
, va_arg(args
, unsigned short*));
1317 res
= objc_read_int(stream
, va_arg(args
, int*));
1321 res
= objc_read_unsigned_int(stream
, va_arg(args
, unsigned int*));
1325 res
= objc_read_long(stream
, va_arg(args
, long*));
1329 res
= objc_read_unsigned_long(stream
, va_arg(args
, unsigned long*));
1335 char** str
= va_arg(args
, char**);
1336 res
= objc_read_string (stream
, str
);
1342 int len
= atoi(c
+1);
1344 while (isdigit(*++t
))
1346 res
= objc_read_array (stream
, t
, len
, va_arg(args
, void*));
1347 t
= objc_skip_typespec (t
);
1349 objc_error(nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1354 objc_error(nil
, OBJC_ERR_BAD_TYPE
,
1355 "objc_read_types: cannot parse typespec: %s\n", type
);
1363 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1364 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1368 objc_write_array (TypedStream
* stream
, const char* type
,
1369 int count
, const void* data
)
1371 int off
= objc_sizeof_type(type
);
1372 const char* where
= data
;
1376 objc_write_type(stream
, type
, where
);
1383 ** Read an array of COUNT elements of TYPE into the memory address
1384 ** DATA. The memory pointed to by data is supposed to be allocated
1385 ** by the callee. This is equivalent of
1386 ** objc_read_type (stream, "[N<type>]", data)
1390 objc_read_array (TypedStream
* stream
, const char* type
,
1391 int count
, void* data
)
1393 int off
= objc_sizeof_type(type
);
1394 char* where
= (char*)data
;
1398 objc_read_type(stream
, type
, where
);
1405 __objc_fread(FILE* file
, char* data
, int len
)
1407 return fread(data
, len
, 1, file
);
1411 __objc_fwrite(FILE* file
, char* data
, int len
)
1413 return fwrite(data
, len
, 1, file
);
1417 __objc_feof(FILE* file
)
1423 __objc_no_write(FILE* file
, char* data
, int len
)
1425 objc_error (nil
, OBJC_ERR_NO_WRITE
, "TypedStream not open for writing");
1429 __objc_no_read(FILE* file
, char* data
, int len
)
1431 objc_error (nil
, OBJC_ERR_NO_READ
, "TypedStream not open for reading");
1435 __objc_read_typed_stream_signature (TypedStream
* stream
)
1440 (*stream
->read
)(stream
->physical
, buffer
+pos
, 1);
1441 while (buffer
[pos
++] != '\0')
1443 sscanf (buffer
, "GNU TypedStream %d", &stream
->version
);
1444 if (stream
->version
!= OBJC_TYPED_STREAM_VERSION
)
1445 objc_error (nil
, OBJC_ERR_STREAM_VERSION
,
1446 "cannot handle TypedStream version %d", stream
->version
);
1451 __objc_write_typed_stream_signature (TypedStream
* stream
)
1454 sprintf(buffer
, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION
);
1455 stream
->version
= OBJC_TYPED_STREAM_VERSION
;
1456 (*stream
->write
)(stream
->physical
, buffer
, strlen(buffer
)+1);
1460 static void __objc_finish_write_root_object(struct objc_typed_stream
* stream
)
1462 hash_delete (stream
->object_table
);
1463 stream
->object_table
= hash_new(64,
1464 (hash_func_type
)hash_ptr
,
1465 (compare_func_type
)compare_ptrs
);
1468 static void __objc_finish_read_root_object(struct objc_typed_stream
* stream
)
1471 SEL awake_sel
= sel_get_any_uid ("awake");
1472 cache_ptr free_list
= hash_new (64,
1473 (hash_func_type
) hash_ptr
,
1474 (compare_func_type
) compare_ptrs
);
1476 /* resolve object forward references */
1477 for (node
= hash_next (stream
->object_refs
, NULL
); node
;
1478 node
= hash_next (stream
->object_refs
, node
))
1480 struct objc_list
* reflist
= node
->value
;
1481 const void* key
= node
->key
;
1482 id object
= hash_value_for_key (stream
->object_table
, key
);
1485 *((id
*)reflist
->head
) = object
;
1486 if (hash_value_for_key (free_list
,reflist
) == NULL
)
1487 hash_add (&free_list
,reflist
,reflist
);
1489 reflist
= reflist
->tail
;
1493 /* apply __objc_free to all objects stored in free_list */
1494 for (node
= hash_next (free_list
, NULL
); node
;
1495 node
= hash_next (free_list
, node
))
1496 objc_free ((void *) node
->key
);
1498 hash_delete (free_list
);
1500 /* empty object reference table */
1501 hash_delete (stream
->object_refs
);
1502 stream
->object_refs
= hash_new(8, (hash_func_type
)hash_ptr
,
1503 (compare_func_type
)compare_ptrs
);
1505 /* call -awake for all objects read */
1508 for (node
= hash_next (stream
->object_table
, NULL
); node
;
1509 node
= hash_next (stream
->object_table
, node
))
1511 id object
= node
->value
;
1512 if (__objc_responds_to (object
, awake_sel
))
1513 (*objc_msg_lookup(object
, awake_sel
))(object
, awake_sel
);
1517 /* empty object table */
1518 hash_delete (stream
->object_table
);
1519 stream
->object_table
= hash_new(64,
1520 (hash_func_type
)hash_ptr
,
1521 (compare_func_type
)compare_ptrs
);
1525 ** Open the stream PHYSICAL in MODE
1529 objc_open_typed_stream (FILE* physical
, int mode
)
1531 TypedStream
* s
= (TypedStream
*)objc_malloc(sizeof(TypedStream
));
1534 s
->physical
= physical
;
1535 s
->stream_table
= hash_new(64,
1536 (hash_func_type
)hash_ptr
,
1537 (compare_func_type
)compare_ptrs
);
1538 s
->object_table
= hash_new(64,
1539 (hash_func_type
)hash_ptr
,
1540 (compare_func_type
)compare_ptrs
);
1541 s
->eof
= (objc_typed_eof_func
)__objc_feof
;
1542 s
->flush
= (objc_typed_flush_func
)fflush
;
1543 s
->writing_root_p
= 0;
1544 if (mode
== OBJC_READONLY
)
1546 s
->class_table
= hash_new(8, (hash_func_type
)hash_string
,
1547 (compare_func_type
)compare_strings
);
1548 s
->object_refs
= hash_new(8, (hash_func_type
)hash_ptr
,
1549 (compare_func_type
)compare_ptrs
);
1550 s
->read
= (objc_typed_read_func
)__objc_fread
;
1551 s
->write
= (objc_typed_write_func
)__objc_no_write
;
1552 __objc_read_typed_stream_signature (s
);
1554 else if (mode
== OBJC_WRITEONLY
)
1558 s
->read
= (objc_typed_read_func
)__objc_no_read
;
1559 s
->write
= (objc_typed_write_func
)__objc_fwrite
;
1560 __objc_write_typed_stream_signature (s
);
1564 objc_close_typed_stream (s
);
1567 s
->type
= OBJC_FILE_STREAM
;
1572 ** Open the file named by FILE_NAME in MODE
1576 objc_open_typed_stream_for_file (const char* file_name
, int mode
)
1581 if (mode
== OBJC_READONLY
)
1582 file
= fopen (file_name
, "r");
1584 file
= fopen (file_name
, "w");
1588 s
= objc_open_typed_stream (file
, mode
);
1590 s
->type
|= OBJC_MANAGED_STREAM
;
1598 ** Close STREAM freeing the structure it self. If it was opened with
1599 ** objc_open_typed_stream_for_file, the file will also be closed.
1603 objc_close_typed_stream (TypedStream
* stream
)
1605 if (stream
->mode
== OBJC_READONLY
)
1607 __objc_finish_read_root_object (stream
); /* Just in case... */
1608 hash_delete (stream
->class_table
);
1609 hash_delete (stream
->object_refs
);
1612 hash_delete (stream
->stream_table
);
1613 hash_delete (stream
->object_table
);
1615 if (stream
->type
== (OBJC_MANAGED_STREAM
| OBJC_FILE_STREAM
))
1616 fclose ((FILE*)stream
->physical
);
1622 objc_end_of_typed_stream (TypedStream
* stream
)
1624 return (*stream
->eof
)(stream
->physical
);
1628 objc_flush_typed_stream (TypedStream
* stream
)
1630 (*stream
->flush
)(stream
->physical
);
1634 objc_get_stream_class_version (TypedStream
* stream
, Class
class)
1636 if (stream
->class_table
)
1637 return PTR2LONG(hash_value_for_key (stream
->class_table
, class->name
));
1639 return class_get_version (class);