1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009 Free Software Foundation, Inc.
3 Contributed by Kresten Krab Thorup
5 This file is part of GCC.
7 GCC 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 3, or (at your option) any later version.
11 GCC 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 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
26 #include "objc/runtime.h"
27 #include "objc/typedstream.h"
28 #include "objc/encoding.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
, (char*)buf
, len
);
89 __objc_code_char (unsigned char *buf
, signed 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
, signed char value
)
104 unsigned char buf
[sizeof (char) + 1];
105 int len
= __objc_code_char (buf
, value
);
106 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
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
, (char*)buf
, len
);
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
, (char*)buf
, len
);
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
, (char*)buf
, len
);
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
, (char*)buf
, len
);
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
, (char*)buf
, len
);
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
, (char*)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
, (char*)buf
, len
) != 0)
292 return (*stream
->write
) (stream
->physical
, (char*)string
, nbytes
);
298 objc_write_string_atomic (struct objc_typed_stream
*stream
,
299 unsigned char *string
, unsigned int nbytes
)
302 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
, string
))))
303 return objc_write_use_common (stream
, key
);
307 objc_hash_add (&stream
->stream_table
,
308 LONG2PTR(key
=PTR2LONG(string
)), string
);
309 if ((length
= objc_write_register_common (stream
, key
)))
310 return objc_write_string (stream
, string
, nbytes
);
316 objc_write_register_common (struct objc_typed_stream
*stream
,
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
, (char*)buf
, len
+ 1);
329 buf
[1] = (buf
[1]&_B_VALUE
)|_B_RCOMM
;
330 return (*stream
->write
) (stream
->physical
, (char*)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
, (char*)buf
, 2);
347 buf
[1] = (buf
[1]&_B_VALUE
)|_B_UCOMM
;
348 return (*stream
->write
) (stream
->physical
, (char*)buf
+ 1, len
);
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
, (char*)&buf
, 1);
362 objc_error (nil
, OBJC_ERR_BAD_OPCODE
,
363 "__objc_write_extension: bad opcode %c\n", code
);
369 __objc_write_object (struct objc_typed_stream
*stream
, id object
)
371 unsigned char buf
= '\0';
372 SEL write_sel
= sel_get_any_uid ("write:");
375 __objc_write_extension (stream
, _BX_OBJECT
);
376 objc_write_class (stream
, object
->class_pointer
);
377 (*objc_msg_lookup (object
, write_sel
)) (object
, write_sel
, stream
);
378 return (*stream
->write
) (stream
->physical
, (char*)&buf
, 1);
381 return objc_write_use_common (stream
, 0);
385 objc_write_object_reference (struct objc_typed_stream
*stream
, id object
)
388 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->object_table
, object
))))
389 return objc_write_use_common (stream
, key
);
391 __objc_write_extension (stream
, _BX_OBJREF
);
392 return objc_write_unsigned_long (stream
, PTR2LONG (object
));
396 objc_write_root_object (struct objc_typed_stream
*stream
, id object
)
399 if (stream
->writing_root_p
)
400 objc_error (nil
, OBJC_ERR_RECURSE_ROOT
,
401 "objc_write_root_object called recursively");
404 stream
->writing_root_p
= 1;
405 __objc_write_extension (stream
, _BX_OBJROOT
);
406 if ((len
= objc_write_object (stream
, object
)))
407 __objc_finish_write_root_object (stream
);
408 stream
->writing_root_p
= 0;
414 objc_write_object (struct objc_typed_stream
*stream
, id object
)
417 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->object_table
, object
))))
418 return objc_write_use_common (stream
, key
);
420 else if (object
== nil
)
421 return objc_write_use_common (stream
, 0);
426 objc_hash_add (&stream
->object_table
,
427 LONG2PTR(key
=PTR2LONG(object
)), object
);
428 if ((length
= objc_write_register_common (stream
, key
)))
429 return __objc_write_object (stream
, object
);
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
, (unsigned char *) class->name
,
439 strlen ((char *) class->name
));
440 return objc_write_unsigned_long (stream
, class->version
);
445 objc_write_class (struct objc_typed_stream
*stream
,
446 struct objc_class
*class)
449 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
, class))))
450 return objc_write_use_common (stream
, key
);
454 objc_hash_add (&stream
->stream_table
,
455 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
, (unsigned char*)"", 0);
471 sel_name
= sel_get_name (selector
);
472 return objc_write_string (stream
, (unsigned char*)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(objc_hash_value_for_key (stream
->stream_table
,
488 return objc_write_use_common (stream
, key
);
492 objc_hash_add (&stream
->stream_table
,
493 LONG2PTR(key
= PTR2LONG(sel_name
)), (char *) sel_name
);
494 if ((length
= objc_write_register_common (stream
, key
)))
495 return __objc_write_selector (stream
, selector
);
507 objc_read_char (struct objc_typed_stream
*stream
, char *val
)
511 len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1);
514 if ((buf
& _B_CODE
) == _B_SINT
)
515 (*val
) = (buf
& _B_VALUE
);
517 else if ((buf
& _B_NUMBER
) == 1)
519 len
= (*stream
->read
) (stream
->physical
, val
, 1);
521 (*val
) = -1 * (*val
);
525 objc_error (nil
, OBJC_ERR_BAD_DATA
,
526 "expected 8bit signed int, got %dbit int",
527 (int) (buf
&_B_NUMBER
)*8);
534 objc_read_unsigned_char (struct objc_typed_stream
*stream
, unsigned char *val
)
538 if ((len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1)))
540 if ((buf
& _B_CODE
) == _B_SINT
)
541 (*val
) = (buf
& _B_VALUE
);
543 else if ((buf
& _B_NUMBER
) == 1)
544 len
= (*stream
->read
) (stream
->physical
, (char*)val
, 1);
547 objc_error (nil
, OBJC_ERR_BAD_DATA
,
548 "expected 8bit unsigned int, got %dbit int",
549 (int) (buf
&_B_NUMBER
)*8);
555 objc_read_short (struct objc_typed_stream
*stream
, short *value
)
557 unsigned char buf
[sizeof (short) + 1];
559 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
561 if ((buf
[0] & _B_CODE
) == _B_SINT
)
562 (*value
) = (buf
[0] & _B_VALUE
);
567 int nbytes
= buf
[0] & _B_NUMBER
;
568 if (nbytes
> (int) sizeof (short))
569 objc_error (nil
, OBJC_ERR_BAD_DATA
,
570 "expected short, got bigger (%dbits)", nbytes
*8);
571 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
573 while (pos
<= nbytes
)
574 (*value
) = ((*value
)*0x100) + buf
[pos
++];
575 if (buf
[0] & _B_SIGN
)
576 (*value
) = -(*value
);
583 objc_read_unsigned_short (struct objc_typed_stream
*stream
,
584 unsigned short *value
)
586 unsigned char buf
[sizeof (unsigned short) + 1];
588 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
590 if ((buf
[0] & _B_CODE
) == _B_SINT
)
591 (*value
) = (buf
[0] & _B_VALUE
);
596 int nbytes
= buf
[0] & _B_NUMBER
;
597 if (nbytes
> (int) sizeof (short))
598 objc_error (nil
, OBJC_ERR_BAD_DATA
,
599 "expected short, got int or bigger");
600 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
602 while (pos
<= nbytes
)
603 (*value
) = ((*value
)*0x100) + buf
[pos
++];
611 objc_read_int (struct objc_typed_stream
*stream
, int *value
)
613 unsigned char buf
[sizeof (int) + 1];
615 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
617 if ((buf
[0] & _B_CODE
) == _B_SINT
)
618 (*value
) = (buf
[0] & _B_VALUE
);
623 int nbytes
= buf
[0] & _B_NUMBER
;
624 if (nbytes
> (int) sizeof (int))
625 objc_error (nil
, OBJC_ERR_BAD_DATA
, "expected int, got bigger");
626 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
628 while (pos
<= nbytes
)
629 (*value
) = ((*value
)*0x100) + buf
[pos
++];
630 if (buf
[0] & _B_SIGN
)
631 (*value
) = -(*value
);
638 objc_read_long (struct objc_typed_stream
*stream
, long *value
)
640 unsigned char buf
[sizeof (long) + 1];
642 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
644 if ((buf
[0] & _B_CODE
) == _B_SINT
)
645 (*value
) = (buf
[0] & _B_VALUE
);
650 int nbytes
= buf
[0] & _B_NUMBER
;
651 if (nbytes
> (int) sizeof (long))
652 objc_error (nil
, OBJC_ERR_BAD_DATA
, "expected long, got bigger");
653 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
655 while (pos
<= nbytes
)
656 (*value
) = ((*value
)*0x100) + buf
[pos
++];
657 if (buf
[0] & _B_SIGN
)
658 (*value
) = -(*value
);
665 __objc_read_nbyte_uint (struct objc_typed_stream
*stream
,
666 unsigned int nbytes
, unsigned int *val
)
669 unsigned int pos
= 0;
670 unsigned char buf
[sizeof (unsigned int) + 1];
672 if (nbytes
> sizeof (int))
673 objc_error (nil
, OBJC_ERR_BAD_DATA
, "expected int, got bigger");
675 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, nbytes
);
678 (*val
) = ((*val
)*0x100) + buf
[pos
++];
684 objc_read_unsigned_int (struct objc_typed_stream
*stream
,
687 unsigned char buf
[sizeof (unsigned int) + 1];
689 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
691 if ((buf
[0] & _B_CODE
) == _B_SINT
)
692 (*value
) = (buf
[0] & _B_VALUE
);
695 len
= __objc_read_nbyte_uint (stream
, (buf
[0] & _B_VALUE
), value
);
702 __objc_read_nbyte_ulong (struct objc_typed_stream
*stream
,
703 unsigned int nbytes
, unsigned long *val
)
706 unsigned int pos
= 0;
707 unsigned char buf
[sizeof (unsigned long) + 1];
709 if (nbytes
> sizeof (long))
710 objc_error (nil
, OBJC_ERR_BAD_DATA
, "expected long, got bigger");
712 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, nbytes
);
715 (*val
) = ((*val
)*0x100) + buf
[pos
++];
721 objc_read_unsigned_long (struct objc_typed_stream
*stream
,
722 unsigned long *value
)
724 unsigned char buf
[sizeof (unsigned long) + 1];
726 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
728 if ((buf
[0] & _B_CODE
) == _B_SINT
)
729 (*value
) = (buf
[0] & _B_VALUE
);
732 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), value
);
739 objc_read_string (struct objc_typed_stream
*stream
,
742 unsigned char buf
[sizeof (unsigned int) + 1];
744 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
746 unsigned long key
= 0;
748 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
750 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
751 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
754 switch (buf
[0]&_B_CODE
) {
757 int length
= buf
[0]&_B_VALUE
;
758 (*string
) = (char*)objc_malloc (length
+ 1);
760 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
761 len
= (*stream
->read
) (stream
->physical
, *string
, length
);
762 (*string
)[length
] = '\0';
769 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
770 tmp
= objc_hash_value_for_key (stream
->stream_table
, LONG2PTR (key
));
771 *string
= objc_malloc (strlen (tmp
) + 1);
772 strcpy (*string
, tmp
);
778 unsigned int nbytes
= buf
[0]&_B_VALUE
;
779 len
= __objc_read_nbyte_uint (stream
, nbytes
, &nbytes
);
781 (*string
) = (char*)objc_malloc (nbytes
+ 1);
783 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
784 len
= (*stream
->read
) (stream
->physical
, *string
, nbytes
);
785 (*string
)[nbytes
] = '\0';
791 objc_error (nil
, OBJC_ERR_BAD_DATA
,
792 "expected string, got opcode %c\n", (buf
[0]&_B_CODE
));
801 objc_read_object (struct objc_typed_stream
*stream
, id
*object
)
803 unsigned char buf
[sizeof (unsigned int)];
805 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
807 SEL read_sel
= sel_get_any_uid ("read:");
808 unsigned long key
= 0;
810 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register common */
812 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
813 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
816 if (buf
[0] == (_B_EXT
| _BX_OBJECT
))
821 len
= objc_read_class (stream
, &class);
823 /* create instance */
824 (*object
) = class_create_instance (class);
828 objc_hash_add (&stream
->object_table
, LONG2PTR(key
), *object
);
831 if (__objc_responds_to (*object
, read_sel
))
832 (*get_imp (class, read_sel
)) (*object
, read_sel
, stream
);
834 /* check null-byte */
835 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
837 objc_error (nil
, OBJC_ERR_BAD_DATA
,
838 "expected null-byte, got opcode %c", buf
[0]);
841 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
844 objc_error (nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
845 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
846 (*object
) = objc_hash_value_for_key (stream
->object_table
,
850 else if (buf
[0] == (_B_EXT
| _BX_OBJREF
)) /* a forward reference */
852 struct objc_list
*other
;
853 len
= objc_read_unsigned_long (stream
, &key
);
855 = (struct objc_list
*) objc_hash_value_for_key (stream
->object_refs
,
857 objc_hash_add (&stream
->object_refs
, LONG2PTR(key
),
858 (void *)list_cons (object
, other
));
861 else if (buf
[0] == (_B_EXT
| _BX_OBJROOT
)) /* a root object */
864 objc_error (nil
, OBJC_ERR_BAD_KEY
,
865 "cannot register root object...");
866 len
= objc_read_object (stream
, object
);
867 __objc_finish_read_root_object (stream
);
871 objc_error (nil
, OBJC_ERR_BAD_DATA
,
872 "expected object, got opcode %c", buf
[0]);
878 objc_read_class (struct objc_typed_stream
*stream
, Class
*class)
880 unsigned char buf
[sizeof (unsigned int)];
882 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
884 unsigned long key
= 0;
886 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
888 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
889 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
892 if (buf
[0] == (_B_EXT
| _BX_CLASS
))
895 char *class_name
= temp
;
896 unsigned long version
;
899 len
= objc_read_string (stream
, &class_name
);
900 (*class) = objc_get_class (class_name
);
901 objc_free (class_name
);
905 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *class);
907 objc_read_unsigned_long (stream
, &version
);
908 objc_hash_add (&stream
->class_table
,
909 (*class)->name
, (void *) ((size_t) version
));
912 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
915 objc_error (nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
916 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
917 *class = objc_hash_value_for_key (stream
->stream_table
,
920 objc_error (nil
, OBJC_ERR_BAD_CLASS
,
921 "cannot find class for key %lu", key
);
925 objc_error (nil
, OBJC_ERR_BAD_DATA
,
926 "expected class, got opcode %c", buf
[0]);
932 objc_read_selector (struct objc_typed_stream
*stream
, SEL
* selector
)
934 unsigned char buf
[sizeof (unsigned int)];
936 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
938 unsigned long key
= 0;
940 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
942 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
943 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
946 if (buf
[0] == (_B_EXT
|_BX_SEL
)) /* selector! */
949 char *selector_name
= temp
;
952 len
= objc_read_string (stream
, &selector_name
);
953 /* To handle NULL selectors */
954 if (0 == strlen (selector_name
))
956 (*selector
) = (SEL
)0;
960 (*selector
) = sel_get_any_uid (selector_name
);
961 objc_free (selector_name
);
965 objc_hash_add (&stream
->stream_table
,
966 LONG2PTR(key
), (void *) *selector
);
969 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
972 objc_error (nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
973 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
974 (*selector
) = objc_hash_value_for_key (stream
->stream_table
,
979 objc_error (nil
, OBJC_ERR_BAD_DATA
,
980 "expected selector, got opcode %c", buf
[0]);
986 ** USER LEVEL FUNCTIONS
990 ** Write one object, encoded in TYPE and pointed to by DATA to the
991 ** typed stream STREAM.
995 objc_write_type (TypedStream
*stream
, const char *type
, const void *data
)
999 return objc_write_object (stream
, *(id
*) data
);
1003 return objc_write_class (stream
, *(Class
*) data
);
1007 return objc_write_selector (stream
, *(SEL
*) data
);
1011 return objc_write_char (stream
, *(signed char *) data
);
1015 return objc_write_unsigned_char (stream
, *(unsigned char *) data
);
1019 return objc_write_short (stream
, *(short *) data
);
1023 return objc_write_unsigned_short (stream
, *(unsigned short *) data
);
1027 return objc_write_int (stream
, *(int *) data
);
1031 return objc_write_unsigned_int (stream
, *(unsigned int *) data
);
1035 return objc_write_long (stream
, *(long *) data
);
1039 return objc_write_unsigned_long (stream
, *(unsigned long *) data
);
1043 return objc_write_string (stream
,
1044 *(unsigned char **) data
, strlen (*(char **) data
));
1048 return objc_write_string_atomic (stream
, *(unsigned char **) data
,
1049 strlen (*(char **) data
));
1054 int len
= atoi (type
+ 1);
1055 while (isdigit ((unsigned char) *++type
))
1057 return objc_write_array (stream
, type
, len
, data
);
1065 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1066 ; /* skip "<name>=" */
1067 while (*type
!= _C_STRUCT_E
)
1069 align
= objc_alignof_type (type
); /* padd to alignment */
1070 acc_size
= ROUND (acc_size
, align
);
1071 objc_write_type (stream
, type
, ((char *) data
) + acc_size
);
1072 acc_size
+= objc_sizeof_type (type
); /* add component size */
1073 type
= objc_skip_typespec (type
); /* skip component */
1080 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1081 "objc_write_type: cannot parse typespec: %s\n", type
);
1088 ** Read one object, encoded in TYPE and pointed to by DATA to the
1089 ** typed stream STREAM. DATA specifies the address of the types to
1090 ** read. Expected type is checked against the type actually present
1095 objc_read_type(TypedStream
*stream
, const char *type
, void *data
)
1098 switch (c
= *type
) {
1100 return objc_read_object (stream
, (id
*)data
);
1104 return objc_read_class (stream
, (Class
*)data
);
1108 return objc_read_selector (stream
, (SEL
*)data
);
1112 return objc_read_char (stream
, (char*)data
);
1116 return objc_read_unsigned_char (stream
, (unsigned char*)data
);
1120 return objc_read_short (stream
, (short*)data
);
1124 return objc_read_unsigned_short (stream
, (unsigned short*)data
);
1128 return objc_read_int (stream
, (int*)data
);
1132 return objc_read_unsigned_int (stream
, (unsigned int*)data
);
1136 return objc_read_long (stream
, (long*)data
);
1140 return objc_read_unsigned_long (stream
, (unsigned long*)data
);
1145 return objc_read_string (stream
, (char**)data
);
1150 int len
= atoi (type
+ 1);
1151 while (isdigit ((unsigned char) *++type
))
1153 return objc_read_array (stream
, type
, len
, data
);
1161 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1162 ; /* skip "<name>=" */
1163 while (*type
!= _C_STRUCT_E
)
1165 align
= objc_alignof_type (type
); /* padd to alignment */
1166 acc_size
= ROUND (acc_size
, align
);
1167 objc_read_type (stream
, type
, ((char*)data
)+acc_size
);
1168 acc_size
+= objc_sizeof_type (type
); /* add component size */
1169 type
= objc_skip_typespec (type
); /* skip component */
1176 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1177 "objc_read_type: cannot parse typespec: %s\n", type
);
1184 ** Write the object specified by the template TYPE to STREAM. Last
1185 ** arguments specify addresses of values to be written. It might
1186 ** seem surprising to specify values by address, but this is extremely
1187 ** convenient for copy-paste with objc_read_types calls. A more
1188 ** down-to-the-earth cause for this passing of addresses is that values
1189 ** of arbitrary size is not well supported in ANSI C for functions with
1190 ** variable number of arguments.
1194 objc_write_types (TypedStream
*stream
, const char *type
, ...)
1200 va_start(args
, type
);
1202 for (c
= type
; *c
; c
= objc_skip_typespec (c
))
1206 res
= objc_write_object (stream
, *va_arg (args
, id
*));
1210 res
= objc_write_class (stream
, *va_arg (args
, Class
*));
1214 res
= objc_write_selector (stream
, *va_arg (args
, SEL
*));
1218 res
= objc_write_char (stream
, *va_arg (args
, char*));
1222 res
= objc_write_unsigned_char (stream
,
1223 *va_arg (args
, unsigned char*));
1227 res
= objc_write_short (stream
, *va_arg (args
, short*));
1231 res
= objc_write_unsigned_short (stream
,
1232 *va_arg (args
, unsigned short*));
1236 res
= objc_write_int(stream
, *va_arg (args
, int*));
1240 res
= objc_write_unsigned_int(stream
, *va_arg (args
, unsigned int*));
1244 res
= objc_write_long(stream
, *va_arg (args
, long*));
1248 res
= objc_write_unsigned_long(stream
, *va_arg (args
, unsigned long*));
1253 unsigned char **str
= va_arg (args
, unsigned char **);
1254 res
= objc_write_string (stream
, *str
, strlen ((char*)*str
));
1260 unsigned char **str
= va_arg (args
, unsigned char **);
1261 res
= objc_write_string_atomic (stream
, *str
, strlen ((char*)*str
));
1267 int len
= atoi (c
+ 1);
1269 while (isdigit ((unsigned char) *++t
))
1271 res
= objc_write_array (stream
, t
, len
, va_arg (args
, void *));
1272 t
= objc_skip_typespec (t
);
1274 objc_error (nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1279 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1280 "objc_write_types: cannot parse typespec: %s\n", type
);
1289 ** Last arguments specify addresses of values to be read. Expected
1290 ** type is checked against the type actually present on the stream.
1294 objc_read_types(TypedStream
*stream
, const char *type
, ...)
1300 va_start (args
, type
);
1302 for (c
= type
; *c
; c
= objc_skip_typespec(c
))
1306 res
= objc_read_object(stream
, va_arg (args
, id
*));
1310 res
= objc_read_class(stream
, va_arg (args
, Class
*));
1314 res
= objc_read_selector(stream
, va_arg (args
, SEL
*));
1318 res
= objc_read_char(stream
, va_arg (args
, char*));
1322 res
= objc_read_unsigned_char(stream
, va_arg (args
, unsigned char*));
1326 res
= objc_read_short(stream
, va_arg (args
, short*));
1330 res
= objc_read_unsigned_short(stream
, va_arg (args
, unsigned short*));
1334 res
= objc_read_int(stream
, va_arg (args
, int*));
1338 res
= objc_read_unsigned_int(stream
, va_arg (args
, unsigned int*));
1342 res
= objc_read_long(stream
, va_arg (args
, long*));
1346 res
= objc_read_unsigned_long(stream
, va_arg (args
, unsigned long*));
1352 char **str
= va_arg (args
, char **);
1353 res
= objc_read_string (stream
, str
);
1359 int len
= atoi (c
+ 1);
1361 while (isdigit ((unsigned char) *++t
))
1363 res
= objc_read_array (stream
, t
, len
, va_arg (args
, void *));
1364 t
= objc_skip_typespec (t
);
1366 objc_error (nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1371 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1372 "objc_read_types: cannot parse typespec: %s\n", type
);
1380 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1381 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1385 objc_write_array (TypedStream
*stream
, const char *type
,
1386 int count
, const void *data
)
1388 int off
= objc_sizeof_type(type
);
1389 const char *where
= data
;
1393 objc_write_type(stream
, type
, where
);
1400 ** Read an array of COUNT elements of TYPE into the memory address
1401 ** DATA. The memory pointed to by data is supposed to be allocated
1402 ** by the callee. This is equivalent of
1403 ** objc_read_type (stream, "[N<type>]", data)
1407 objc_read_array (TypedStream
*stream
, const char *type
,
1408 int count
, void *data
)
1410 int off
= objc_sizeof_type(type
);
1411 char *where
= (char*)data
;
1415 objc_read_type(stream
, type
, where
);
1422 __objc_fread (FILE *file
, char *data
, int len
)
1424 return fread(data
, len
, 1, file
);
1428 __objc_fwrite (FILE *file
, char *data
, int len
)
1430 return fwrite(data
, len
, 1, file
);
1434 __objc_feof (FILE *file
)
1440 __objc_no_write (FILE *file
__attribute__ ((__unused__
)),
1441 const char *data
__attribute__ ((__unused__
)),
1442 int len
__attribute__ ((__unused__
)))
1444 objc_error (nil
, OBJC_ERR_NO_WRITE
, "TypedStream not open for writing");
1449 __objc_no_read (FILE *file
__attribute__ ((__unused__
)),
1450 const char *data
__attribute__ ((__unused__
)),
1451 int len
__attribute__ ((__unused__
)))
1453 objc_error (nil
, OBJC_ERR_NO_READ
, "TypedStream not open for reading");
1458 __objc_read_typed_stream_signature (TypedStream
*stream
)
1463 (*stream
->read
) (stream
->physical
, buffer
+pos
, 1);
1464 while (buffer
[pos
++] != '\0')
1466 sscanf (buffer
, "GNU TypedStream %d", &stream
->version
);
1467 if (stream
->version
!= OBJC_TYPED_STREAM_VERSION
)
1468 objc_error (nil
, OBJC_ERR_STREAM_VERSION
,
1469 "cannot handle TypedStream version %d", stream
->version
);
1474 __objc_write_typed_stream_signature (TypedStream
*stream
)
1477 sprintf(buffer
, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION
);
1478 stream
->version
= OBJC_TYPED_STREAM_VERSION
;
1479 (*stream
->write
) (stream
->physical
, buffer
, strlen (buffer
) + 1);
1483 static void __objc_finish_write_root_object(struct objc_typed_stream
*stream
)
1485 objc_hash_delete (stream
->object_table
);
1486 stream
->object_table
= objc_hash_new (64,
1487 (hash_func_type
) objc_hash_ptr
,
1488 (compare_func_type
) objc_compare_ptrs
);
1491 static void __objc_finish_read_root_object(struct objc_typed_stream
*stream
)
1494 SEL awake_sel
= sel_get_any_uid ("awake");
1495 cache_ptr free_list
= objc_hash_new (64,
1496 (hash_func_type
) objc_hash_ptr
,
1497 (compare_func_type
) objc_compare_ptrs
);
1499 /* resolve object forward references */
1500 for (node
= objc_hash_next (stream
->object_refs
, NULL
); node
;
1501 node
= objc_hash_next (stream
->object_refs
, node
))
1503 struct objc_list
*reflist
= node
->value
;
1504 const void *key
= node
->key
;
1505 id object
= objc_hash_value_for_key (stream
->object_table
, key
);
1508 *((id
*) reflist
->head
) = object
;
1509 if (objc_hash_value_for_key (free_list
,reflist
) == NULL
)
1510 objc_hash_add (&free_list
,reflist
,reflist
);
1512 reflist
= reflist
->tail
;
1516 /* apply __objc_free to all objects stored in free_list */
1517 for (node
= objc_hash_next (free_list
, NULL
); node
;
1518 node
= objc_hash_next (free_list
, node
))
1519 objc_free ((void *) node
->key
);
1521 objc_hash_delete (free_list
);
1523 /* empty object reference table */
1524 objc_hash_delete (stream
->object_refs
);
1525 stream
->object_refs
= objc_hash_new (8, (hash_func_type
) objc_hash_ptr
,
1526 (compare_func_type
) objc_compare_ptrs
);
1528 /* call -awake for all objects read */
1531 for (node
= objc_hash_next (stream
->object_table
, NULL
); node
;
1532 node
= objc_hash_next (stream
->object_table
, node
))
1534 id object
= node
->value
;
1535 if (__objc_responds_to (object
, awake_sel
))
1536 (*objc_msg_lookup (object
, awake_sel
)) (object
, awake_sel
);
1540 /* empty object table */
1541 objc_hash_delete (stream
->object_table
);
1542 stream
->object_table
= objc_hash_new(64,
1543 (hash_func_type
)objc_hash_ptr
,
1544 (compare_func_type
)objc_compare_ptrs
);
1548 ** Open the stream PHYSICAL in MODE
1552 objc_open_typed_stream (FILE *physical
, int mode
)
1554 TypedStream
*s
= (TypedStream
*) objc_malloc (sizeof (TypedStream
));
1557 s
->physical
= physical
;
1558 s
->stream_table
= objc_hash_new (64,
1559 (hash_func_type
) objc_hash_ptr
,
1560 (compare_func_type
) objc_compare_ptrs
);
1561 s
->object_table
= objc_hash_new (64,
1562 (hash_func_type
) objc_hash_ptr
,
1563 (compare_func_type
) objc_compare_ptrs
);
1564 s
->eof
= (objc_typed_eof_func
) __objc_feof
;
1565 s
->flush
= (objc_typed_flush_func
) fflush
;
1566 s
->writing_root_p
= 0;
1567 if (mode
== OBJC_READONLY
)
1570 = objc_hash_new (8, (hash_func_type
) objc_hash_string
,
1571 (compare_func_type
) objc_compare_strings
);
1572 s
->object_refs
= objc_hash_new (8, (hash_func_type
) objc_hash_ptr
,
1573 (compare_func_type
) objc_compare_ptrs
);
1574 s
->read
= (objc_typed_read_func
) __objc_fread
;
1575 s
->write
= (objc_typed_write_func
) __objc_no_write
;
1576 __objc_read_typed_stream_signature (s
);
1578 else if (mode
== OBJC_WRITEONLY
)
1582 s
->read
= (objc_typed_read_func
) __objc_no_read
;
1583 s
->write
= (objc_typed_write_func
) __objc_fwrite
;
1584 __objc_write_typed_stream_signature (s
);
1588 objc_close_typed_stream (s
);
1591 s
->type
= OBJC_FILE_STREAM
;
1596 ** Open the file named by FILE_NAME in MODE
1600 objc_open_typed_stream_for_file (const char *file_name
, int mode
)
1605 if (mode
== OBJC_READONLY
)
1606 file
= fopen (file_name
, "r");
1608 file
= fopen (file_name
, "w");
1612 s
= objc_open_typed_stream (file
, mode
);
1614 s
->type
|= OBJC_MANAGED_STREAM
;
1622 ** Close STREAM freeing the structure it self. If it was opened with
1623 ** objc_open_typed_stream_for_file, the file will also be closed.
1627 objc_close_typed_stream (TypedStream
*stream
)
1629 if (stream
->mode
== OBJC_READONLY
)
1631 __objc_finish_read_root_object (stream
); /* Just in case... */
1632 objc_hash_delete (stream
->class_table
);
1633 objc_hash_delete (stream
->object_refs
);
1636 objc_hash_delete (stream
->stream_table
);
1637 objc_hash_delete (stream
->object_table
);
1639 if (stream
->type
== (OBJC_MANAGED_STREAM
| OBJC_FILE_STREAM
))
1640 fclose ((FILE *)stream
->physical
);
1646 objc_end_of_typed_stream (TypedStream
*stream
)
1648 return (*stream
->eof
) (stream
->physical
);
1652 objc_flush_typed_stream (TypedStream
*stream
)
1654 (*stream
->flush
) (stream
->physical
);
1658 objc_get_stream_class_version (TypedStream
*stream
, Class
class)
1660 if (stream
->class_table
)
1661 return PTR2LONG(objc_hash_value_for_key (stream
->class_table
,
1664 return class_get_version (class);