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(objc_hash_value_for_key (stream
->stream_table
, string
))))
305 return objc_write_use_common (stream
, key
);
309 objc_hash_add (&stream
->stream_table
,
310 LONG2PTR(key
=PTR2LONG(string
)), string
);
311 if ((length
= objc_write_register_common (stream
, key
)))
312 return objc_write_string (stream
, string
, nbytes
);
318 objc_write_register_common (struct objc_typed_stream
*stream
,
321 unsigned char buf
[sizeof (unsigned long)+2];
322 int len
= __objc_code_unsigned_long (buf
+ 1, key
);
325 buf
[0] = _B_RCOMM
|0x01;
327 return (*stream
->write
) (stream
->physical
, (char*)buf
, len
+ 1);
331 buf
[1] = (buf
[1]&_B_VALUE
)|_B_RCOMM
;
332 return (*stream
->write
) (stream
->physical
, (char*)buf
+ 1, len
);
337 objc_write_use_common (struct objc_typed_stream
*stream
, unsigned long key
)
339 unsigned char buf
[sizeof (unsigned long)+2];
340 int len
= __objc_code_unsigned_long (buf
+ 1, key
);
343 buf
[0] = _B_UCOMM
|0x01;
345 return (*stream
->write
) (stream
->physical
, (char*)buf
, 2);
349 buf
[1] = (buf
[1]&_B_VALUE
)|_B_UCOMM
;
350 return (*stream
->write
) (stream
->physical
, (char*)buf
+ 1, len
);
355 __objc_write_extension (struct objc_typed_stream
*stream
, unsigned char code
)
357 if (code
<= _B_VALUE
)
359 unsigned char buf
= code
|_B_EXT
;
360 return (*stream
->write
) (stream
->physical
, (char*)&buf
, 1);
364 objc_error (nil
, OBJC_ERR_BAD_OPCODE
,
365 "__objc_write_extension: bad opcode %c\n", code
);
371 __objc_write_object (struct objc_typed_stream
*stream
, id object
)
373 unsigned char buf
= '\0';
374 SEL write_sel
= sel_get_any_uid ("write:");
377 __objc_write_extension (stream
, _BX_OBJECT
);
378 objc_write_class (stream
, object
->class_pointer
);
379 (*objc_msg_lookup (object
, write_sel
)) (object
, write_sel
, stream
);
380 return (*stream
->write
) (stream
->physical
, (char*)&buf
, 1);
383 return objc_write_use_common (stream
, 0);
387 objc_write_object_reference (struct objc_typed_stream
*stream
, id object
)
390 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->object_table
, object
))))
391 return objc_write_use_common (stream
, key
);
393 __objc_write_extension (stream
, _BX_OBJREF
);
394 return objc_write_unsigned_long (stream
, PTR2LONG (object
));
398 objc_write_root_object (struct objc_typed_stream
*stream
, id object
)
401 if (stream
->writing_root_p
)
402 objc_error (nil
, OBJC_ERR_RECURSE_ROOT
,
403 "objc_write_root_object called recursively");
406 stream
->writing_root_p
= 1;
407 __objc_write_extension (stream
, _BX_OBJROOT
);
408 if ((len
= objc_write_object (stream
, object
)))
409 __objc_finish_write_root_object (stream
);
410 stream
->writing_root_p
= 0;
416 objc_write_object (struct objc_typed_stream
*stream
, id object
)
419 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->object_table
, object
))))
420 return objc_write_use_common (stream
, key
);
422 else if (object
== nil
)
423 return objc_write_use_common (stream
, 0);
428 objc_hash_add (&stream
->object_table
,
429 LONG2PTR(key
=PTR2LONG(object
)), object
);
430 if ((length
= objc_write_register_common (stream
, key
)))
431 return __objc_write_object (stream
, object
);
437 __objc_write_class (struct objc_typed_stream
*stream
, struct objc_class
*class)
439 __objc_write_extension (stream
, _BX_CLASS
);
440 objc_write_string_atomic (stream
, (unsigned char *) class->name
,
441 strlen ((char *) class->name
));
442 return objc_write_unsigned_long (stream
, class->version
);
447 objc_write_class (struct objc_typed_stream
*stream
,
448 struct objc_class
*class)
451 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
, class))))
452 return objc_write_use_common (stream
, key
);
456 objc_hash_add (&stream
->stream_table
,
457 LONG2PTR(key
= PTR2LONG(class)), class);
458 if ((length
= objc_write_register_common (stream
, key
)))
459 return __objc_write_class (stream
, class);
466 __objc_write_selector (struct objc_typed_stream
*stream
, SEL selector
)
468 const char *sel_name
;
469 __objc_write_extension (stream
, _BX_SEL
);
470 /* to handle NULL selectors */
471 if ((SEL
)0 == selector
)
472 return objc_write_string (stream
, (unsigned char*)"", 0);
473 sel_name
= sel_get_name (selector
);
474 return objc_write_string (stream
, (unsigned char*)sel_name
, strlen ((char*)sel_name
));
478 objc_write_selector (struct objc_typed_stream
*stream
, SEL selector
)
480 const char *sel_name
;
483 /* to handle NULL selectors */
484 if ((SEL
)0 == selector
)
485 return __objc_write_selector (stream
, selector
);
487 sel_name
= sel_get_name (selector
);
488 if ((key
= PTR2LONG(objc_hash_value_for_key (stream
->stream_table
,
490 return objc_write_use_common (stream
, key
);
494 objc_hash_add (&stream
->stream_table
,
495 LONG2PTR(key
= PTR2LONG(sel_name
)), (char *) sel_name
);
496 if ((length
= objc_write_register_common (stream
, key
)))
497 return __objc_write_selector (stream
, selector
);
509 objc_read_char (struct objc_typed_stream
*stream
, char *val
)
513 len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1);
516 if ((buf
& _B_CODE
) == _B_SINT
)
517 (*val
) = (buf
& _B_VALUE
);
519 else if ((buf
& _B_NUMBER
) == 1)
521 len
= (*stream
->read
) (stream
->physical
, val
, 1);
523 (*val
) = -1 * (*val
);
527 objc_error (nil
, OBJC_ERR_BAD_DATA
,
528 "expected 8bit signed int, got %dbit int",
529 (int) (buf
&_B_NUMBER
)*8);
536 objc_read_unsigned_char (struct objc_typed_stream
*stream
, unsigned char *val
)
540 if ((len
= (*stream
->read
) (stream
->physical
, (char*)&buf
, 1)))
542 if ((buf
& _B_CODE
) == _B_SINT
)
543 (*val
) = (buf
& _B_VALUE
);
545 else if ((buf
& _B_NUMBER
) == 1)
546 len
= (*stream
->read
) (stream
->physical
, (char*)val
, 1);
549 objc_error (nil
, OBJC_ERR_BAD_DATA
,
550 "expected 8bit unsigned int, got %dbit int",
551 (int) (buf
&_B_NUMBER
)*8);
557 objc_read_short (struct objc_typed_stream
*stream
, short *value
)
559 unsigned char buf
[sizeof (short) + 1];
561 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
563 if ((buf
[0] & _B_CODE
) == _B_SINT
)
564 (*value
) = (buf
[0] & _B_VALUE
);
569 int nbytes
= buf
[0] & _B_NUMBER
;
570 if (nbytes
> (int) sizeof (short))
571 objc_error (nil
, OBJC_ERR_BAD_DATA
,
572 "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_error (nil
, OBJC_ERR_BAD_DATA
,
601 "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_error (nil
, OBJC_ERR_BAD_DATA
, "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_error (nil
, OBJC_ERR_BAD_DATA
, "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_error (nil
, OBJC_ERR_BAD_DATA
, "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_error (nil
, OBJC_ERR_BAD_DATA
, "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_error (nil
, OBJC_ERR_BAD_DATA
,
794 "expected string, got opcode %c\n", (buf
[0]&_B_CODE
));
803 objc_read_object (struct objc_typed_stream
*stream
, id
*object
)
805 unsigned char buf
[sizeof (unsigned int)];
807 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
809 SEL read_sel
= sel_get_any_uid ("read:");
810 unsigned long key
= 0;
812 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register common */
814 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
815 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
818 if (buf
[0] == (_B_EXT
| _BX_OBJECT
))
823 len
= objc_read_class (stream
, &class);
825 /* create instance */
826 (*object
) = class_create_instance (class);
830 objc_hash_add (&stream
->object_table
, LONG2PTR(key
), *object
);
833 if (__objc_responds_to (*object
, read_sel
))
834 (*get_imp (class, read_sel
)) (*object
, read_sel
, stream
);
836 /* check null-byte */
837 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
839 objc_error (nil
, OBJC_ERR_BAD_DATA
,
840 "expected null-byte, got opcode %c", buf
[0]);
843 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
846 objc_error (nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
847 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
848 (*object
) = objc_hash_value_for_key (stream
->object_table
,
852 else if (buf
[0] == (_B_EXT
| _BX_OBJREF
)) /* a forward reference */
854 struct objc_list
*other
;
855 len
= objc_read_unsigned_long (stream
, &key
);
857 = (struct objc_list
*) objc_hash_value_for_key (stream
->object_refs
,
859 objc_hash_add (&stream
->object_refs
, LONG2PTR(key
),
860 (void *)list_cons (object
, other
));
863 else if (buf
[0] == (_B_EXT
| _BX_OBJROOT
)) /* a root object */
866 objc_error (nil
, OBJC_ERR_BAD_KEY
,
867 "cannot register root object...");
868 len
= objc_read_object (stream
, object
);
869 __objc_finish_read_root_object (stream
);
873 objc_error (nil
, OBJC_ERR_BAD_DATA
,
874 "expected object, got opcode %c", buf
[0]);
880 objc_read_class (struct objc_typed_stream
*stream
, Class
*class)
882 unsigned char buf
[sizeof (unsigned int)];
884 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
886 unsigned long key
= 0;
888 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
890 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
891 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
894 if (buf
[0] == (_B_EXT
| _BX_CLASS
))
897 char *class_name
= temp
;
898 unsigned long version
;
901 len
= objc_read_string (stream
, &class_name
);
902 (*class) = objc_get_class (class_name
);
903 objc_free (class_name
);
907 objc_hash_add (&stream
->stream_table
, LONG2PTR(key
), *class);
909 objc_read_unsigned_long (stream
, &version
);
910 objc_hash_add (&stream
->class_table
,
911 (*class)->name
, (void *)version
);
914 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
917 objc_error (nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
918 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
919 *class = objc_hash_value_for_key (stream
->stream_table
,
922 objc_error (nil
, OBJC_ERR_BAD_CLASS
,
923 "cannot find class for key %lu", key
);
927 objc_error (nil
, OBJC_ERR_BAD_DATA
,
928 "expected class, got opcode %c", buf
[0]);
934 objc_read_selector (struct objc_typed_stream
*stream
, SEL
* selector
)
936 unsigned char buf
[sizeof (unsigned int)];
938 if ((len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1)))
940 unsigned long key
= 0;
942 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
944 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
945 len
= (*stream
->read
) (stream
->physical
, (char*)buf
, 1);
948 if (buf
[0] == (_B_EXT
|_BX_SEL
)) /* selector! */
951 char *selector_name
= temp
;
954 len
= objc_read_string (stream
, &selector_name
);
955 /* To handle NULL selectors */
956 if (0 == strlen (selector_name
))
958 (*selector
) = (SEL
)0;
962 (*selector
) = sel_get_any_uid (selector_name
);
963 objc_free (selector_name
);
967 objc_hash_add (&stream
->stream_table
,
968 LONG2PTR(key
), (void *) *selector
);
971 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
974 objc_error (nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
975 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), &key
);
976 (*selector
) = objc_hash_value_for_key (stream
->stream_table
,
981 objc_error (nil
, OBJC_ERR_BAD_DATA
,
982 "expected selector, got opcode %c", buf
[0]);
988 ** USER LEVEL FUNCTIONS
992 ** Write one object, encoded in TYPE and pointed to by DATA to the
993 ** typed stream STREAM.
997 objc_write_type (TypedStream
*stream
, const char *type
, const void *data
)
1001 return objc_write_object (stream
, *(id
*) data
);
1005 return objc_write_class (stream
, *(Class
*) data
);
1009 return objc_write_selector (stream
, *(SEL
*) data
);
1013 return objc_write_char (stream
, *(signed char *) data
);
1017 return objc_write_unsigned_char (stream
, *(unsigned char *) data
);
1021 return objc_write_short (stream
, *(short *) data
);
1025 return objc_write_unsigned_short (stream
, *(unsigned short *) data
);
1029 return objc_write_int (stream
, *(int *) data
);
1033 return objc_write_unsigned_int (stream
, *(unsigned int *) data
);
1037 return objc_write_long (stream
, *(long *) data
);
1041 return objc_write_unsigned_long (stream
, *(unsigned long *) data
);
1045 return objc_write_string (stream
,
1046 *(unsigned char **) data
, strlen (*(char **) data
));
1050 return objc_write_string_atomic (stream
, *(unsigned char **) data
,
1051 strlen (*(char **) data
));
1056 int len
= atoi (type
+ 1);
1057 while (isdigit ((unsigned char) *++type
))
1059 return objc_write_array (stream
, type
, len
, data
);
1067 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1068 ; /* skip "<name>=" */
1069 while (*type
!= _C_STRUCT_E
)
1071 align
= objc_alignof_type (type
); /* padd to alignment */
1072 acc_size
+= ROUND (acc_size
, align
);
1073 objc_write_type (stream
, type
, ((char *) data
) + acc_size
);
1074 acc_size
+= objc_sizeof_type (type
); /* add component size */
1075 type
= objc_skip_typespec (type
); /* skip component */
1082 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1083 "objc_write_type: cannot parse typespec: %s\n", type
);
1090 ** Read one object, encoded in TYPE and pointed to by DATA to the
1091 ** typed stream STREAM. DATA specifies the address of the types to
1092 ** read. Expected type is checked against the type actually present
1097 objc_read_type(TypedStream
*stream
, const char *type
, void *data
)
1100 switch (c
= *type
) {
1102 return objc_read_object (stream
, (id
*)data
);
1106 return objc_read_class (stream
, (Class
*)data
);
1110 return objc_read_selector (stream
, (SEL
*)data
);
1114 return objc_read_char (stream
, (char*)data
);
1118 return objc_read_unsigned_char (stream
, (unsigned char*)data
);
1122 return objc_read_short (stream
, (short*)data
);
1126 return objc_read_unsigned_short (stream
, (unsigned short*)data
);
1130 return objc_read_int (stream
, (int*)data
);
1134 return objc_read_unsigned_int (stream
, (unsigned int*)data
);
1138 return objc_read_long (stream
, (long*)data
);
1142 return objc_read_unsigned_long (stream
, (unsigned long*)data
);
1147 return objc_read_string (stream
, (char**)data
);
1152 int len
= atoi (type
+ 1);
1153 while (isdigit ((unsigned char) *++type
))
1155 return objc_read_array (stream
, type
, len
, data
);
1163 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1164 ; /* skip "<name>=" */
1165 while (*type
!= _C_STRUCT_E
)
1167 align
= objc_alignof_type (type
); /* padd to alignment */
1168 acc_size
+= ROUND (acc_size
, align
);
1169 objc_read_type (stream
, type
, ((char*)data
)+acc_size
);
1170 acc_size
+= objc_sizeof_type (type
); /* add component size */
1171 type
= objc_skip_typespec (type
); /* skip component */
1178 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1179 "objc_read_type: cannot parse typespec: %s\n", type
);
1186 ** Write the object specified by the template TYPE to STREAM. Last
1187 ** arguments specify addresses of values to be written. It might
1188 ** seem surprising to specify values by address, but this is extremely
1189 ** convenient for copy-paste with objc_read_types calls. A more
1190 ** down-to-the-earth cause for this passing of addresses is that values
1191 ** of arbitrary size is not well supported in ANSI C for functions with
1192 ** variable number of arguments.
1196 objc_write_types (TypedStream
*stream
, const char *type
, ...)
1202 va_start(args
, type
);
1204 for (c
= type
; *c
; c
= objc_skip_typespec (c
))
1208 res
= objc_write_object (stream
, *va_arg (args
, id
*));
1212 res
= objc_write_class (stream
, *va_arg (args
, Class
*));
1216 res
= objc_write_selector (stream
, *va_arg (args
, SEL
*));
1220 res
= objc_write_char (stream
, *va_arg (args
, char*));
1224 res
= objc_write_unsigned_char (stream
,
1225 *va_arg (args
, unsigned char*));
1229 res
= objc_write_short (stream
, *va_arg (args
, short*));
1233 res
= objc_write_unsigned_short (stream
,
1234 *va_arg (args
, unsigned short*));
1238 res
= objc_write_int(stream
, *va_arg (args
, int*));
1242 res
= objc_write_unsigned_int(stream
, *va_arg (args
, unsigned int*));
1246 res
= objc_write_long(stream
, *va_arg (args
, long*));
1250 res
= objc_write_unsigned_long(stream
, *va_arg (args
, unsigned long*));
1255 unsigned char **str
= va_arg (args
, unsigned char **);
1256 res
= objc_write_string (stream
, *str
, strlen ((char*)*str
));
1262 unsigned char **str
= va_arg (args
, unsigned char **);
1263 res
= objc_write_string_atomic (stream
, *str
, strlen ((char*)*str
));
1269 int len
= atoi (c
+ 1);
1271 while (isdigit ((unsigned char) *++t
))
1273 res
= objc_write_array (stream
, t
, len
, va_arg (args
, void *));
1274 t
= objc_skip_typespec (t
);
1276 objc_error (nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1281 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1282 "objc_write_types: cannot parse typespec: %s\n", type
);
1291 ** Last arguments specify addresses of values to be read. Expected
1292 ** type is checked against the type actually present on the stream.
1296 objc_read_types(TypedStream
*stream
, const char *type
, ...)
1302 va_start (args
, type
);
1304 for (c
= type
; *c
; c
= objc_skip_typespec(c
))
1308 res
= objc_read_object(stream
, va_arg (args
, id
*));
1312 res
= objc_read_class(stream
, va_arg (args
, Class
*));
1316 res
= objc_read_selector(stream
, va_arg (args
, SEL
*));
1320 res
= objc_read_char(stream
, va_arg (args
, char*));
1324 res
= objc_read_unsigned_char(stream
, va_arg (args
, unsigned char*));
1328 res
= objc_read_short(stream
, va_arg (args
, short*));
1332 res
= objc_read_unsigned_short(stream
, va_arg (args
, unsigned short*));
1336 res
= objc_read_int(stream
, va_arg (args
, int*));
1340 res
= objc_read_unsigned_int(stream
, va_arg (args
, unsigned int*));
1344 res
= objc_read_long(stream
, va_arg (args
, long*));
1348 res
= objc_read_unsigned_long(stream
, va_arg (args
, unsigned long*));
1354 char **str
= va_arg (args
, char **);
1355 res
= objc_read_string (stream
, str
);
1361 int len
= atoi (c
+ 1);
1363 while (isdigit ((unsigned char) *++t
))
1365 res
= objc_read_array (stream
, t
, len
, va_arg (args
, void *));
1366 t
= objc_skip_typespec (t
);
1368 objc_error (nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1373 objc_error (nil
, OBJC_ERR_BAD_TYPE
,
1374 "objc_read_types: cannot parse typespec: %s\n", type
);
1382 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1383 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1387 objc_write_array (TypedStream
*stream
, const char *type
,
1388 int count
, const void *data
)
1390 int off
= objc_sizeof_type(type
);
1391 const char *where
= data
;
1395 objc_write_type(stream
, type
, where
);
1402 ** Read an array of COUNT elements of TYPE into the memory address
1403 ** DATA. The memory pointed to by data is supposed to be allocated
1404 ** by the callee. This is equivalent of
1405 ** objc_read_type (stream, "[N<type>]", data)
1409 objc_read_array (TypedStream
*stream
, const char *type
,
1410 int count
, void *data
)
1412 int off
= objc_sizeof_type(type
);
1413 char *where
= (char*)data
;
1417 objc_read_type(stream
, type
, where
);
1424 __objc_fread (FILE *file
, char *data
, int len
)
1426 return fread(data
, len
, 1, file
);
1430 __objc_fwrite (FILE *file
, char *data
, int len
)
1432 return fwrite(data
, len
, 1, file
);
1436 __objc_feof (FILE *file
)
1442 __objc_no_write (FILE *file
__attribute__ ((__unused__
)),
1443 const char *data
__attribute__ ((__unused__
)),
1444 int len
__attribute__ ((__unused__
)))
1446 objc_error (nil
, OBJC_ERR_NO_WRITE
, "TypedStream not open for writing");
1451 __objc_no_read (FILE *file
__attribute__ ((__unused__
)),
1452 const char *data
__attribute__ ((__unused__
)),
1453 int len
__attribute__ ((__unused__
)))
1455 objc_error (nil
, OBJC_ERR_NO_READ
, "TypedStream not open for reading");
1460 __objc_read_typed_stream_signature (TypedStream
*stream
)
1465 (*stream
->read
) (stream
->physical
, buffer
+pos
, 1);
1466 while (buffer
[pos
++] != '\0')
1468 sscanf (buffer
, "GNU TypedStream %d", &stream
->version
);
1469 if (stream
->version
!= OBJC_TYPED_STREAM_VERSION
)
1470 objc_error (nil
, OBJC_ERR_STREAM_VERSION
,
1471 "cannot handle TypedStream version %d", stream
->version
);
1476 __objc_write_typed_stream_signature (TypedStream
*stream
)
1479 sprintf(buffer
, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION
);
1480 stream
->version
= OBJC_TYPED_STREAM_VERSION
;
1481 (*stream
->write
) (stream
->physical
, buffer
, strlen (buffer
) + 1);
1485 static void __objc_finish_write_root_object(struct objc_typed_stream
*stream
)
1487 objc_hash_delete (stream
->object_table
);
1488 stream
->object_table
= objc_hash_new (64,
1489 (hash_func_type
) objc_hash_ptr
,
1490 (compare_func_type
) objc_compare_ptrs
);
1493 static void __objc_finish_read_root_object(struct objc_typed_stream
*stream
)
1496 SEL awake_sel
= sel_get_any_uid ("awake");
1497 cache_ptr free_list
= objc_hash_new (64,
1498 (hash_func_type
) objc_hash_ptr
,
1499 (compare_func_type
) objc_compare_ptrs
);
1501 /* resolve object forward references */
1502 for (node
= objc_hash_next (stream
->object_refs
, NULL
); node
;
1503 node
= objc_hash_next (stream
->object_refs
, node
))
1505 struct objc_list
*reflist
= node
->value
;
1506 const void *key
= node
->key
;
1507 id object
= objc_hash_value_for_key (stream
->object_table
, key
);
1510 *((id
*) reflist
->head
) = object
;
1511 if (objc_hash_value_for_key (free_list
,reflist
) == NULL
)
1512 objc_hash_add (&free_list
,reflist
,reflist
);
1514 reflist
= reflist
->tail
;
1518 /* apply __objc_free to all objects stored in free_list */
1519 for (node
= objc_hash_next (free_list
, NULL
); node
;
1520 node
= objc_hash_next (free_list
, node
))
1521 objc_free ((void *) node
->key
);
1523 objc_hash_delete (free_list
);
1525 /* empty object reference table */
1526 objc_hash_delete (stream
->object_refs
);
1527 stream
->object_refs
= objc_hash_new (8, (hash_func_type
) objc_hash_ptr
,
1528 (compare_func_type
) objc_compare_ptrs
);
1530 /* call -awake for all objects read */
1533 for (node
= objc_hash_next (stream
->object_table
, NULL
); node
;
1534 node
= objc_hash_next (stream
->object_table
, node
))
1536 id object
= node
->value
;
1537 if (__objc_responds_to (object
, awake_sel
))
1538 (*objc_msg_lookup (object
, awake_sel
)) (object
, awake_sel
);
1542 /* empty object table */
1543 objc_hash_delete (stream
->object_table
);
1544 stream
->object_table
= objc_hash_new(64,
1545 (hash_func_type
)objc_hash_ptr
,
1546 (compare_func_type
)objc_compare_ptrs
);
1550 ** Open the stream PHYSICAL in MODE
1554 objc_open_typed_stream (FILE *physical
, int mode
)
1556 TypedStream
*s
= (TypedStream
*) objc_malloc (sizeof (TypedStream
));
1559 s
->physical
= physical
;
1560 s
->stream_table
= objc_hash_new (64,
1561 (hash_func_type
) objc_hash_ptr
,
1562 (compare_func_type
) objc_compare_ptrs
);
1563 s
->object_table
= objc_hash_new (64,
1564 (hash_func_type
) objc_hash_ptr
,
1565 (compare_func_type
) objc_compare_ptrs
);
1566 s
->eof
= (objc_typed_eof_func
) __objc_feof
;
1567 s
->flush
= (objc_typed_flush_func
) fflush
;
1568 s
->writing_root_p
= 0;
1569 if (mode
== OBJC_READONLY
)
1572 = objc_hash_new (8, (hash_func_type
) objc_hash_string
,
1573 (compare_func_type
) objc_compare_strings
);
1574 s
->object_refs
= objc_hash_new (8, (hash_func_type
) objc_hash_ptr
,
1575 (compare_func_type
) objc_compare_ptrs
);
1576 s
->read
= (objc_typed_read_func
) __objc_fread
;
1577 s
->write
= (objc_typed_write_func
) __objc_no_write
;
1578 __objc_read_typed_stream_signature (s
);
1580 else if (mode
== OBJC_WRITEONLY
)
1584 s
->read
= (objc_typed_read_func
) __objc_no_read
;
1585 s
->write
= (objc_typed_write_func
) __objc_fwrite
;
1586 __objc_write_typed_stream_signature (s
);
1590 objc_close_typed_stream (s
);
1593 s
->type
= OBJC_FILE_STREAM
;
1598 ** Open the file named by FILE_NAME in MODE
1602 objc_open_typed_stream_for_file (const char *file_name
, int mode
)
1607 if (mode
== OBJC_READONLY
)
1608 file
= fopen (file_name
, "r");
1610 file
= fopen (file_name
, "w");
1614 s
= objc_open_typed_stream (file
, mode
);
1616 s
->type
|= OBJC_MANAGED_STREAM
;
1624 ** Close STREAM freeing the structure it self. If it was opened with
1625 ** objc_open_typed_stream_for_file, the file will also be closed.
1629 objc_close_typed_stream (TypedStream
*stream
)
1631 if (stream
->mode
== OBJC_READONLY
)
1633 __objc_finish_read_root_object (stream
); /* Just in case... */
1634 objc_hash_delete (stream
->class_table
);
1635 objc_hash_delete (stream
->object_refs
);
1638 objc_hash_delete (stream
->stream_table
);
1639 objc_hash_delete (stream
->object_table
);
1641 if (stream
->type
== (OBJC_MANAGED_STREAM
| OBJC_FILE_STREAM
))
1642 fclose ((FILE *)stream
->physical
);
1648 objc_end_of_typed_stream (TypedStream
*stream
)
1650 return (*stream
->eof
) (stream
->physical
);
1654 objc_flush_typed_stream (TypedStream
*stream
)
1656 (*stream
->flush
) (stream
->physical
);
1660 objc_get_stream_class_version (TypedStream
*stream
, Class
class)
1662 if (stream
->class_table
)
1663 return PTR2LONG(objc_hash_value_for_key (stream
->class_table
,
1666 return class_get_version (class);