1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009,
3 2010 Free Software Foundation, Inc.
4 Contributed by Kresten Krab Thorup
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 3, or (at your option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 /* This file is entirely deprecated and will be removed. */
28 #include "objc-private/common.h"
29 #include "objc-private/error.h"
31 #include "objc/objc-api.h"
32 #include "objc/hash.h"
33 #include "objc/objc-list.h"
34 #include "objc-private/runtime.h"
35 #include "objc/typedstream.h"
36 #include "objc/encoding.h"
39 extern int fflush (FILE *);
42 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
43 __a * ((__v + __a - 1)/__a); })
45 #define PTR2LONG(P) (((char *) (P))-(char *) 0)
46 #define LONG2PTR(L) (((char *) 0) + (L))
48 /* Declare some functions... */
51 objc_read_class (struct objc_typed_stream
*stream
, Class
*class);
53 int objc_sizeof_type (const char *type
);
56 objc_write_use_common (struct objc_typed_stream
*stream
, unsigned long key
);
59 objc_write_register_common (struct objc_typed_stream
*stream
,
63 objc_write_class (struct objc_typed_stream
*stream
,
64 struct objc_class
*class);
66 const char *objc_skip_type (const char *type
);
68 static void __objc_finish_write_root_object (struct objc_typed_stream
*);
69 static void __objc_finish_read_root_object (struct objc_typed_stream
*);
72 __objc_code_unsigned_char (unsigned char *buf
, unsigned char val
)
74 if ((val
&_B_VALUE
) == val
)
81 buf
[0] = _B_NINT
|0x01;
88 objc_write_unsigned_char (struct objc_typed_stream
*stream
,
91 unsigned char buf
[sizeof (unsigned char) + 1];
92 int len
= __objc_code_unsigned_char (buf
, value
);
93 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
97 __objc_code_char (unsigned char *buf
, signed char val
)
100 return __objc_code_unsigned_char (buf
, val
);
103 buf
[0] = _B_NINT
|_B_SIGN
|0x01;
110 objc_write_char (struct objc_typed_stream
*stream
, signed char value
)
112 unsigned char buf
[sizeof (char) + 1];
113 int len
= __objc_code_char (buf
, value
);
114 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
118 __objc_code_unsigned_short (unsigned char *buf
, unsigned short val
)
120 if ((val
&_B_VALUE
) == val
)
122 buf
[0] = val
|_B_SINT
;
131 for (c
= sizeof (short); c
!= 0; c
-= 1)
132 if (((val
>> (8*(c
- 1)))%0x100) != 0)
137 for (b
= 1; c
!= 0; c
--, b
++)
139 buf
[b
] = (val
>> (8*(c
- 1)))%0x100;
147 objc_write_unsigned_short (struct objc_typed_stream
*stream
,
148 unsigned short value
)
150 unsigned char buf
[sizeof (unsigned short) + 1];
151 int len
= __objc_code_unsigned_short (buf
, value
);
152 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
156 __objc_code_short (unsigned char *buf
, short val
)
158 int sign
= (val
< 0);
159 int size
= __objc_code_unsigned_short (buf
, sign
? -val
: val
);
166 objc_write_short (struct objc_typed_stream
*stream
, short value
)
168 unsigned char buf
[sizeof (short) + 1];
169 int len
= __objc_code_short (buf
, value
);
170 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
175 __objc_code_unsigned_int (unsigned char *buf
, unsigned int val
)
177 if ((val
&_B_VALUE
) == val
)
179 buf
[0] = val
|_B_SINT
;
188 for (c
= sizeof (int); c
!= 0; c
-= 1)
189 if (((val
>> (8*(c
- 1)))%0x100) != 0)
194 for (b
= 1; c
!= 0; c
--, b
++)
196 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
204 objc_write_unsigned_int (struct objc_typed_stream
*stream
, unsigned int value
)
206 unsigned char buf
[sizeof (unsigned int) + 1];
207 int len
= __objc_code_unsigned_int (buf
, value
);
208 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
212 __objc_code_int (unsigned char *buf
, int val
)
214 int sign
= (val
< 0);
215 int size
= __objc_code_unsigned_int (buf
, sign
? -val
: val
);
222 objc_write_int (struct objc_typed_stream
*stream
, int value
)
224 unsigned char buf
[sizeof (int) + 1];
225 int len
= __objc_code_int (buf
, value
);
226 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
230 __objc_code_unsigned_long (unsigned char *buf
, unsigned long val
)
232 if ((val
&_B_VALUE
) == val
)
234 buf
[0] = val
|_B_SINT
;
243 for (c
= sizeof (long); c
!= 0; c
-= 1)
244 if (((val
>> (8*(c
- 1)))%0x100) != 0)
249 for (b
= 1; c
!= 0; c
--, b
++)
251 buf
[b
] = (val
>> (8*(c
- 1)))%0x100;
259 objc_write_unsigned_long (struct objc_typed_stream
*stream
,
262 unsigned char buf
[sizeof (unsigned long) + 1];
263 int len
= __objc_code_unsigned_long (buf
, value
);
264 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
268 __objc_code_long (unsigned char *buf
, long val
)
270 int sign
= (val
< 0);
271 int size
= __objc_code_unsigned_long (buf
, sign
? -val
: val
);
278 objc_write_long (struct objc_typed_stream
*stream
, long value
)
280 unsigned char buf
[sizeof (long) + 1];
281 int len
= __objc_code_long (buf
, value
);
282 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
287 objc_write_string (struct objc_typed_stream
*stream
,
288 const unsigned char *string
, unsigned int nbytes
)
290 unsigned char buf
[sizeof (unsigned int) + 1];
291 int len
= __objc_code_unsigned_int (buf
, nbytes
);
293 if ((buf
[0]&_B_CODE
) == _B_SINT
)
294 buf
[0] = (buf
[0]&_B_VALUE
)|_B_SSTR
;
297 buf
[0] = (buf
[0]&_B_VALUE
)|_B_NSTR
;
299 if ((*stream
->write
) (stream
->physical
, (char*)buf
, len
) != 0)
300 return (*stream
->write
) (stream
->physical
, (char*)string
, nbytes
);
306 objc_write_string_atomic (struct objc_typed_stream
*stream
,
307 unsigned char *string
, unsigned int nbytes
)
310 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
, string
))))
311 return objc_write_use_common (stream
, key
);
315 objc_hash_add (&stream
->stream_table
,
316 LONG2PTR(key
=PTR2LONG(string
)), string
);
317 if ((length
= objc_write_register_common (stream
, key
)))
318 return objc_write_string (stream
, string
, nbytes
);
324 objc_write_register_common (struct objc_typed_stream
*stream
,
327 unsigned char buf
[sizeof (unsigned long)+2];
328 int len
= __objc_code_unsigned_long (buf
+ 1, key
);
331 buf
[0] = _B_RCOMM
|0x01;
333 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
+ 1);
337 buf
[1] = (buf
[1]&_B_VALUE
)|_B_RCOMM
;
338 return (*stream
->write
) (stream
->physical
, (char*)buf
+ 1, len
);
343 objc_write_use_common (struct objc_typed_stream
*stream
, unsigned long key
)
345 unsigned char buf
[sizeof (unsigned long)+2];
346 int len
= __objc_code_unsigned_long (buf
+ 1, key
);
349 buf
[0] = _B_UCOMM
|0x01;
351 return (*stream
->write
) (stream
->physical
, (char*)buf
, 2);
355 buf
[1] = (buf
[1]&_B_VALUE
)|_B_UCOMM
;
356 return (*stream
->write
) (stream
->physical
, (char*)buf
+ 1, len
);
361 __objc_write_extension (struct objc_typed_stream
*stream
, unsigned char code
)
363 if (code
<= _B_VALUE
)
365 unsigned char buf
= code
|_B_EXT
;
366 return (*stream
->write
) (stream
->physical
, (char*)&buf
, 1);
370 _objc_abort ("__objc_write_extension: bad opcode %c\n", code
);
376 __objc_write_object (struct objc_typed_stream
*stream
, id object
)
378 unsigned char buf
= '\0';
379 SEL write_sel
= sel_get_any_uid ("write:");
382 __objc_write_extension (stream
, _BX_OBJECT
);
383 objc_write_class (stream
, object
->class_pointer
);
384 (*objc_msg_lookup (object
, write_sel
)) (object
, write_sel
, stream
);
385 return (*stream
->write
) (stream
->physical
, (char*)&buf
, 1);
388 return objc_write_use_common (stream
, 0);
392 objc_write_object_reference (struct objc_typed_stream
*stream
, id object
)
395 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->object_table
, object
))))
396 return objc_write_use_common (stream
, key
);
398 __objc_write_extension (stream
, _BX_OBJREF
);
399 return objc_write_unsigned_long (stream
, PTR2LONG (object
));
403 objc_write_root_object (struct objc_typed_stream
*stream
, id object
)
406 if (stream
->writing_root_p
)
407 _objc_abort ("objc_write_root_object called recursively");
410 stream
->writing_root_p
= 1;
411 __objc_write_extension (stream
, _BX_OBJROOT
);
412 if ((len
= objc_write_object (stream
, object
)))
413 __objc_finish_write_root_object (stream
);
414 stream
->writing_root_p
= 0;
420 objc_write_object (struct objc_typed_stream
*stream
, id object
)
423 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->object_table
, object
))))
424 return objc_write_use_common (stream
, key
);
426 else if (object
== nil
)
427 return objc_write_use_common (stream
, 0);
432 objc_hash_add (&stream
->object_table
,
433 LONG2PTR(key
=PTR2LONG(object
)), object
);
434 if ((length
= objc_write_register_common (stream
, key
)))
435 return __objc_write_object (stream
, object
);
441 __objc_write_class (struct objc_typed_stream
*stream
, struct objc_class
*class)
443 __objc_write_extension (stream
, _BX_CLASS
);
444 objc_write_string_atomic (stream
, (unsigned char *) class->name
,
445 strlen ((char *) class->name
));
446 return objc_write_unsigned_long (stream
, class->version
);
451 objc_write_class (struct objc_typed_stream
*stream
,
452 struct objc_class
*class)
455 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
, class))))
456 return objc_write_use_common (stream
, key
);
460 objc_hash_add (&stream
->stream_table
,
461 LONG2PTR(key
= PTR2LONG(class)), class);
462 if ((length
= objc_write_register_common (stream
, key
)))
463 return __objc_write_class (stream
, class);
470 __objc_write_selector (struct objc_typed_stream
*stream
, SEL selector
)
472 const char *sel_name
;
473 __objc_write_extension (stream
, _BX_SEL
);
474 /* to handle NULL selectors */
475 if ((SEL
)0 == selector
)
476 return objc_write_string (stream
, (unsigned char*)"", 0);
477 sel_name
= sel_get_name (selector
);
478 return objc_write_string (stream
, (unsigned char*)sel_name
, strlen ((char*)sel_name
));
482 objc_write_selector (struct objc_typed_stream
*stream
, SEL selector
)
484 const char *sel_name
;
487 /* to handle NULL selectors */
488 if ((SEL
)0 == selector
)
489 return __objc_write_selector (stream
, selector
);
491 sel_name
= sel_get_name (selector
);
492 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
,
494 return objc_write_use_common (stream
, key
);
498 objc_hash_add (&stream
->stream_table
,
499 LONG2PTR(key
= PTR2LONG(sel_name
)), (char *) sel_name
);
500 if ((length
= objc_write_register_common (stream
, key
)))
501 return __objc_write_selector (stream
, selector
);
513 objc_read_char (struct objc_typed_stream
*stream
, char *val
)
517 len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1);
520 if ((buf
& _B_CODE
) == _B_SINT
)
521 (*val
) = (buf
& _B_VALUE
);
523 else if ((buf
& _B_NUMBER
) == 1)
525 len
= (*stream
->read
) (stream
->physical
, val
, 1);
527 (*val
) = -1 * (*val
);
531 _objc_abort ("expected 8bit signed int, got %dbit int",
532 (int) (buf
&_B_NUMBER
)*8);
539 objc_read_unsigned_char (struct objc_typed_stream
*stream
, unsigned char *val
)
543 if ((len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1)))
545 if ((buf
& _B_CODE
) == _B_SINT
)
546 (*val
) = (buf
& _B_VALUE
);
548 else if ((buf
& _B_NUMBER
) == 1)
549 len
= (*stream
->read
) (stream
->physical
, (char*)val
, 1);
552 _objc_abort ("expected 8bit unsigned int, got %dbit int",
553 (int) (buf
&_B_NUMBER
)*8);
559 objc_read_short (struct objc_typed_stream
*stream
, short *value
)
561 unsigned char buf
[sizeof (short) + 1];
563 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
565 if ((buf
[0] & _B_CODE
) == _B_SINT
)
566 (*value
) = (buf
[0] & _B_VALUE
);
571 int nbytes
= buf
[0] & _B_NUMBER
;
572 if (nbytes
> (int) sizeof (short))
573 _objc_abort ("expected short, got bigger (%dbits)", nbytes
*8);
574 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
576 while (pos
<= nbytes
)
577 (*value
) = ((*value
)*0x100) + buf
[pos
++];
578 if (buf
[0] & _B_SIGN
)
579 (*value
) = -(*value
);
586 objc_read_unsigned_short (struct objc_typed_stream
*stream
,
587 unsigned short *value
)
589 unsigned char buf
[sizeof (unsigned short) + 1];
591 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
593 if ((buf
[0] & _B_CODE
) == _B_SINT
)
594 (*value
) = (buf
[0] & _B_VALUE
);
599 int nbytes
= buf
[0] & _B_NUMBER
;
600 if (nbytes
> (int) sizeof (short))
601 _objc_abort ("expected short, got int or bigger");
602 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
604 while (pos
<= nbytes
)
605 (*value
) = ((*value
)*0x100) + buf
[pos
++];
613 objc_read_int (struct objc_typed_stream
*stream
, int *value
)
615 unsigned char buf
[sizeof (int) + 1];
617 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
619 if ((buf
[0] & _B_CODE
) == _B_SINT
)
620 (*value
) = (buf
[0] & _B_VALUE
);
625 int nbytes
= buf
[0] & _B_NUMBER
;
626 if (nbytes
> (int) sizeof (int))
627 _objc_abort ("expected int, got bigger");
628 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
630 while (pos
<= nbytes
)
631 (*value
) = ((*value
)*0x100) + buf
[pos
++];
632 if (buf
[0] & _B_SIGN
)
633 (*value
) = -(*value
);
640 objc_read_long (struct objc_typed_stream
*stream
, long *value
)
642 unsigned char buf
[sizeof (long) + 1];
644 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
646 if ((buf
[0] & _B_CODE
) == _B_SINT
)
647 (*value
) = (buf
[0] & _B_VALUE
);
652 int nbytes
= buf
[0] & _B_NUMBER
;
653 if (nbytes
> (int) sizeof (long))
654 _objc_abort ("expected long, got bigger");
655 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
657 while (pos
<= nbytes
)
658 (*value
) = ((*value
)*0x100) + buf
[pos
++];
659 if (buf
[0] & _B_SIGN
)
660 (*value
) = -(*value
);
667 __objc_read_nbyte_uint (struct objc_typed_stream
*stream
,
668 unsigned int nbytes
, unsigned int *val
)
671 unsigned int pos
= 0;
672 unsigned char buf
[sizeof (unsigned int) + 1];
674 if (nbytes
> sizeof (int))
675 _objc_abort ("expected int, got bigger");
677 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, nbytes
);
680 (*val
) = ((*val
)*0x100) + buf
[pos
++];
686 objc_read_unsigned_int (struct objc_typed_stream
*stream
,
689 unsigned char buf
[sizeof (unsigned int) + 1];
691 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
693 if ((buf
[0] & _B_CODE
) == _B_SINT
)
694 (*value
) = (buf
[0] & _B_VALUE
);
697 len
= __objc_read_nbyte_uint (stream
, (buf
[0] & _B_VALUE
), value
);
704 __objc_read_nbyte_ulong (struct objc_typed_stream
*stream
,
705 unsigned int nbytes
, unsigned long *val
)
708 unsigned int pos
= 0;
709 unsigned char buf
[sizeof (unsigned long) + 1];
711 if (nbytes
> sizeof (long))
712 _objc_abort ("expected long, got bigger");
714 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, nbytes
);
717 (*val
) = ((*val
)*0x100) + buf
[pos
++];
723 objc_read_unsigned_long (struct objc_typed_stream
*stream
,
724 unsigned long *value
)
726 unsigned char buf
[sizeof (unsigned long) + 1];
728 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
730 if ((buf
[0] & _B_CODE
) == _B_SINT
)
731 (*value
) = (buf
[0] & _B_VALUE
);
734 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), value
);
741 objc_read_string (struct objc_typed_stream
*stream
,
744 unsigned char buf
[sizeof (unsigned int) + 1];
746 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
748 unsigned long key
= 0;
750 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
752 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
753 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
756 switch (buf
[0]&_B_CODE
) {
759 int length
= buf
[0]&_B_VALUE
;
760 (*string
) = (char*)objc_malloc (length
+ 1);
762 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
763 len
= (*stream
->read
) (stream
->physical
, *string
, length
);
764 (*string
)[length
] = '\0';
771 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
772 tmp
= objc_hash_value_for_key (stream
->stream_table
, LONG2PTR (key
));
773 *string
= objc_malloc (strlen (tmp
) + 1);
774 strcpy (*string
, tmp
);
780 unsigned int nbytes
= buf
[0]&_B_VALUE
;
781 len
= __objc_read_nbyte_uint (stream
, nbytes
, &nbytes
);
783 (*string
) = (char*)objc_malloc (nbytes
+ 1);
785 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
786 len
= (*stream
->read
) (stream
->physical
, *string
, nbytes
);
787 (*string
)[nbytes
] = '\0';
793 _objc_abort ("expected string, got opcode %c\n", (buf
[0]&_B_CODE
));
802 objc_read_object (struct objc_typed_stream
*stream
, id
*object
)
804 unsigned char buf
[sizeof (unsigned int)];
806 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
808 SEL read_sel
= sel_get_any_uid ("read:");
809 unsigned long key
= 0;
811 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register common */
813 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
814 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
817 if (buf
[0] == (_B_EXT
| _BX_OBJECT
))
822 len
= objc_read_class (stream
, &class);
824 /* create instance */
825 (*object
) = class_create_instance (class);
829 objc_hash_add (&stream
->object_table
, LONG2PTR(key
), *object
);
832 if (__objc_responds_to (*object
, read_sel
))
833 (*get_imp (class, read_sel
)) (*object
, read_sel
, stream
);
835 /* check null-byte */
836 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
838 _objc_abort ("expected null-byte, got opcode %c", buf
[0]);
841 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
844 _objc_abort ("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_abort ("cannot register root object...");
865 len
= objc_read_object (stream
, object
);
866 __objc_finish_read_root_object (stream
);
870 _objc_abort ("expected object, got opcode %c", buf
[0]);
876 objc_read_class (struct objc_typed_stream
*stream
, Class
*class)
878 unsigned char buf
[sizeof (unsigned int)];
880 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
882 unsigned long key
= 0;
884 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
886 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
887 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
890 if (buf
[0] == (_B_EXT
| _BX_CLASS
))
893 char *class_name
= temp
;
894 unsigned long version
;
897 len
= objc_read_string (stream
, &class_name
);
898 (*class) = objc_get_class (class_name
);
899 objc_free (class_name
);
903 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *class);
905 objc_read_unsigned_long (stream
, &version
);
906 objc_hash_add (&stream
->class_table
,
907 (*class)->name
, (void *) ((size_t) version
));
910 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
913 _objc_abort ("cannot register use upcode...");
914 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
915 *class = objc_hash_value_for_key (stream
->stream_table
,
918 _objc_abort ("cannot find class for key %lu", key
);
922 _objc_abort ("expected class, got opcode %c", buf
[0]);
928 objc_read_selector (struct objc_typed_stream
*stream
, SEL
* selector
)
930 unsigned char buf
[sizeof (unsigned int)];
932 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
934 unsigned long key
= 0;
936 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
938 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
939 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
942 if (buf
[0] == (_B_EXT
|_BX_SEL
)) /* selector! */
945 char *selector_name
= temp
;
948 len
= objc_read_string (stream
, &selector_name
);
949 /* To handle NULL selectors */
950 if (0 == strlen (selector_name
))
952 (*selector
) = (SEL
)0;
956 (*selector
) = sel_get_any_uid (selector_name
);
957 objc_free (selector_name
);
961 objc_hash_add (&stream
->stream_table
,
962 LONG2PTR(key
), (void *) *selector
);
965 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
968 _objc_abort ("cannot register use upcode...");
969 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
970 (*selector
) = objc_hash_value_for_key (stream
->stream_table
,
975 _objc_abort ("expected selector, got opcode %c", buf
[0]);
981 ** USER LEVEL FUNCTIONS
985 ** Write one object, encoded in TYPE and pointed to by DATA to the
986 ** typed stream STREAM.
990 objc_write_type (TypedStream
*stream
, const char *type
, const void *data
)
994 return objc_write_object (stream
, *(id
*) data
);
998 return objc_write_class (stream
, *(Class
*) data
);
1002 return objc_write_selector (stream
, *(SEL
*) data
);
1006 return objc_write_char (stream
, *(signed char *) data
);
1010 return objc_write_unsigned_char (stream
, *(unsigned char *) data
);
1014 return objc_write_short (stream
, *(short *) data
);
1018 return objc_write_unsigned_short (stream
, *(unsigned short *) data
);
1022 return objc_write_int (stream
, *(int *) data
);
1026 return objc_write_unsigned_int (stream
, *(unsigned int *) data
);
1030 return objc_write_long (stream
, *(long *) data
);
1034 return objc_write_unsigned_long (stream
, *(unsigned long *) data
);
1038 return objc_write_string (stream
,
1039 *(unsigned char **) data
, strlen (*(char **) data
));
1043 return objc_write_string_atomic (stream
, *(unsigned char **) data
,
1044 strlen (*(char **) data
));
1049 int len
= atoi (type
+ 1);
1050 while (isdigit ((unsigned char) *++type
))
1052 return objc_write_array (stream
, type
, len
, data
);
1060 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1061 ; /* skip "<name>=" */
1062 while (*type
!= _C_STRUCT_E
)
1064 align
= objc_alignof_type (type
); /* padd to alignment */
1065 acc_size
= ROUND (acc_size
, align
);
1066 objc_write_type (stream
, type
, ((char *) data
) + acc_size
);
1067 acc_size
+= objc_sizeof_type (type
); /* add component size */
1068 type
= objc_skip_typespec (type
); /* skip component */
1075 _objc_abort ("objc_write_type: cannot parse typespec: %s\n", type
);
1082 ** Read one object, encoded in TYPE and pointed to by DATA to the
1083 ** typed stream STREAM. DATA specifies the address of the types to
1084 ** read. Expected type is checked against the type actually present
1089 objc_read_type(TypedStream
*stream
, const char *type
, void *data
)
1092 switch (c
= *type
) {
1094 return objc_read_object (stream
, (id
*)data
);
1098 return objc_read_class (stream
, (Class
*)data
);
1102 return objc_read_selector (stream
, (SEL
*)data
);
1106 return objc_read_char (stream
, (char*)data
);
1110 return objc_read_unsigned_char (stream
, (unsigned char*)data
);
1114 return objc_read_short (stream
, (short*)data
);
1118 return objc_read_unsigned_short (stream
, (unsigned short*)data
);
1122 return objc_read_int (stream
, (int*)data
);
1126 return objc_read_unsigned_int (stream
, (unsigned int*)data
);
1130 return objc_read_long (stream
, (long*)data
);
1134 return objc_read_unsigned_long (stream
, (unsigned long*)data
);
1139 return objc_read_string (stream
, (char**)data
);
1144 int len
= atoi (type
+ 1);
1145 while (isdigit ((unsigned char) *++type
))
1147 return objc_read_array (stream
, type
, len
, data
);
1155 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1156 ; /* skip "<name>=" */
1157 while (*type
!= _C_STRUCT_E
)
1159 align
= objc_alignof_type (type
); /* padd to alignment */
1160 acc_size
= ROUND (acc_size
, align
);
1161 objc_read_type (stream
, type
, ((char*)data
)+acc_size
);
1162 acc_size
+= objc_sizeof_type (type
); /* add component size */
1163 type
= objc_skip_typespec (type
); /* skip component */
1170 _objc_abort ("objc_read_type: cannot parse typespec: %s\n", type
);
1177 ** Write the object specified by the template TYPE to STREAM. Last
1178 ** arguments specify addresses of values to be written. It might
1179 ** seem surprising to specify values by address, but this is extremely
1180 ** convenient for copy-paste with objc_read_types calls. A more
1181 ** down-to-the-earth cause for this passing of addresses is that values
1182 ** of arbitrary size is not well supported in ANSI C for functions with
1183 ** variable number of arguments.
1187 objc_write_types (TypedStream
*stream
, const char *type
, ...)
1193 va_start(args
, type
);
1195 for (c
= type
; *c
; c
= objc_skip_typespec (c
))
1199 res
= objc_write_object (stream
, *va_arg (args
, id
*));
1203 res
= objc_write_class (stream
, *va_arg (args
, Class
*));
1207 res
= objc_write_selector (stream
, *va_arg (args
, SEL
*));
1211 res
= objc_write_char (stream
, *va_arg (args
, char*));
1215 res
= objc_write_unsigned_char (stream
,
1216 *va_arg (args
, unsigned char*));
1220 res
= objc_write_short (stream
, *va_arg (args
, short*));
1224 res
= objc_write_unsigned_short (stream
,
1225 *va_arg (args
, unsigned short*));
1229 res
= objc_write_int(stream
, *va_arg (args
, int*));
1233 res
= objc_write_unsigned_int(stream
, *va_arg (args
, unsigned int*));
1237 res
= objc_write_long(stream
, *va_arg (args
, long*));
1241 res
= objc_write_unsigned_long(stream
, *va_arg (args
, unsigned long*));
1246 unsigned char **str
= va_arg (args
, unsigned char **);
1247 res
= objc_write_string (stream
, *str
, strlen ((char*)*str
));
1253 unsigned char **str
= va_arg (args
, unsigned char **);
1254 res
= objc_write_string_atomic (stream
, *str
, strlen ((char*)*str
));
1260 int len
= atoi (c
+ 1);
1262 while (isdigit ((unsigned char) *++t
))
1264 res
= objc_write_array (stream
, t
, len
, va_arg (args
, void *));
1265 t
= objc_skip_typespec (t
);
1267 _objc_abort ("expected `]', got: %s", t
);
1272 _objc_abort ("objc_write_types: cannot parse typespec: %s\n", type
);
1281 ** Last arguments specify addresses of values to be read. Expected
1282 ** type is checked against the type actually present on the stream.
1286 objc_read_types(TypedStream
*stream
, const char *type
, ...)
1292 va_start (args
, type
);
1294 for (c
= type
; *c
; c
= objc_skip_typespec(c
))
1298 res
= objc_read_object(stream
, va_arg (args
, id
*));
1302 res
= objc_read_class(stream
, va_arg (args
, Class
*));
1306 res
= objc_read_selector(stream
, va_arg (args
, SEL
*));
1310 res
= objc_read_char(stream
, va_arg (args
, char*));
1314 res
= objc_read_unsigned_char(stream
, va_arg (args
, unsigned char*));
1318 res
= objc_read_short(stream
, va_arg (args
, short*));
1322 res
= objc_read_unsigned_short(stream
, va_arg (args
, unsigned short*));
1326 res
= objc_read_int(stream
, va_arg (args
, int*));
1330 res
= objc_read_unsigned_int(stream
, va_arg (args
, unsigned int*));
1334 res
= objc_read_long(stream
, va_arg (args
, long*));
1338 res
= objc_read_unsigned_long(stream
, va_arg (args
, unsigned long*));
1344 char **str
= va_arg (args
, char **);
1345 res
= objc_read_string (stream
, str
);
1351 int len
= atoi (c
+ 1);
1353 while (isdigit ((unsigned char) *++t
))
1355 res
= objc_read_array (stream
, t
, len
, va_arg (args
, void *));
1356 t
= objc_skip_typespec (t
);
1358 _objc_abort ("expected `]', got: %s", t
);
1363 _objc_abort ("objc_read_types: cannot parse typespec: %s\n", type
);
1371 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1372 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1376 objc_write_array (TypedStream
*stream
, const char *type
,
1377 int count
, const void *data
)
1379 int off
= objc_sizeof_type(type
);
1380 const char *where
= data
;
1384 objc_write_type(stream
, type
, where
);
1391 ** Read an array of COUNT elements of TYPE into the memory address
1392 ** DATA. The memory pointed to by data is supposed to be allocated
1393 ** by the callee. This is equivalent of
1394 ** objc_read_type (stream, "[N<type>]", data)
1398 objc_read_array (TypedStream
*stream
, const char *type
,
1399 int count
, void *data
)
1401 int off
= objc_sizeof_type(type
);
1402 char *where
= (char*)data
;
1406 objc_read_type(stream
, type
, where
);
1413 __objc_fread (FILE *file
, char *data
, int len
)
1415 return fread(data
, len
, 1, file
);
1419 __objc_fwrite (FILE *file
, char *data
, int len
)
1421 return fwrite(data
, len
, 1, file
);
1425 __objc_feof (FILE *file
)
1431 __objc_no_write (FILE *file
__attribute__ ((__unused__
)),
1432 const char *data
__attribute__ ((__unused__
)),
1433 int len
__attribute__ ((__unused__
)))
1435 _objc_abort ("TypedStream not open for writing");
1440 __objc_no_read (FILE *file
__attribute__ ((__unused__
)),
1441 const char *data
__attribute__ ((__unused__
)),
1442 int len
__attribute__ ((__unused__
)))
1444 _objc_abort ("TypedStream not open for reading");
1449 __objc_read_typed_stream_signature (TypedStream
*stream
)
1454 (*stream
->read
) (stream
->physical
, buffer
+pos
, 1);
1455 while (buffer
[pos
++] != '\0')
1457 sscanf (buffer
, "GNU TypedStream %d", &stream
->version
);
1458 if (stream
->version
!= OBJC_TYPED_STREAM_VERSION
)
1459 _objc_abort ("cannot handle TypedStream version %d", stream
->version
);
1464 __objc_write_typed_stream_signature (TypedStream
*stream
)
1467 sprintf(buffer
, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION
);
1468 stream
->version
= OBJC_TYPED_STREAM_VERSION
;
1469 (*stream
->write
) (stream
->physical
, buffer
, strlen (buffer
) + 1);
1473 static void __objc_finish_write_root_object(struct objc_typed_stream
*stream
)
1475 objc_hash_delete (stream
->object_table
);
1476 stream
->object_table
= objc_hash_new (64,
1477 (hash_func_type
) objc_hash_ptr
,
1478 (compare_func_type
) objc_compare_ptrs
);
1481 static void __objc_finish_read_root_object(struct objc_typed_stream
*stream
)
1484 SEL awake_sel
= sel_get_any_uid ("awake");
1485 cache_ptr free_list
= objc_hash_new (64,
1486 (hash_func_type
) objc_hash_ptr
,
1487 (compare_func_type
) objc_compare_ptrs
);
1489 /* resolve object forward references */
1490 for (node
= objc_hash_next (stream
->object_refs
, NULL
); node
;
1491 node
= objc_hash_next (stream
->object_refs
, node
))
1493 struct objc_list
*reflist
= node
->value
;
1494 const void *key
= node
->key
;
1495 id object
= objc_hash_value_for_key (stream
->object_table
, key
);
1498 *((id
*) reflist
->head
) = object
;
1499 if (objc_hash_value_for_key (free_list
,reflist
) == NULL
)
1500 objc_hash_add (&free_list
,reflist
,reflist
);
1502 reflist
= reflist
->tail
;
1506 /* apply __objc_free to all objects stored in free_list */
1507 for (node
= objc_hash_next (free_list
, NULL
); node
;
1508 node
= objc_hash_next (free_list
, node
))
1509 objc_free ((void *) node
->key
);
1511 objc_hash_delete (free_list
);
1513 /* empty object reference table */
1514 objc_hash_delete (stream
->object_refs
);
1515 stream
->object_refs
= objc_hash_new (8, (hash_func_type
) objc_hash_ptr
,
1516 (compare_func_type
) objc_compare_ptrs
);
1518 /* call -awake for all objects read */
1521 for (node
= objc_hash_next (stream
->object_table
, NULL
); node
;
1522 node
= objc_hash_next (stream
->object_table
, node
))
1524 id object
= node
->value
;
1525 if (__objc_responds_to (object
, awake_sel
))
1526 (*objc_msg_lookup (object
, awake_sel
)) (object
, awake_sel
);
1530 /* empty object table */
1531 objc_hash_delete (stream
->object_table
);
1532 stream
->object_table
= objc_hash_new(64,
1533 (hash_func_type
)objc_hash_ptr
,
1534 (compare_func_type
)objc_compare_ptrs
);
1538 ** Open the stream PHYSICAL in MODE
1542 objc_open_typed_stream (FILE *physical
, int mode
)
1544 TypedStream
*s
= (TypedStream
*) objc_malloc (sizeof (TypedStream
));
1547 s
->physical
= physical
;
1548 s
->stream_table
= objc_hash_new (64,
1549 (hash_func_type
) objc_hash_ptr
,
1550 (compare_func_type
) objc_compare_ptrs
);
1551 s
->object_table
= objc_hash_new (64,
1552 (hash_func_type
) objc_hash_ptr
,
1553 (compare_func_type
) objc_compare_ptrs
);
1554 s
->eof
= (objc_typed_eof_func
) __objc_feof
;
1555 s
->flush
= (objc_typed_flush_func
) fflush
;
1556 s
->writing_root_p
= 0;
1557 if (mode
== OBJC_READONLY
)
1560 = objc_hash_new (8, (hash_func_type
) objc_hash_string
,
1561 (compare_func_type
) objc_compare_strings
);
1562 s
->object_refs
= objc_hash_new (8, (hash_func_type
) objc_hash_ptr
,
1563 (compare_func_type
) objc_compare_ptrs
);
1564 s
->read
= (objc_typed_read_func
) __objc_fread
;
1565 s
->write
= (objc_typed_write_func
) __objc_no_write
;
1566 __objc_read_typed_stream_signature (s
);
1568 else if (mode
== OBJC_WRITEONLY
)
1572 s
->read
= (objc_typed_read_func
) __objc_no_read
;
1573 s
->write
= (objc_typed_write_func
) __objc_fwrite
;
1574 __objc_write_typed_stream_signature (s
);
1578 objc_close_typed_stream (s
);
1581 s
->type
= OBJC_FILE_STREAM
;
1586 ** Open the file named by FILE_NAME in MODE
1590 objc_open_typed_stream_for_file (const char *file_name
, int mode
)
1595 if (mode
== OBJC_READONLY
)
1596 file
= fopen (file_name
, "r");
1598 file
= fopen (file_name
, "w");
1602 s
= objc_open_typed_stream (file
, mode
);
1604 s
->type
|= OBJC_MANAGED_STREAM
;
1612 ** Close STREAM freeing the structure it self. If it was opened with
1613 ** objc_open_typed_stream_for_file, the file will also be closed.
1617 objc_close_typed_stream (TypedStream
*stream
)
1619 if (stream
->mode
== OBJC_READONLY
)
1621 __objc_finish_read_root_object (stream
); /* Just in case... */
1622 objc_hash_delete (stream
->class_table
);
1623 objc_hash_delete (stream
->object_refs
);
1626 objc_hash_delete (stream
->stream_table
);
1627 objc_hash_delete (stream
->object_table
);
1629 if (stream
->type
== (OBJC_MANAGED_STREAM
| OBJC_FILE_STREAM
))
1630 fclose ((FILE *)stream
->physical
);
1636 objc_end_of_typed_stream (TypedStream
*stream
)
1638 return (*stream
->eof
) (stream
->physical
);
1642 objc_flush_typed_stream (TypedStream
*stream
)
1644 (*stream
->flush
) (stream
->physical
);
1648 objc_get_stream_class_version (TypedStream
*stream
, Class
class)
1650 if (stream
->class_table
)
1651 return PTR2LONG(objc_hash_value_for_key (stream
->class_table
,
1654 return class_get_version (class);