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/>. */
25 /* This file is entirely deprecated and will be removed. */
27 #include "objc-private/common.h"
28 #include "objc-private/error.h"
30 #include "objc/objc-api.h"
31 #include "objc/hash.h"
32 #include "objc/objc-list.h"
33 #include "objc-private/runtime.h"
34 #include "objc/typedstream.h"
35 #include "objc/encoding.h"
38 extern int fflush (FILE *);
41 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
42 __a * ((__v + __a - 1)/__a); })
44 #define PTR2LONG(P) (((char *) (P))-(char *) 0)
45 #define LONG2PTR(L) (((char *) 0) + (L))
47 /* Declare some functions... */
50 objc_read_class (struct objc_typed_stream
*stream
, Class
*class);
52 int objc_sizeof_type (const char *type
);
55 objc_write_use_common (struct objc_typed_stream
*stream
, unsigned long key
);
58 objc_write_register_common (struct objc_typed_stream
*stream
,
62 objc_write_class (struct objc_typed_stream
*stream
,
63 struct objc_class
*class);
65 const char *objc_skip_type (const char *type
);
67 static void __objc_finish_write_root_object (struct objc_typed_stream
*);
68 static void __objc_finish_read_root_object (struct objc_typed_stream
*);
71 __objc_code_unsigned_char (unsigned char *buf
, unsigned char val
)
73 if ((val
&_B_VALUE
) == val
)
80 buf
[0] = _B_NINT
|0x01;
87 objc_write_unsigned_char (struct objc_typed_stream
*stream
,
90 unsigned char buf
[sizeof (unsigned char) + 1];
91 int len
= __objc_code_unsigned_char (buf
, value
);
92 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
96 __objc_code_char (unsigned char *buf
, signed char val
)
99 return __objc_code_unsigned_char (buf
, val
);
102 buf
[0] = _B_NINT
|_B_SIGN
|0x01;
109 objc_write_char (struct objc_typed_stream
*stream
, signed char value
)
111 unsigned char buf
[sizeof (char) + 1];
112 int len
= __objc_code_char (buf
, value
);
113 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
117 __objc_code_unsigned_short (unsigned char *buf
, unsigned short val
)
119 if ((val
&_B_VALUE
) == val
)
121 buf
[0] = val
|_B_SINT
;
130 for (c
= sizeof (short); c
!= 0; c
-= 1)
131 if (((val
>> (8*(c
- 1)))%0x100) != 0)
136 for (b
= 1; c
!= 0; c
--, b
++)
138 buf
[b
] = (val
>> (8*(c
- 1)))%0x100;
146 objc_write_unsigned_short (struct objc_typed_stream
*stream
,
147 unsigned short value
)
149 unsigned char buf
[sizeof (unsigned short) + 1];
150 int len
= __objc_code_unsigned_short (buf
, value
);
151 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
155 __objc_code_short (unsigned char *buf
, short val
)
157 int sign
= (val
< 0);
158 int size
= __objc_code_unsigned_short (buf
, sign
? -val
: val
);
165 objc_write_short (struct objc_typed_stream
*stream
, short value
)
167 unsigned char buf
[sizeof (short) + 1];
168 int len
= __objc_code_short (buf
, value
);
169 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
174 __objc_code_unsigned_int (unsigned char *buf
, unsigned int val
)
176 if ((val
&_B_VALUE
) == val
)
178 buf
[0] = val
|_B_SINT
;
187 for (c
= sizeof (int); c
!= 0; c
-= 1)
188 if (((val
>> (8*(c
- 1)))%0x100) != 0)
193 for (b
= 1; c
!= 0; c
--, b
++)
195 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
203 objc_write_unsigned_int (struct objc_typed_stream
*stream
, unsigned int value
)
205 unsigned char buf
[sizeof (unsigned int) + 1];
206 int len
= __objc_code_unsigned_int (buf
, value
);
207 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
211 __objc_code_int (unsigned char *buf
, int val
)
213 int sign
= (val
< 0);
214 int size
= __objc_code_unsigned_int (buf
, sign
? -val
: val
);
221 objc_write_int (struct objc_typed_stream
*stream
, int value
)
223 unsigned char buf
[sizeof (int) + 1];
224 int len
= __objc_code_int (buf
, value
);
225 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
229 __objc_code_unsigned_long (unsigned char *buf
, unsigned long val
)
231 if ((val
&_B_VALUE
) == val
)
233 buf
[0] = val
|_B_SINT
;
242 for (c
= sizeof (long); c
!= 0; c
-= 1)
243 if (((val
>> (8*(c
- 1)))%0x100) != 0)
248 for (b
= 1; c
!= 0; c
--, b
++)
250 buf
[b
] = (val
>> (8*(c
- 1)))%0x100;
258 objc_write_unsigned_long (struct objc_typed_stream
*stream
,
261 unsigned char buf
[sizeof (unsigned long) + 1];
262 int len
= __objc_code_unsigned_long (buf
, value
);
263 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
267 __objc_code_long (unsigned char *buf
, long val
)
269 int sign
= (val
< 0);
270 int size
= __objc_code_unsigned_long (buf
, sign
? -val
: val
);
277 objc_write_long (struct objc_typed_stream
*stream
, long value
)
279 unsigned char buf
[sizeof (long) + 1];
280 int len
= __objc_code_long (buf
, value
);
281 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
286 objc_write_string (struct objc_typed_stream
*stream
,
287 const unsigned char *string
, unsigned int nbytes
)
289 unsigned char buf
[sizeof (unsigned int) + 1];
290 int len
= __objc_code_unsigned_int (buf
, nbytes
);
292 if ((buf
[0]&_B_CODE
) == _B_SINT
)
293 buf
[0] = (buf
[0]&_B_VALUE
)|_B_SSTR
;
296 buf
[0] = (buf
[0]&_B_VALUE
)|_B_NSTR
;
298 if ((*stream
->write
) (stream
->physical
, (char*)buf
, len
) != 0)
299 return (*stream
->write
) (stream
->physical
, (char*)string
, nbytes
);
305 objc_write_string_atomic (struct objc_typed_stream
*stream
,
306 unsigned char *string
, unsigned int nbytes
)
309 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
, string
))))
310 return objc_write_use_common (stream
, key
);
314 objc_hash_add (&stream
->stream_table
,
315 LONG2PTR(key
=PTR2LONG(string
)), string
);
316 if ((length
= objc_write_register_common (stream
, key
)))
317 return objc_write_string (stream
, string
, nbytes
);
323 objc_write_register_common (struct objc_typed_stream
*stream
,
326 unsigned char buf
[sizeof (unsigned long)+2];
327 int len
= __objc_code_unsigned_long (buf
+ 1, key
);
330 buf
[0] = _B_RCOMM
|0x01;
332 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
+ 1);
336 buf
[1] = (buf
[1]&_B_VALUE
)|_B_RCOMM
;
337 return (*stream
->write
) (stream
->physical
, (char*)buf
+ 1, len
);
342 objc_write_use_common (struct objc_typed_stream
*stream
, unsigned long key
)
344 unsigned char buf
[sizeof (unsigned long)+2];
345 int len
= __objc_code_unsigned_long (buf
+ 1, key
);
348 buf
[0] = _B_UCOMM
|0x01;
350 return (*stream
->write
) (stream
->physical
, (char*)buf
, 2);
354 buf
[1] = (buf
[1]&_B_VALUE
)|_B_UCOMM
;
355 return (*stream
->write
) (stream
->physical
, (char*)buf
+ 1, len
);
360 __objc_write_extension (struct objc_typed_stream
*stream
, unsigned char code
)
362 if (code
<= _B_VALUE
)
364 unsigned char buf
= code
|_B_EXT
;
365 return (*stream
->write
) (stream
->physical
, (char*)&buf
, 1);
369 _objc_abort ("__objc_write_extension: bad opcode %c\n", code
);
375 __objc_write_object (struct objc_typed_stream
*stream
, id object
)
377 unsigned char buf
= '\0';
378 SEL write_sel
= sel_get_any_uid ("write:");
381 __objc_write_extension (stream
, _BX_OBJECT
);
382 objc_write_class (stream
, object
->class_pointer
);
383 (*objc_msg_lookup (object
, write_sel
)) (object
, write_sel
, stream
);
384 return (*stream
->write
) (stream
->physical
, (char*)&buf
, 1);
387 return objc_write_use_common (stream
, 0);
391 objc_write_object_reference (struct objc_typed_stream
*stream
, id object
)
394 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->object_table
, object
))))
395 return objc_write_use_common (stream
, key
);
397 __objc_write_extension (stream
, _BX_OBJREF
);
398 return objc_write_unsigned_long (stream
, PTR2LONG (object
));
402 objc_write_root_object (struct objc_typed_stream
*stream
, id object
)
405 if (stream
->writing_root_p
)
406 _objc_abort ("objc_write_root_object called recursively");
409 stream
->writing_root_p
= 1;
410 __objc_write_extension (stream
, _BX_OBJROOT
);
411 if ((len
= objc_write_object (stream
, object
)))
412 __objc_finish_write_root_object (stream
);
413 stream
->writing_root_p
= 0;
419 objc_write_object (struct objc_typed_stream
*stream
, id object
)
422 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->object_table
, object
))))
423 return objc_write_use_common (stream
, key
);
425 else if (object
== nil
)
426 return objc_write_use_common (stream
, 0);
431 objc_hash_add (&stream
->object_table
,
432 LONG2PTR(key
=PTR2LONG(object
)), object
);
433 if ((length
= objc_write_register_common (stream
, key
)))
434 return __objc_write_object (stream
, object
);
440 __objc_write_class (struct objc_typed_stream
*stream
, struct objc_class
*class)
442 __objc_write_extension (stream
, _BX_CLASS
);
443 objc_write_string_atomic (stream
, (unsigned char *) class->name
,
444 strlen ((char *) class->name
));
445 return objc_write_unsigned_long (stream
, class->version
);
450 objc_write_class (struct objc_typed_stream
*stream
,
451 struct objc_class
*class)
454 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
, class))))
455 return objc_write_use_common (stream
, key
);
459 objc_hash_add (&stream
->stream_table
,
460 LONG2PTR(key
= PTR2LONG(class)), class);
461 if ((length
= objc_write_register_common (stream
, key
)))
462 return __objc_write_class (stream
, class);
469 __objc_write_selector (struct objc_typed_stream
*stream
, SEL selector
)
471 const char *sel_name
;
472 __objc_write_extension (stream
, _BX_SEL
);
473 /* to handle NULL selectors */
474 if ((SEL
)0 == selector
)
475 return objc_write_string (stream
, (unsigned char*)"", 0);
476 sel_name
= sel_get_name (selector
);
477 return objc_write_string (stream
, (unsigned char*)sel_name
, strlen ((char*)sel_name
));
481 objc_write_selector (struct objc_typed_stream
*stream
, SEL selector
)
483 const char *sel_name
;
486 /* to handle NULL selectors */
487 if ((SEL
)0 == selector
)
488 return __objc_write_selector (stream
, selector
);
490 sel_name
= sel_get_name (selector
);
491 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
,
493 return objc_write_use_common (stream
, key
);
497 objc_hash_add (&stream
->stream_table
,
498 LONG2PTR(key
= PTR2LONG(sel_name
)), (char *) sel_name
);
499 if ((length
= objc_write_register_common (stream
, key
)))
500 return __objc_write_selector (stream
, selector
);
512 objc_read_char (struct objc_typed_stream
*stream
, char *val
)
516 len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1);
519 if ((buf
& _B_CODE
) == _B_SINT
)
520 (*val
) = (buf
& _B_VALUE
);
522 else if ((buf
& _B_NUMBER
) == 1)
524 len
= (*stream
->read
) (stream
->physical
, val
, 1);
526 (*val
) = -1 * (*val
);
530 _objc_abort ("expected 8bit signed int, got %dbit int",
531 (int) (buf
&_B_NUMBER
)*8);
538 objc_read_unsigned_char (struct objc_typed_stream
*stream
, unsigned char *val
)
542 if ((len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1)))
544 if ((buf
& _B_CODE
) == _B_SINT
)
545 (*val
) = (buf
& _B_VALUE
);
547 else if ((buf
& _B_NUMBER
) == 1)
548 len
= (*stream
->read
) (stream
->physical
, (char*)val
, 1);
551 _objc_abort ("expected 8bit unsigned int, got %dbit int",
552 (int) (buf
&_B_NUMBER
)*8);
558 objc_read_short (struct objc_typed_stream
*stream
, short *value
)
560 unsigned char buf
[sizeof (short) + 1];
562 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
564 if ((buf
[0] & _B_CODE
) == _B_SINT
)
565 (*value
) = (buf
[0] & _B_VALUE
);
570 int nbytes
= buf
[0] & _B_NUMBER
;
571 if (nbytes
> (int) sizeof (short))
572 _objc_abort ("expected short, got bigger (%dbits)", nbytes
*8);
573 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
575 while (pos
<= nbytes
)
576 (*value
) = ((*value
)*0x100) + buf
[pos
++];
577 if (buf
[0] & _B_SIGN
)
578 (*value
) = -(*value
);
585 objc_read_unsigned_short (struct objc_typed_stream
*stream
,
586 unsigned short *value
)
588 unsigned char buf
[sizeof (unsigned short) + 1];
590 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
592 if ((buf
[0] & _B_CODE
) == _B_SINT
)
593 (*value
) = (buf
[0] & _B_VALUE
);
598 int nbytes
= buf
[0] & _B_NUMBER
;
599 if (nbytes
> (int) sizeof (short))
600 _objc_abort ("expected short, got int or bigger");
601 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
603 while (pos
<= nbytes
)
604 (*value
) = ((*value
)*0x100) + buf
[pos
++];
612 objc_read_int (struct objc_typed_stream
*stream
, int *value
)
614 unsigned char buf
[sizeof (int) + 1];
616 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
618 if ((buf
[0] & _B_CODE
) == _B_SINT
)
619 (*value
) = (buf
[0] & _B_VALUE
);
624 int nbytes
= buf
[0] & _B_NUMBER
;
625 if (nbytes
> (int) sizeof (int))
626 _objc_abort ("expected int, got bigger");
627 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
629 while (pos
<= nbytes
)
630 (*value
) = ((*value
)*0x100) + buf
[pos
++];
631 if (buf
[0] & _B_SIGN
)
632 (*value
) = -(*value
);
639 objc_read_long (struct objc_typed_stream
*stream
, long *value
)
641 unsigned char buf
[sizeof (long) + 1];
643 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
645 if ((buf
[0] & _B_CODE
) == _B_SINT
)
646 (*value
) = (buf
[0] & _B_VALUE
);
651 int nbytes
= buf
[0] & _B_NUMBER
;
652 if (nbytes
> (int) sizeof (long))
653 _objc_abort ("expected long, got bigger");
654 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
656 while (pos
<= nbytes
)
657 (*value
) = ((*value
)*0x100) + buf
[pos
++];
658 if (buf
[0] & _B_SIGN
)
659 (*value
) = -(*value
);
666 __objc_read_nbyte_uint (struct objc_typed_stream
*stream
,
667 unsigned int nbytes
, unsigned int *val
)
670 unsigned int pos
= 0;
671 unsigned char buf
[sizeof (unsigned int) + 1];
673 if (nbytes
> sizeof (int))
674 _objc_abort ("expected int, got bigger");
676 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, nbytes
);
679 (*val
) = ((*val
)*0x100) + buf
[pos
++];
685 objc_read_unsigned_int (struct objc_typed_stream
*stream
,
688 unsigned char buf
[sizeof (unsigned int) + 1];
690 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
692 if ((buf
[0] & _B_CODE
) == _B_SINT
)
693 (*value
) = (buf
[0] & _B_VALUE
);
696 len
= __objc_read_nbyte_uint (stream
, (buf
[0] & _B_VALUE
), value
);
703 __objc_read_nbyte_ulong (struct objc_typed_stream
*stream
,
704 unsigned int nbytes
, unsigned long *val
)
707 unsigned int pos
= 0;
708 unsigned char buf
[sizeof (unsigned long) + 1];
710 if (nbytes
> sizeof (long))
711 _objc_abort ("expected long, got bigger");
713 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, nbytes
);
716 (*val
) = ((*val
)*0x100) + buf
[pos
++];
722 objc_read_unsigned_long (struct objc_typed_stream
*stream
,
723 unsigned long *value
)
725 unsigned char buf
[sizeof (unsigned long) + 1];
727 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
729 if ((buf
[0] & _B_CODE
) == _B_SINT
)
730 (*value
) = (buf
[0] & _B_VALUE
);
733 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), value
);
740 objc_read_string (struct objc_typed_stream
*stream
,
743 unsigned char buf
[sizeof (unsigned int) + 1];
745 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
747 unsigned long key
= 0;
749 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
751 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
752 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
755 switch (buf
[0]&_B_CODE
) {
758 int length
= buf
[0]&_B_VALUE
;
759 (*string
) = (char*)objc_malloc (length
+ 1);
761 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
762 len
= (*stream
->read
) (stream
->physical
, *string
, length
);
763 (*string
)[length
] = '\0';
770 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
771 tmp
= objc_hash_value_for_key (stream
->stream_table
, LONG2PTR (key
));
772 *string
= objc_malloc (strlen (tmp
) + 1);
773 strcpy (*string
, tmp
);
779 unsigned int nbytes
= buf
[0]&_B_VALUE
;
780 len
= __objc_read_nbyte_uint (stream
, nbytes
, &nbytes
);
782 (*string
) = (char*)objc_malloc (nbytes
+ 1);
784 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
785 len
= (*stream
->read
) (stream
->physical
, *string
, nbytes
);
786 (*string
)[nbytes
] = '\0';
792 _objc_abort ("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_abort ("expected null-byte, got opcode %c", buf
[0]);
840 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
843 _objc_abort ("cannot register use upcode...");
844 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
845 (*object
) = objc_hash_value_for_key (stream
->object_table
,
849 else if (buf
[0] == (_B_EXT
| _BX_OBJREF
)) /* a forward reference */
851 struct objc_list
*other
;
852 len
= objc_read_unsigned_long (stream
, &key
);
854 = (struct objc_list
*) objc_hash_value_for_key (stream
->object_refs
,
856 objc_hash_add (&stream
->object_refs
, LONG2PTR(key
),
857 (void *)list_cons (object
, other
));
860 else if (buf
[0] == (_B_EXT
| _BX_OBJROOT
)) /* a root object */
863 _objc_abort ("cannot register root object...");
864 len
= objc_read_object (stream
, object
);
865 __objc_finish_read_root_object (stream
);
869 _objc_abort ("expected object, got opcode %c", buf
[0]);
875 objc_read_class (struct objc_typed_stream
*stream
, Class
*class)
877 unsigned char buf
[sizeof (unsigned int)];
879 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
881 unsigned long key
= 0;
883 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
885 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
886 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
889 if (buf
[0] == (_B_EXT
| _BX_CLASS
))
892 char *class_name
= temp
;
893 unsigned long version
;
896 len
= objc_read_string (stream
, &class_name
);
897 (*class) = objc_get_class (class_name
);
898 objc_free (class_name
);
902 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *class);
904 objc_read_unsigned_long (stream
, &version
);
905 objc_hash_add (&stream
->class_table
,
906 (*class)->name
, (void *) ((size_t) version
));
909 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
912 _objc_abort ("cannot register use upcode...");
913 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
914 *class = objc_hash_value_for_key (stream
->stream_table
,
917 _objc_abort ("cannot find class for key %lu", key
);
921 _objc_abort ("expected class, got opcode %c", buf
[0]);
927 objc_read_selector (struct objc_typed_stream
*stream
, SEL
* selector
)
929 unsigned char buf
[sizeof (unsigned int)];
931 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
933 unsigned long key
= 0;
935 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
937 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
938 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
941 if (buf
[0] == (_B_EXT
|_BX_SEL
)) /* selector! */
944 char *selector_name
= temp
;
947 len
= objc_read_string (stream
, &selector_name
);
948 /* To handle NULL selectors */
949 if (0 == strlen (selector_name
))
951 (*selector
) = (SEL
)0;
955 (*selector
) = sel_get_any_uid (selector_name
);
956 objc_free (selector_name
);
960 objc_hash_add (&stream
->stream_table
,
961 LONG2PTR(key
), (void *) *selector
);
964 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
967 _objc_abort ("cannot register use upcode...");
968 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
969 (*selector
) = objc_hash_value_for_key (stream
->stream_table
,
974 _objc_abort ("expected selector, got opcode %c", buf
[0]);
980 ** USER LEVEL FUNCTIONS
984 ** Write one object, encoded in TYPE and pointed to by DATA to the
985 ** typed stream STREAM.
989 objc_write_type (TypedStream
*stream
, const char *type
, const void *data
)
993 return objc_write_object (stream
, *(id
*) data
);
997 return objc_write_class (stream
, *(Class
*) data
);
1001 return objc_write_selector (stream
, *(SEL
*) data
);
1005 return objc_write_char (stream
, *(signed char *) data
);
1009 return objc_write_unsigned_char (stream
, *(unsigned char *) data
);
1013 return objc_write_short (stream
, *(short *) data
);
1017 return objc_write_unsigned_short (stream
, *(unsigned short *) data
);
1021 return objc_write_int (stream
, *(int *) data
);
1025 return objc_write_unsigned_int (stream
, *(unsigned int *) data
);
1029 return objc_write_long (stream
, *(long *) data
);
1033 return objc_write_unsigned_long (stream
, *(unsigned long *) data
);
1037 return objc_write_string (stream
,
1038 *(unsigned char **) data
, strlen (*(char **) data
));
1042 return objc_write_string_atomic (stream
, *(unsigned char **) data
,
1043 strlen (*(char **) data
));
1048 int len
= atoi (type
+ 1);
1049 while (isdigit ((unsigned char) *++type
))
1051 return objc_write_array (stream
, type
, len
, data
);
1059 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1060 ; /* skip "<name>=" */
1061 while (*type
!= _C_STRUCT_E
)
1063 align
= objc_alignof_type (type
); /* padd to alignment */
1064 acc_size
= ROUND (acc_size
, align
);
1065 objc_write_type (stream
, type
, ((char *) data
) + acc_size
);
1066 acc_size
+= objc_sizeof_type (type
); /* add component size */
1067 type
= objc_skip_typespec (type
); /* skip component */
1074 _objc_abort ("objc_write_type: cannot parse typespec: %s\n", type
);
1081 ** Read one object, encoded in TYPE and pointed to by DATA to the
1082 ** typed stream STREAM. DATA specifies the address of the types to
1083 ** read. Expected type is checked against the type actually present
1088 objc_read_type(TypedStream
*stream
, const char *type
, void *data
)
1091 switch (c
= *type
) {
1093 return objc_read_object (stream
, (id
*)data
);
1097 return objc_read_class (stream
, (Class
*)data
);
1101 return objc_read_selector (stream
, (SEL
*)data
);
1105 return objc_read_char (stream
, (char*)data
);
1109 return objc_read_unsigned_char (stream
, (unsigned char*)data
);
1113 return objc_read_short (stream
, (short*)data
);
1117 return objc_read_unsigned_short (stream
, (unsigned short*)data
);
1121 return objc_read_int (stream
, (int*)data
);
1125 return objc_read_unsigned_int (stream
, (unsigned int*)data
);
1129 return objc_read_long (stream
, (long*)data
);
1133 return objc_read_unsigned_long (stream
, (unsigned long*)data
);
1138 return objc_read_string (stream
, (char**)data
);
1143 int len
= atoi (type
+ 1);
1144 while (isdigit ((unsigned char) *++type
))
1146 return objc_read_array (stream
, type
, len
, data
);
1154 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1155 ; /* skip "<name>=" */
1156 while (*type
!= _C_STRUCT_E
)
1158 align
= objc_alignof_type (type
); /* padd to alignment */
1159 acc_size
= ROUND (acc_size
, align
);
1160 objc_read_type (stream
, type
, ((char*)data
)+acc_size
);
1161 acc_size
+= objc_sizeof_type (type
); /* add component size */
1162 type
= objc_skip_typespec (type
); /* skip component */
1169 _objc_abort ("objc_read_type: cannot parse typespec: %s\n", type
);
1176 ** Write the object specified by the template TYPE to STREAM. Last
1177 ** arguments specify addresses of values to be written. It might
1178 ** seem surprising to specify values by address, but this is extremely
1179 ** convenient for copy-paste with objc_read_types calls. A more
1180 ** down-to-the-earth cause for this passing of addresses is that values
1181 ** of arbitrary size is not well supported in ANSI C for functions with
1182 ** variable number of arguments.
1186 objc_write_types (TypedStream
*stream
, const char *type
, ...)
1192 va_start(args
, type
);
1194 for (c
= type
; *c
; c
= objc_skip_typespec (c
))
1198 res
= objc_write_object (stream
, *va_arg (args
, id
*));
1202 res
= objc_write_class (stream
, *va_arg (args
, Class
*));
1206 res
= objc_write_selector (stream
, *va_arg (args
, SEL
*));
1210 res
= objc_write_char (stream
, *va_arg (args
, char*));
1214 res
= objc_write_unsigned_char (stream
,
1215 *va_arg (args
, unsigned char*));
1219 res
= objc_write_short (stream
, *va_arg (args
, short*));
1223 res
= objc_write_unsigned_short (stream
,
1224 *va_arg (args
, unsigned short*));
1228 res
= objc_write_int(stream
, *va_arg (args
, int*));
1232 res
= objc_write_unsigned_int(stream
, *va_arg (args
, unsigned int*));
1236 res
= objc_write_long(stream
, *va_arg (args
, long*));
1240 res
= objc_write_unsigned_long(stream
, *va_arg (args
, unsigned long*));
1245 unsigned char **str
= va_arg (args
, unsigned char **);
1246 res
= objc_write_string (stream
, *str
, strlen ((char*)*str
));
1252 unsigned char **str
= va_arg (args
, unsigned char **);
1253 res
= objc_write_string_atomic (stream
, *str
, strlen ((char*)*str
));
1259 int len
= atoi (c
+ 1);
1261 while (isdigit ((unsigned char) *++t
))
1263 res
= objc_write_array (stream
, t
, len
, va_arg (args
, void *));
1264 t
= objc_skip_typespec (t
);
1266 _objc_abort ("expected `]', got: %s", t
);
1271 _objc_abort ("objc_write_types: cannot parse typespec: %s\n", type
);
1280 ** Last arguments specify addresses of values to be read. Expected
1281 ** type is checked against the type actually present on the stream.
1285 objc_read_types(TypedStream
*stream
, const char *type
, ...)
1291 va_start (args
, type
);
1293 for (c
= type
; *c
; c
= objc_skip_typespec(c
))
1297 res
= objc_read_object(stream
, va_arg (args
, id
*));
1301 res
= objc_read_class(stream
, va_arg (args
, Class
*));
1305 res
= objc_read_selector(stream
, va_arg (args
, SEL
*));
1309 res
= objc_read_char(stream
, va_arg (args
, char*));
1313 res
= objc_read_unsigned_char(stream
, va_arg (args
, unsigned char*));
1317 res
= objc_read_short(stream
, va_arg (args
, short*));
1321 res
= objc_read_unsigned_short(stream
, va_arg (args
, unsigned short*));
1325 res
= objc_read_int(stream
, va_arg (args
, int*));
1329 res
= objc_read_unsigned_int(stream
, va_arg (args
, unsigned int*));
1333 res
= objc_read_long(stream
, va_arg (args
, long*));
1337 res
= objc_read_unsigned_long(stream
, va_arg (args
, unsigned long*));
1343 char **str
= va_arg (args
, char **);
1344 res
= objc_read_string (stream
, str
);
1350 int len
= atoi (c
+ 1);
1352 while (isdigit ((unsigned char) *++t
))
1354 res
= objc_read_array (stream
, t
, len
, va_arg (args
, void *));
1355 t
= objc_skip_typespec (t
);
1357 _objc_abort ("expected `]', got: %s", t
);
1362 _objc_abort ("objc_read_types: cannot parse typespec: %s\n", type
);
1370 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1371 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1375 objc_write_array (TypedStream
*stream
, const char *type
,
1376 int count
, const void *data
)
1378 int off
= objc_sizeof_type(type
);
1379 const char *where
= data
;
1383 objc_write_type(stream
, type
, where
);
1390 ** Read an array of COUNT elements of TYPE into the memory address
1391 ** DATA. The memory pointed to by data is supposed to be allocated
1392 ** by the callee. This is equivalent of
1393 ** objc_read_type (stream, "[N<type>]", data)
1397 objc_read_array (TypedStream
*stream
, const char *type
,
1398 int count
, void *data
)
1400 int off
= objc_sizeof_type(type
);
1401 char *where
= (char*)data
;
1405 objc_read_type(stream
, type
, where
);
1412 __objc_fread (FILE *file
, char *data
, int len
)
1414 return fread(data
, len
, 1, file
);
1418 __objc_fwrite (FILE *file
, char *data
, int len
)
1420 return fwrite(data
, len
, 1, file
);
1424 __objc_feof (FILE *file
)
1430 __objc_no_write (FILE *file
__attribute__ ((__unused__
)),
1431 const char *data
__attribute__ ((__unused__
)),
1432 int len
__attribute__ ((__unused__
)))
1434 _objc_abort ("TypedStream not open for writing");
1439 __objc_no_read (FILE *file
__attribute__ ((__unused__
)),
1440 const char *data
__attribute__ ((__unused__
)),
1441 int len
__attribute__ ((__unused__
)))
1443 _objc_abort ("TypedStream not open for reading");
1448 __objc_read_typed_stream_signature (TypedStream
*stream
)
1453 (*stream
->read
) (stream
->physical
, buffer
+pos
, 1);
1454 while (buffer
[pos
++] != '\0')
1456 sscanf (buffer
, "GNU TypedStream %d", &stream
->version
);
1457 if (stream
->version
!= OBJC_TYPED_STREAM_VERSION
)
1458 _objc_abort ("cannot handle TypedStream version %d", stream
->version
);
1463 __objc_write_typed_stream_signature (TypedStream
*stream
)
1466 sprintf(buffer
, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION
);
1467 stream
->version
= OBJC_TYPED_STREAM_VERSION
;
1468 (*stream
->write
) (stream
->physical
, buffer
, strlen (buffer
) + 1);
1472 static void __objc_finish_write_root_object(struct objc_typed_stream
*stream
)
1474 objc_hash_delete (stream
->object_table
);
1475 stream
->object_table
= objc_hash_new (64,
1476 (hash_func_type
) objc_hash_ptr
,
1477 (compare_func_type
) objc_compare_ptrs
);
1480 static void __objc_finish_read_root_object(struct objc_typed_stream
*stream
)
1483 SEL awake_sel
= sel_get_any_uid ("awake");
1484 cache_ptr free_list
= objc_hash_new (64,
1485 (hash_func_type
) objc_hash_ptr
,
1486 (compare_func_type
) objc_compare_ptrs
);
1488 /* resolve object forward references */
1489 for (node
= objc_hash_next (stream
->object_refs
, NULL
); node
;
1490 node
= objc_hash_next (stream
->object_refs
, node
))
1492 struct objc_list
*reflist
= node
->value
;
1493 const void *key
= node
->key
;
1494 id object
= objc_hash_value_for_key (stream
->object_table
, key
);
1497 *((id
*) reflist
->head
) = object
;
1498 if (objc_hash_value_for_key (free_list
,reflist
) == NULL
)
1499 objc_hash_add (&free_list
,reflist
,reflist
);
1501 reflist
= reflist
->tail
;
1505 /* apply __objc_free to all objects stored in free_list */
1506 for (node
= objc_hash_next (free_list
, NULL
); node
;
1507 node
= objc_hash_next (free_list
, node
))
1508 objc_free ((void *) node
->key
);
1510 objc_hash_delete (free_list
);
1512 /* empty object reference table */
1513 objc_hash_delete (stream
->object_refs
);
1514 stream
->object_refs
= objc_hash_new (8, (hash_func_type
) objc_hash_ptr
,
1515 (compare_func_type
) objc_compare_ptrs
);
1517 /* call -awake for all objects read */
1520 for (node
= objc_hash_next (stream
->object_table
, NULL
); node
;
1521 node
= objc_hash_next (stream
->object_table
, node
))
1523 id object
= node
->value
;
1524 if (__objc_responds_to (object
, awake_sel
))
1525 (*objc_msg_lookup (object
, awake_sel
)) (object
, awake_sel
);
1529 /* empty object table */
1530 objc_hash_delete (stream
->object_table
);
1531 stream
->object_table
= objc_hash_new(64,
1532 (hash_func_type
)objc_hash_ptr
,
1533 (compare_func_type
)objc_compare_ptrs
);
1537 ** Open the stream PHYSICAL in MODE
1541 objc_open_typed_stream (FILE *physical
, int mode
)
1543 TypedStream
*s
= (TypedStream
*) objc_malloc (sizeof (TypedStream
));
1546 s
->physical
= physical
;
1547 s
->stream_table
= objc_hash_new (64,
1548 (hash_func_type
) objc_hash_ptr
,
1549 (compare_func_type
) objc_compare_ptrs
);
1550 s
->object_table
= objc_hash_new (64,
1551 (hash_func_type
) objc_hash_ptr
,
1552 (compare_func_type
) objc_compare_ptrs
);
1553 s
->eof
= (objc_typed_eof_func
) __objc_feof
;
1554 s
->flush
= (objc_typed_flush_func
) fflush
;
1555 s
->writing_root_p
= 0;
1556 if (mode
== OBJC_READONLY
)
1559 = objc_hash_new (8, (hash_func_type
) objc_hash_string
,
1560 (compare_func_type
) objc_compare_strings
);
1561 s
->object_refs
= objc_hash_new (8, (hash_func_type
) objc_hash_ptr
,
1562 (compare_func_type
) objc_compare_ptrs
);
1563 s
->read
= (objc_typed_read_func
) __objc_fread
;
1564 s
->write
= (objc_typed_write_func
) __objc_no_write
;
1565 __objc_read_typed_stream_signature (s
);
1567 else if (mode
== OBJC_WRITEONLY
)
1571 s
->read
= (objc_typed_read_func
) __objc_no_read
;
1572 s
->write
= (objc_typed_write_func
) __objc_fwrite
;
1573 __objc_write_typed_stream_signature (s
);
1577 objc_close_typed_stream (s
);
1580 s
->type
= OBJC_FILE_STREAM
;
1585 ** Open the file named by FILE_NAME in MODE
1589 objc_open_typed_stream_for_file (const char *file_name
, int mode
)
1594 if (mode
== OBJC_READONLY
)
1595 file
= fopen (file_name
, "r");
1597 file
= fopen (file_name
, "w");
1601 s
= objc_open_typed_stream (file
, mode
);
1603 s
->type
|= OBJC_MANAGED_STREAM
;
1611 ** Close STREAM freeing the structure it self. If it was opened with
1612 ** objc_open_typed_stream_for_file, the file will also be closed.
1616 objc_close_typed_stream (TypedStream
*stream
)
1618 if (stream
->mode
== OBJC_READONLY
)
1620 __objc_finish_read_root_object (stream
); /* Just in case... */
1621 objc_hash_delete (stream
->class_table
);
1622 objc_hash_delete (stream
->object_refs
);
1625 objc_hash_delete (stream
->stream_table
);
1626 objc_hash_delete (stream
->object_table
);
1628 if (stream
->type
== (OBJC_MANAGED_STREAM
| OBJC_FILE_STREAM
))
1629 fclose ((FILE *)stream
->physical
);
1635 objc_end_of_typed_stream (TypedStream
*stream
)
1637 return (*stream
->eof
) (stream
->physical
);
1641 objc_flush_typed_stream (TypedStream
*stream
)
1643 (*stream
->flush
) (stream
->physical
);
1647 objc_get_stream_class_version (TypedStream
*stream
, Class
class)
1649 if (stream
->class_table
)
1650 return PTR2LONG(objc_hash_value_for_key (stream
->class_table
,
1653 return class_get_version (class);