1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004 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 2, 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 You should have received a copy of the GNU General Public License along with
17 GCC; see the file COPYING. If not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* As a special exception, if you link this library with files compiled with
22 GCC to produce an executable, this does not cause the resulting executable
23 to be covered by the GNU General Public License. This exception does not
24 however invalidate any other reasons why the executable file might be
25 covered by the GNU General Public License. */
29 #include "typedstream.h"
33 extern int fflush (FILE *);
36 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
37 __a * ((__v + __a - 1)/__a); })
39 #define PTR2LONG(P) (((char *) (P))-(char *) 0)
40 #define LONG2PTR(L) (((char *) 0) + (L))
42 /* Declare some functions... */
45 objc_read_class (struct objc_typed_stream
*stream
, Class
*class);
47 int objc_sizeof_type (const char *type
);
50 objc_write_use_common (struct objc_typed_stream
*stream
, unsigned long key
);
53 objc_write_register_common (struct objc_typed_stream
*stream
,
57 objc_write_class (struct objc_typed_stream
*stream
,
58 struct objc_class
*class);
60 const char *objc_skip_type (const char *type
);
62 static void __objc_finish_write_root_object (struct objc_typed_stream
*);
63 static void __objc_finish_read_root_object (struct objc_typed_stream
*);
66 __objc_code_unsigned_char (unsigned char *buf
, unsigned char val
)
68 if ((val
&_B_VALUE
) == val
)
75 buf
[0] = _B_NINT
|0x01;
82 objc_write_unsigned_char (struct objc_typed_stream
*stream
,
85 unsigned char buf
[sizeof (unsigned char) + 1];
86 int len
= __objc_code_unsigned_char (buf
, value
);
87 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
91 __objc_code_char (unsigned char *buf
, signed char val
)
94 return __objc_code_unsigned_char (buf
, val
);
97 buf
[0] = _B_NINT
|_B_SIGN
|0x01;
104 objc_write_char (struct objc_typed_stream
*stream
, signed char value
)
106 unsigned char buf
[sizeof (char) + 1];
107 int len
= __objc_code_char (buf
, value
);
108 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
112 __objc_code_unsigned_short (unsigned char *buf
, unsigned short val
)
114 if ((val
&_B_VALUE
) == val
)
116 buf
[0] = val
|_B_SINT
;
125 for (c
= sizeof (short); c
!= 0; c
-= 1)
126 if (((val
>> (8*(c
- 1)))%0x100) != 0)
131 for (b
= 1; c
!= 0; c
--, b
++)
133 buf
[b
] = (val
>> (8*(c
- 1)))%0x100;
141 objc_write_unsigned_short (struct objc_typed_stream
*stream
,
142 unsigned short value
)
144 unsigned char buf
[sizeof (unsigned short) + 1];
145 int len
= __objc_code_unsigned_short (buf
, value
);
146 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
150 __objc_code_short (unsigned char *buf
, short val
)
152 int sign
= (val
< 0);
153 int size
= __objc_code_unsigned_short (buf
, sign
? -val
: val
);
160 objc_write_short (struct objc_typed_stream
*stream
, short value
)
162 unsigned char buf
[sizeof (short) + 1];
163 int len
= __objc_code_short (buf
, value
);
164 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
169 __objc_code_unsigned_int (unsigned char *buf
, unsigned int val
)
171 if ((val
&_B_VALUE
) == val
)
173 buf
[0] = val
|_B_SINT
;
182 for (c
= sizeof (int); c
!= 0; c
-= 1)
183 if (((val
>> (8*(c
- 1)))%0x100) != 0)
188 for (b
= 1; c
!= 0; c
--, b
++)
190 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
198 objc_write_unsigned_int (struct objc_typed_stream
*stream
, unsigned int value
)
200 unsigned char buf
[sizeof (unsigned int) + 1];
201 int len
= __objc_code_unsigned_int (buf
, value
);
202 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
206 __objc_code_int (unsigned char *buf
, int val
)
208 int sign
= (val
< 0);
209 int size
= __objc_code_unsigned_int (buf
, sign
? -val
: val
);
216 objc_write_int (struct objc_typed_stream
*stream
, int value
)
218 unsigned char buf
[sizeof (int) + 1];
219 int len
= __objc_code_int (buf
, value
);
220 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
224 __objc_code_unsigned_long (unsigned char *buf
, unsigned long val
)
226 if ((val
&_B_VALUE
) == val
)
228 buf
[0] = val
|_B_SINT
;
237 for (c
= sizeof (long); c
!= 0; c
-= 1)
238 if (((val
>> (8*(c
- 1)))%0x100) != 0)
243 for (b
= 1; c
!= 0; c
--, b
++)
245 buf
[b
] = (val
>> (8*(c
- 1)))%0x100;
253 objc_write_unsigned_long (struct objc_typed_stream
*stream
,
256 unsigned char buf
[sizeof (unsigned long) + 1];
257 int len
= __objc_code_unsigned_long (buf
, value
);
258 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
262 __objc_code_long (unsigned char *buf
, long val
)
264 int sign
= (val
< 0);
265 int size
= __objc_code_unsigned_long (buf
, sign
? -val
: val
);
272 objc_write_long (struct objc_typed_stream
*stream
, long value
)
274 unsigned char buf
[sizeof (long) + 1];
275 int len
= __objc_code_long (buf
, value
);
276 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
);
281 objc_write_string (struct objc_typed_stream
*stream
,
282 const unsigned char *string
, unsigned int nbytes
)
284 unsigned char buf
[sizeof (unsigned int) + 1];
285 int len
= __objc_code_unsigned_int (buf
, nbytes
);
287 if ((buf
[0]&_B_CODE
) == _B_SINT
)
288 buf
[0] = (buf
[0]&_B_VALUE
)|_B_SSTR
;
291 buf
[0] = (buf
[0]&_B_VALUE
)|_B_NSTR
;
293 if ((*stream
->write
) (stream
->physical
, (char*)buf
, len
) != 0)
294 return (*stream
->write
) (stream
->physical
, (char*)string
, nbytes
);
300 objc_write_string_atomic (struct objc_typed_stream
*stream
,
301 unsigned char *string
, unsigned int nbytes
)
304 if ((key
= PTR2LONG(hash_value_for_key (stream
->stream_table
, string
))))
305 return objc_write_use_common (stream
, key
);
309 hash_add (&stream
->stream_table
, LONG2PTR(key
=PTR2LONG(string
)), string
);
310 if ((length
= objc_write_register_common (stream
, key
)))
311 return objc_write_string (stream
, string
, nbytes
);
317 objc_write_register_common (struct objc_typed_stream
*stream
,
320 unsigned char buf
[sizeof (unsigned long)+2];
321 int len
= __objc_code_unsigned_long (buf
+ 1, key
);
324 buf
[0] = _B_RCOMM
|0x01;
326 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
+ 1);
330 buf
[1] = (buf
[1]&_B_VALUE
)|_B_RCOMM
;
331 return (*stream
->write
) (stream
->physical
, (char*)buf
+ 1, len
);
336 objc_write_use_common (struct objc_typed_stream
*stream
, unsigned long key
)
338 unsigned char buf
[sizeof (unsigned long)+2];
339 int len
= __objc_code_unsigned_long (buf
+ 1, key
);
342 buf
[0] = _B_UCOMM
|0x01;
344 return (*stream
->write
) (stream
->physical
, (char*)buf
, 2);
348 buf
[1] = (buf
[1]&_B_VALUE
)|_B_UCOMM
;
349 return (*stream
->write
) (stream
->physical
, (char*)buf
+ 1, len
);
354 __objc_write_extension (struct objc_typed_stream
*stream
, unsigned char code
)
356 if (code
<= _B_VALUE
)
358 unsigned char buf
= code
|_B_EXT
;
359 return (*stream
->write
) (stream
->physical
, (char*)&buf
, 1);
363 objc_error (nil
, OBJC_ERR_BAD_OPCODE
,
364 "__objc_write_extension: bad opcode %c\n", code
);
370 __objc_write_object (struct objc_typed_stream
*stream
, id object
)
372 unsigned char buf
= '\0';
373 SEL write_sel
= sel_get_any_uid ("write:");
376 __objc_write_extension (stream
, _BX_OBJECT
);
377 objc_write_class (stream
, object
->class_pointer
);
378 (*objc_msg_lookup (object
, write_sel
)) (object
, write_sel
, stream
);
379 return (*stream
->write
) (stream
->physical
, (char*)&buf
, 1);
382 return objc_write_use_common (stream
, 0);
386 objc_write_object_reference (struct objc_typed_stream
*stream
, id object
)
389 if ((key
= PTR2LONG(hash_value_for_key (stream
->object_table
, object
))))
390 return objc_write_use_common (stream
, key
);
392 __objc_write_extension (stream
, _BX_OBJREF
);
393 return objc_write_unsigned_long (stream
, PTR2LONG (object
));
397 objc_write_root_object (struct objc_typed_stream
*stream
, id object
)
400 if (stream
->writing_root_p
)
401 objc_error (nil
, OBJC_ERR_RECURSE_ROOT
,
402 "objc_write_root_object called recursively");
405 stream
->writing_root_p
= 1;
406 __objc_write_extension (stream
, _BX_OBJROOT
);
407 if ((len
= objc_write_object (stream
, object
)))
408 __objc_finish_write_root_object (stream
);
409 stream
->writing_root_p
= 0;
415 objc_write_object (struct objc_typed_stream
*stream
, id object
)
418 if ((key
= PTR2LONG(hash_value_for_key (stream
->object_table
, object
))))
419 return objc_write_use_common (stream
, key
);
421 else if (object
== nil
)
422 return objc_write_use_common (stream
, 0);
427 hash_add (&stream
->object_table
, 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(hash_value_for_key (stream
->stream_table
, class))))
450 return objc_write_use_common (stream
, key
);
454 hash_add (&stream
->stream_table
, LONG2PTR(key
= PTR2LONG(class)), class);
455 if ((length
= objc_write_register_common (stream
, key
)))
456 return __objc_write_class (stream
, class);
463 __objc_write_selector (struct objc_typed_stream
*stream
, SEL selector
)
465 const char *sel_name
;
466 __objc_write_extension (stream
, _BX_SEL
);
467 /* to handle NULL selectors */
468 if ((SEL
)0 == selector
)
469 return objc_write_string (stream
, (unsigned char*)"", 0);
470 sel_name
= sel_get_name (selector
);
471 return objc_write_string (stream
, (unsigned char*)sel_name
, strlen ((char*)sel_name
));
475 objc_write_selector (struct objc_typed_stream
*stream
, SEL selector
)
477 const char *sel_name
;
480 /* to handle NULL selectors */
481 if ((SEL
)0 == selector
)
482 return __objc_write_selector (stream
, selector
);
484 sel_name
= sel_get_name (selector
);
485 if ((key
= PTR2LONG(hash_value_for_key (stream
->stream_table
, sel_name
))))
486 return objc_write_use_common (stream
, key
);
490 hash_add (&stream
->stream_table
,
491 LONG2PTR(key
= PTR2LONG(sel_name
)), (char *) sel_name
);
492 if ((length
= objc_write_register_common (stream
, key
)))
493 return __objc_write_selector (stream
, selector
);
505 objc_read_char (struct objc_typed_stream
*stream
, char *val
)
509 len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1);
512 if ((buf
& _B_CODE
) == _B_SINT
)
513 (*val
) = (buf
& _B_VALUE
);
515 else if ((buf
& _B_NUMBER
) == 1)
517 len
= (*stream
->read
) (stream
->physical
, val
, 1);
519 (*val
) = -1 * (*val
);
523 objc_error (nil
, OBJC_ERR_BAD_DATA
,
524 "expected 8bit signed int, got %dbit int",
525 (int) (buf
&_B_NUMBER
)*8);
532 objc_read_unsigned_char (struct objc_typed_stream
*stream
, unsigned char *val
)
536 if ((len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1)))
538 if ((buf
& _B_CODE
) == _B_SINT
)
539 (*val
) = (buf
& _B_VALUE
);
541 else if ((buf
& _B_NUMBER
) == 1)
542 len
= (*stream
->read
) (stream
->physical
, (char*)val
, 1);
545 objc_error (nil
, OBJC_ERR_BAD_DATA
,
546 "expected 8bit unsigned int, got %dbit int",
547 (int) (buf
&_B_NUMBER
)*8);
553 objc_read_short (struct objc_typed_stream
*stream
, short *value
)
555 unsigned char buf
[sizeof (short) + 1];
557 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
559 if ((buf
[0] & _B_CODE
) == _B_SINT
)
560 (*value
) = (buf
[0] & _B_VALUE
);
565 int nbytes
= buf
[0] & _B_NUMBER
;
566 if (nbytes
> (int) sizeof (short))
567 objc_error (nil
, OBJC_ERR_BAD_DATA
,
568 "expected short, got bigger (%dbits)", nbytes
*8);
569 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
571 while (pos
<= nbytes
)
572 (*value
) = ((*value
)*0x100) + buf
[pos
++];
573 if (buf
[0] & _B_SIGN
)
574 (*value
) = -(*value
);
581 objc_read_unsigned_short (struct objc_typed_stream
*stream
,
582 unsigned short *value
)
584 unsigned char buf
[sizeof (unsigned short) + 1];
586 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
588 if ((buf
[0] & _B_CODE
) == _B_SINT
)
589 (*value
) = (buf
[0] & _B_VALUE
);
594 int nbytes
= buf
[0] & _B_NUMBER
;
595 if (nbytes
> (int) sizeof (short))
596 objc_error (nil
, OBJC_ERR_BAD_DATA
,
597 "expected short, got int or bigger");
598 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
600 while (pos
<= nbytes
)
601 (*value
) = ((*value
)*0x100) + buf
[pos
++];
609 objc_read_int (struct objc_typed_stream
*stream
, int *value
)
611 unsigned char buf
[sizeof (int) + 1];
613 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
615 if ((buf
[0] & _B_CODE
) == _B_SINT
)
616 (*value
) = (buf
[0] & _B_VALUE
);
621 int nbytes
= buf
[0] & _B_NUMBER
;
622 if (nbytes
> (int) sizeof (int))
623 objc_error (nil
, OBJC_ERR_BAD_DATA
, "expected int, got bigger");
624 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
626 while (pos
<= nbytes
)
627 (*value
) = ((*value
)*0x100) + buf
[pos
++];
628 if (buf
[0] & _B_SIGN
)
629 (*value
) = -(*value
);
636 objc_read_long (struct objc_typed_stream
*stream
, long *value
)
638 unsigned char buf
[sizeof (long) + 1];
640 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
642 if ((buf
[0] & _B_CODE
) == _B_SINT
)
643 (*value
) = (buf
[0] & _B_VALUE
);
648 int nbytes
= buf
[0] & _B_NUMBER
;
649 if (nbytes
> (int) sizeof (long))
650 objc_error (nil
, OBJC_ERR_BAD_DATA
, "expected long, got bigger");
651 len
= (*stream
->read
) (stream
->physical
, (char*)buf
+ 1, nbytes
);
653 while (pos
<= nbytes
)
654 (*value
) = ((*value
)*0x100) + buf
[pos
++];
655 if (buf
[0] & _B_SIGN
)
656 (*value
) = -(*value
);
663 __objc_read_nbyte_uint (struct objc_typed_stream
*stream
,
664 unsigned int nbytes
, unsigned int *val
)
667 unsigned int pos
= 0;
668 unsigned char buf
[sizeof (unsigned int) + 1];
670 if (nbytes
> sizeof (int))
671 objc_error (nil
, OBJC_ERR_BAD_DATA
, "expected int, got bigger");
673 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, nbytes
);
676 (*val
) = ((*val
)*0x100) + buf
[pos
++];
682 objc_read_unsigned_int (struct objc_typed_stream
*stream
,
685 unsigned char buf
[sizeof (unsigned int) + 1];
687 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
689 if ((buf
[0] & _B_CODE
) == _B_SINT
)
690 (*value
) = (buf
[0] & _B_VALUE
);
693 len
= __objc_read_nbyte_uint (stream
, (buf
[0] & _B_VALUE
), value
);
700 __objc_read_nbyte_ulong (struct objc_typed_stream
*stream
,
701 unsigned int nbytes
, unsigned long *val
)
704 unsigned int pos
= 0;
705 unsigned char buf
[sizeof (unsigned long) + 1];
707 if (nbytes
> sizeof (long))
708 objc_error (nil
, OBJC_ERR_BAD_DATA
, "expected long, got bigger");
710 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, nbytes
);
713 (*val
) = ((*val
)*0x100) + buf
[pos
++];
719 objc_read_unsigned_long (struct objc_typed_stream
*stream
,
720 unsigned long *value
)
722 unsigned char buf
[sizeof (unsigned long) + 1];
724 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
726 if ((buf
[0] & _B_CODE
) == _B_SINT
)
727 (*value
) = (buf
[0] & _B_VALUE
);
730 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), value
);
737 objc_read_string (struct objc_typed_stream
*stream
,
740 unsigned char buf
[sizeof (unsigned int) + 1];
742 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
744 unsigned long key
= 0;
746 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
748 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
749 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
752 switch (buf
[0]&_B_CODE
) {
755 int length
= buf
[0]&_B_VALUE
;
756 (*string
) = (char*)objc_malloc (length
+ 1);
758 hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
759 len
= (*stream
->read
) (stream
->physical
, *string
, length
);
760 (*string
)[length
] = '\0';
767 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
768 tmp
= hash_value_for_key (stream
->stream_table
, LONG2PTR (key
));
769 *string
= objc_malloc (strlen (tmp
) + 1);
770 strcpy (*string
, tmp
);
776 unsigned int nbytes
= buf
[0]&_B_VALUE
;
777 len
= __objc_read_nbyte_uint (stream
, nbytes
, &nbytes
);
779 (*string
) = (char*)objc_malloc (nbytes
+ 1);
781 hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
782 len
= (*stream
->read
) (stream
->physical
, *string
, nbytes
);
783 (*string
)[nbytes
] = '\0';
789 objc_error (nil
, OBJC_ERR_BAD_DATA
,
790 "expected string, got opcode %c\n", (buf
[0]&_B_CODE
));
799 objc_read_object (struct objc_typed_stream
*stream
, id
*object
)
801 unsigned char buf
[sizeof (unsigned int)];
803 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
805 SEL read_sel
= sel_get_any_uid ("read:");
806 unsigned long key
= 0;
808 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register common */
810 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
811 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
814 if (buf
[0] == (_B_EXT
| _BX_OBJECT
))
819 len
= objc_read_class (stream
, &class);
821 /* create instance */
822 (*object
) = class_create_instance (class);
826 hash_add (&stream
->object_table
, LONG2PTR(key
), *object
);
829 if (__objc_responds_to (*object
, read_sel
))
830 (*get_imp (class, read_sel
)) (*object
, read_sel
, stream
);
832 /* check null-byte */
833 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
835 objc_error (nil
, OBJC_ERR_BAD_DATA
,
836 "expected null-byte, got opcode %c", buf
[0]);
839 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
842 objc_error (nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
843 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
844 (*object
) = hash_value_for_key (stream
->object_table
, LONG2PTR(key
));
847 else if (buf
[0] == (_B_EXT
| _BX_OBJREF
)) /* a forward reference */
849 struct objc_list
*other
;
850 len
= objc_read_unsigned_long (stream
, &key
);
851 other
= (struct objc_list
*) hash_value_for_key (stream
->object_refs
,
853 hash_add (&stream
->object_refs
, LONG2PTR(key
),
854 (void *)list_cons (object
, other
));
857 else if (buf
[0] == (_B_EXT
| _BX_OBJROOT
)) /* a root object */
860 objc_error (nil
, OBJC_ERR_BAD_KEY
,
861 "cannot register root object...");
862 len
= objc_read_object (stream
, object
);
863 __objc_finish_read_root_object (stream
);
867 objc_error (nil
, OBJC_ERR_BAD_DATA
,
868 "expected object, got opcode %c", buf
[0]);
874 objc_read_class (struct objc_typed_stream
*stream
, Class
*class)
876 unsigned char buf
[sizeof (unsigned int)];
878 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
880 unsigned long key
= 0;
882 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
884 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
885 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
888 if (buf
[0] == (_B_EXT
| _BX_CLASS
))
891 char *class_name
= temp
;
892 unsigned long version
;
895 len
= objc_read_string (stream
, &class_name
);
896 (*class) = objc_get_class (class_name
);
897 objc_free (class_name
);
901 hash_add (&stream
->stream_table
, LONG2PTR(key
), *class);
903 objc_read_unsigned_long (stream
, &version
);
904 hash_add (&stream
->class_table
, (*class)->name
, (void *)version
);
907 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
910 objc_error (nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
911 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
912 *class = hash_value_for_key (stream
->stream_table
, LONG2PTR(key
));
914 objc_error (nil
, OBJC_ERR_BAD_CLASS
,
915 "cannot find class for key %lu", key
);
919 objc_error (nil
, OBJC_ERR_BAD_DATA
,
920 "expected class, got opcode %c", buf
[0]);
926 objc_read_selector (struct objc_typed_stream
*stream
, SEL
* selector
)
928 unsigned char buf
[sizeof (unsigned int)];
930 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
932 unsigned long key
= 0;
934 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
936 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
937 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
940 if (buf
[0] == (_B_EXT
|_BX_SEL
)) /* selector! */
943 char *selector_name
= temp
;
946 len
= objc_read_string (stream
, &selector_name
);
947 /* To handle NULL selectors */
948 if (0 == strlen (selector_name
))
950 (*selector
) = (SEL
)0;
954 (*selector
) = sel_get_any_uid (selector_name
);
955 objc_free (selector_name
);
959 hash_add (&stream
->stream_table
, LONG2PTR(key
), (void *) *selector
);
962 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
965 objc_error (nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
966 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
967 (*selector
) = hash_value_for_key (stream
->stream_table
,
972 objc_error (nil
, OBJC_ERR_BAD_DATA
,
973 "expected selector, got opcode %c", buf
[0]);
979 ** USER LEVEL FUNCTIONS
983 ** Write one object, encoded in TYPE and pointed to by DATA to the
984 ** typed stream STREAM.
988 objc_write_type (TypedStream
*stream
, const char *type
, const void *data
)
992 return objc_write_object (stream
, *(id
*) data
);
996 return objc_write_class (stream
, *(Class
*) data
);
1000 return objc_write_selector (stream
, *(SEL
*) data
);
1004 return objc_write_char (stream
, *(signed char *) data
);
1008 return objc_write_unsigned_char (stream
, *(unsigned char *) data
);
1012 return objc_write_short (stream
, *(short *) data
);
1016 return objc_write_unsigned_short (stream
, *(unsigned short *) data
);
1020 return objc_write_int (stream
, *(int *) data
);
1024 return objc_write_unsigned_int (stream
, *(unsigned int *) data
);
1028 return objc_write_long (stream
, *(long *) data
);
1032 return objc_write_unsigned_long (stream
, *(unsigned long *) data
);
1036 return objc_write_string (stream
,
1037 *(unsigned char **) data
, strlen (*(char **) data
));
1041 return objc_write_string_atomic (stream
, *(unsigned char **) data
,
1042 strlen (*(char **) data
));
1047 int len
= atoi (type
+ 1);
1048 while (isdigit ((unsigned char) *++type
))
1050 return objc_write_array (stream
, type
, len
, data
);
1058 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1059 ; /* skip "<name>=" */
1060 while (*type
!= _C_STRUCT_E
)
1062 align
= objc_alignof_type (type
); /* padd to alignment */
1063 acc_size
+= ROUND (acc_size
, align
);
1064 objc_write_type (stream
, type
, ((char *) data
) + acc_size
);
1065 acc_size
+= objc_sizeof_type (type
); /* add component size */
1066 type
= objc_skip_typespec (type
); /* skip component */
1073 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1074 "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_error (nil
, OBJC_ERR_BAD_TYPE
,
1170 "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_error (nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1272 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1273 "objc_write_types: cannot parse typespec: %s\n", type
);
1282 ** Last arguments specify addresses of values to be read. Expected
1283 ** type is checked against the type actually present on the stream.
1287 objc_read_types(TypedStream
*stream
, const char *type
, ...)
1293 va_start (args
, type
);
1295 for (c
= type
; *c
; c
= objc_skip_typespec(c
))
1299 res
= objc_read_object(stream
, va_arg (args
, id
*));
1303 res
= objc_read_class(stream
, va_arg (args
, Class
*));
1307 res
= objc_read_selector(stream
, va_arg (args
, SEL
*));
1311 res
= objc_read_char(stream
, va_arg (args
, char*));
1315 res
= objc_read_unsigned_char(stream
, va_arg (args
, unsigned char*));
1319 res
= objc_read_short(stream
, va_arg (args
, short*));
1323 res
= objc_read_unsigned_short(stream
, va_arg (args
, unsigned short*));
1327 res
= objc_read_int(stream
, va_arg (args
, int*));
1331 res
= objc_read_unsigned_int(stream
, va_arg (args
, unsigned int*));
1335 res
= objc_read_long(stream
, va_arg (args
, long*));
1339 res
= objc_read_unsigned_long(stream
, va_arg (args
, unsigned long*));
1345 char **str
= va_arg (args
, char **);
1346 res
= objc_read_string (stream
, str
);
1352 int len
= atoi (c
+ 1);
1354 while (isdigit ((unsigned char) *++t
))
1356 res
= objc_read_array (stream
, t
, len
, va_arg (args
, void *));
1357 t
= objc_skip_typespec (t
);
1359 objc_error (nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1364 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1365 "objc_read_types: cannot parse typespec: %s\n", type
);
1373 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1374 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1378 objc_write_array (TypedStream
*stream
, const char *type
,
1379 int count
, const void *data
)
1381 int off
= objc_sizeof_type(type
);
1382 const char *where
= data
;
1386 objc_write_type(stream
, type
, where
);
1393 ** Read an array of COUNT elements of TYPE into the memory address
1394 ** DATA. The memory pointed to by data is supposed to be allocated
1395 ** by the callee. This is equivalent of
1396 ** objc_read_type (stream, "[N<type>]", data)
1400 objc_read_array (TypedStream
*stream
, const char *type
,
1401 int count
, void *data
)
1403 int off
= objc_sizeof_type(type
);
1404 char *where
= (char*)data
;
1408 objc_read_type(stream
, type
, where
);
1415 __objc_fread (FILE *file
, char *data
, int len
)
1417 return fread(data
, len
, 1, file
);
1421 __objc_fwrite (FILE *file
, char *data
, int len
)
1423 return fwrite(data
, len
, 1, file
);
1427 __objc_feof (FILE *file
)
1433 __objc_no_write (FILE *file
__attribute__ ((__unused__
)),
1434 const char *data
__attribute__ ((__unused__
)),
1435 int len
__attribute__ ((__unused__
)))
1437 objc_error (nil
, OBJC_ERR_NO_WRITE
, "TypedStream not open for writing");
1442 __objc_no_read (FILE *file
__attribute__ ((__unused__
)),
1443 const char *data
__attribute__ ((__unused__
)),
1444 int len
__attribute__ ((__unused__
)))
1446 objc_error (nil
, OBJC_ERR_NO_READ
, "TypedStream not open for reading");
1451 __objc_read_typed_stream_signature (TypedStream
*stream
)
1456 (*stream
->read
) (stream
->physical
, buffer
+pos
, 1);
1457 while (buffer
[pos
++] != '\0')
1459 sscanf (buffer
, "GNU TypedStream %d", &stream
->version
);
1460 if (stream
->version
!= OBJC_TYPED_STREAM_VERSION
)
1461 objc_error (nil
, OBJC_ERR_STREAM_VERSION
,
1462 "cannot handle TypedStream version %d", stream
->version
);
1467 __objc_write_typed_stream_signature (TypedStream
*stream
)
1470 sprintf(buffer
, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION
);
1471 stream
->version
= OBJC_TYPED_STREAM_VERSION
;
1472 (*stream
->write
) (stream
->physical
, buffer
, strlen (buffer
) + 1);
1476 static void __objc_finish_write_root_object(struct objc_typed_stream
*stream
)
1478 hash_delete (stream
->object_table
);
1479 stream
->object_table
= hash_new(64,
1480 (hash_func_type
)hash_ptr
,
1481 (compare_func_type
)compare_ptrs
);
1484 static void __objc_finish_read_root_object(struct objc_typed_stream
*stream
)
1487 SEL awake_sel
= sel_get_any_uid ("awake");
1488 cache_ptr free_list
= hash_new (64,
1489 (hash_func_type
) hash_ptr
,
1490 (compare_func_type
) compare_ptrs
);
1492 /* resolve object forward references */
1493 for (node
= hash_next (stream
->object_refs
, NULL
); node
;
1494 node
= hash_next (stream
->object_refs
, node
))
1496 struct objc_list
*reflist
= node
->value
;
1497 const void *key
= node
->key
;
1498 id object
= hash_value_for_key (stream
->object_table
, key
);
1501 *((id
*) reflist
->head
) = object
;
1502 if (hash_value_for_key (free_list
,reflist
) == NULL
)
1503 hash_add (&free_list
,reflist
,reflist
);
1505 reflist
= reflist
->tail
;
1509 /* apply __objc_free to all objects stored in free_list */
1510 for (node
= hash_next (free_list
, NULL
); node
;
1511 node
= hash_next (free_list
, node
))
1512 objc_free ((void *) node
->key
);
1514 hash_delete (free_list
);
1516 /* empty object reference table */
1517 hash_delete (stream
->object_refs
);
1518 stream
->object_refs
= hash_new(8, (hash_func_type
)hash_ptr
,
1519 (compare_func_type
)compare_ptrs
);
1521 /* call -awake for all objects read */
1524 for (node
= hash_next (stream
->object_table
, NULL
); node
;
1525 node
= hash_next (stream
->object_table
, node
))
1527 id object
= node
->value
;
1528 if (__objc_responds_to (object
, awake_sel
))
1529 (*objc_msg_lookup (object
, awake_sel
)) (object
, awake_sel
);
1533 /* empty object table */
1534 hash_delete (stream
->object_table
);
1535 stream
->object_table
= hash_new(64,
1536 (hash_func_type
)hash_ptr
,
1537 (compare_func_type
)compare_ptrs
);
1541 ** Open the stream PHYSICAL in MODE
1545 objc_open_typed_stream (FILE *physical
, int mode
)
1547 TypedStream
*s
= (TypedStream
*) objc_malloc (sizeof (TypedStream
));
1550 s
->physical
= physical
;
1551 s
->stream_table
= hash_new (64,
1552 (hash_func_type
) hash_ptr
,
1553 (compare_func_type
) compare_ptrs
);
1554 s
->object_table
= hash_new (64,
1555 (hash_func_type
) hash_ptr
,
1556 (compare_func_type
) compare_ptrs
);
1557 s
->eof
= (objc_typed_eof_func
) __objc_feof
;
1558 s
->flush
= (objc_typed_flush_func
) fflush
;
1559 s
->writing_root_p
= 0;
1560 if (mode
== OBJC_READONLY
)
1562 s
->class_table
= hash_new (8, (hash_func_type
) hash_string
,
1563 (compare_func_type
) compare_strings
);
1564 s
->object_refs
= hash_new (8, (hash_func_type
) hash_ptr
,
1565 (compare_func_type
) compare_ptrs
);
1566 s
->read
= (objc_typed_read_func
) __objc_fread
;
1567 s
->write
= (objc_typed_write_func
) __objc_no_write
;
1568 __objc_read_typed_stream_signature (s
);
1570 else if (mode
== OBJC_WRITEONLY
)
1574 s
->read
= (objc_typed_read_func
) __objc_no_read
;
1575 s
->write
= (objc_typed_write_func
) __objc_fwrite
;
1576 __objc_write_typed_stream_signature (s
);
1580 objc_close_typed_stream (s
);
1583 s
->type
= OBJC_FILE_STREAM
;
1588 ** Open the file named by FILE_NAME in MODE
1592 objc_open_typed_stream_for_file (const char *file_name
, int mode
)
1597 if (mode
== OBJC_READONLY
)
1598 file
= fopen (file_name
, "r");
1600 file
= fopen (file_name
, "w");
1604 s
= objc_open_typed_stream (file
, mode
);
1606 s
->type
|= OBJC_MANAGED_STREAM
;
1614 ** Close STREAM freeing the structure it self. If it was opened with
1615 ** objc_open_typed_stream_for_file, the file will also be closed.
1619 objc_close_typed_stream (TypedStream
*stream
)
1621 if (stream
->mode
== OBJC_READONLY
)
1623 __objc_finish_read_root_object (stream
); /* Just in case... */
1624 hash_delete (stream
->class_table
);
1625 hash_delete (stream
->object_refs
);
1628 hash_delete (stream
->stream_table
);
1629 hash_delete (stream
->object_table
);
1631 if (stream
->type
== (OBJC_MANAGED_STREAM
| OBJC_FILE_STREAM
))
1632 fclose ((FILE *)stream
->physical
);
1638 objc_end_of_typed_stream (TypedStream
*stream
)
1640 return (*stream
->eof
) (stream
->physical
);
1644 objc_flush_typed_stream (TypedStream
*stream
)
1646 (*stream
->flush
) (stream
->physical
);
1650 objc_get_stream_class_version (TypedStream
*stream
, Class
class)
1652 if (stream
->class_table
)
1653 return PTR2LONG(hash_value_for_key (stream
->class_table
, class->name
));
1655 return class_get_version (class);