1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
3 Contributed by Kresten Krab Thorup
5 This file is part of GNU CC.
7 GNU CC 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 GNU CC 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 GNU CC; 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"
36 extern int fflush(FILE*);
39 ({ typeof(V) __v=(V); typeof(A) __a=(A); \
40 __a*((__v+__a-1)/__a); })
42 #define PTR2LONG(P) (((char*)(P))-(char*)0)
43 #define LONG2PTR(L) (((char*)0)+(L))
45 /* Declare some functions... */
48 objc_read_class (struct objc_typed_stream
* stream
, Class
* class);
50 int objc_sizeof_type(const char* type
);
53 objc_write_use_common (struct objc_typed_stream
* stream
, unsigned long key
);
56 objc_write_register_common (struct objc_typed_stream
* stream
,
60 objc_write_class (struct objc_typed_stream
* stream
,
61 struct objc_class
* class);
63 const char* objc_skip_type (const char* type
);
65 static void __objc_finish_write_root_object(struct objc_typed_stream
*);
66 static void __objc_finish_read_root_object(struct objc_typed_stream
*);
69 __objc_code_unsigned_char (unsigned char* buf
, unsigned char val
)
71 if ((val
&_B_VALUE
) == val
)
78 buf
[0] = _B_NINT
|0x01;
85 objc_write_unsigned_char (struct objc_typed_stream
* stream
,
88 unsigned char buf
[sizeof (unsigned char)+1];
89 int len
= __objc_code_unsigned_char (buf
, value
);
90 return (*stream
->write
)(stream
->physical
, buf
, len
);
94 __objc_code_char (unsigned char* buf
, signed char val
)
97 return __objc_code_unsigned_char (buf
, val
);
100 buf
[0] = _B_NINT
|_B_SIGN
|0x01;
107 objc_write_char (struct objc_typed_stream
* stream
, signed char value
)
109 unsigned char buf
[sizeof (char)+1];
110 int len
= __objc_code_char (buf
, value
);
111 return (*stream
->write
)(stream
->physical
, buf
, len
);
114 static __inline__
int
115 __objc_code_unsigned_short (unsigned char* buf
, unsigned short val
)
117 if ((val
&_B_VALUE
) == val
)
119 buf
[0] = val
|_B_SINT
;
128 for (c
= sizeof(short); c
!= 0; c
-= 1)
129 if (((val
>>(8*(c
-1)))%0x100) != 0)
134 for (b
= 1; c
!= 0; c
--, b
++)
136 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
144 objc_write_unsigned_short (struct objc_typed_stream
* stream
,
145 unsigned short value
)
147 unsigned char buf
[sizeof (unsigned short)+1];
148 int len
= __objc_code_unsigned_short (buf
, value
);
149 return (*stream
->write
)(stream
->physical
, buf
, len
);
152 static __inline__
int
153 __objc_code_short (unsigned char* buf
, short val
)
155 int sign
= (val
< 0);
156 int size
= __objc_code_unsigned_short (buf
, sign
? -val
: val
);
163 objc_write_short (struct objc_typed_stream
* stream
, short value
)
165 unsigned char buf
[sizeof (short)+1];
166 int len
= __objc_code_short (buf
, value
);
167 return (*stream
->write
)(stream
->physical
, buf
, len
);
171 static __inline__
int
172 __objc_code_unsigned_int (unsigned char* buf
, unsigned int val
)
174 if ((val
&_B_VALUE
) == val
)
176 buf
[0] = val
|_B_SINT
;
185 for (c
= sizeof(int); c
!= 0; c
-= 1)
186 if (((val
>>(8*(c
-1)))%0x100) != 0)
191 for (b
= 1; c
!= 0; c
--, b
++)
193 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
201 objc_write_unsigned_int (struct objc_typed_stream
* stream
, unsigned int value
)
203 unsigned char buf
[sizeof(unsigned int)+1];
204 int len
= __objc_code_unsigned_int (buf
, value
);
205 return (*stream
->write
)(stream
->physical
, buf
, len
);
208 static __inline__
int
209 __objc_code_int (unsigned char* buf
, int val
)
211 int sign
= (val
< 0);
212 int size
= __objc_code_unsigned_int (buf
, sign
? -val
: val
);
219 objc_write_int (struct objc_typed_stream
* stream
, int value
)
221 unsigned char buf
[sizeof(int)+1];
222 int len
= __objc_code_int (buf
, value
);
223 return (*stream
->write
)(stream
->physical
, buf
, len
);
226 static __inline__
int
227 __objc_code_unsigned_long (unsigned char* buf
, unsigned long val
)
229 if ((val
&_B_VALUE
) == val
)
231 buf
[0] = val
|_B_SINT
;
240 for (c
= sizeof(long); c
!= 0; c
-= 1)
241 if (((val
>>(8*(c
-1)))%0x100) != 0)
246 for (b
= 1; c
!= 0; c
--, b
++)
248 buf
[b
] = (val
>> (8*(c
-1)))%0x100;
256 objc_write_unsigned_long (struct objc_typed_stream
* stream
,
259 unsigned char buf
[sizeof(unsigned long)+1];
260 int len
= __objc_code_unsigned_long (buf
, value
);
261 return (*stream
->write
)(stream
->physical
, buf
, len
);
264 static __inline__
int
265 __objc_code_long (unsigned char* buf
, long val
)
267 int sign
= (val
< 0);
268 int size
= __objc_code_unsigned_long (buf
, sign
? -val
: val
);
275 objc_write_long (struct objc_typed_stream
* stream
, long value
)
277 unsigned char buf
[sizeof(long)+1];
278 int len
= __objc_code_long (buf
, value
);
279 return (*stream
->write
)(stream
->physical
, buf
, len
);
284 objc_write_string (struct objc_typed_stream
* stream
,
285 const unsigned char* string
, unsigned int nbytes
)
287 unsigned char buf
[sizeof(unsigned int)+1];
288 int len
= __objc_code_unsigned_int (buf
, nbytes
);
290 if ((buf
[0]&_B_CODE
) == _B_SINT
)
291 buf
[0] = (buf
[0]&_B_VALUE
)|_B_SSTR
;
294 buf
[0] = (buf
[0]&_B_VALUE
)|_B_NSTR
;
296 if ((*stream
->write
)(stream
->physical
, buf
, len
) != 0)
297 return (*stream
->write
)(stream
->physical
, string
, nbytes
);
303 objc_write_string_atomic (struct objc_typed_stream
* stream
,
304 unsigned char* string
, unsigned int nbytes
)
307 if ((key
= PTR2LONG(hash_value_for_key (stream
->stream_table
, string
))))
308 return objc_write_use_common (stream
, key
);
312 hash_add (&stream
->stream_table
, LONG2PTR(key
=PTR2LONG(string
)), string
);
313 if ((length
= objc_write_register_common (stream
, key
)))
314 return objc_write_string (stream
, string
, nbytes
);
320 objc_write_register_common (struct objc_typed_stream
* stream
,
323 unsigned char buf
[sizeof (unsigned long)+2];
324 int len
= __objc_code_unsigned_long (buf
+1, key
);
327 buf
[0] = _B_RCOMM
|0x01;
329 return (*stream
->write
)(stream
->physical
, buf
, len
+1);
333 buf
[1] = (buf
[1]&_B_VALUE
)|_B_RCOMM
;
334 return (*stream
->write
)(stream
->physical
, buf
+1, len
);
339 objc_write_use_common (struct objc_typed_stream
* stream
, unsigned long key
)
341 unsigned char buf
[sizeof (unsigned long)+2];
342 int len
= __objc_code_unsigned_long (buf
+1, key
);
345 buf
[0] = _B_UCOMM
|0x01;
347 return (*stream
->write
)(stream
->physical
, buf
, 2);
351 buf
[1] = (buf
[1]&_B_VALUE
)|_B_UCOMM
;
352 return (*stream
->write
)(stream
->physical
, buf
+1, len
);
356 static __inline__
int
357 __objc_write_extension (struct objc_typed_stream
* stream
, unsigned char code
)
359 if (code
<= _B_VALUE
)
361 unsigned char buf
= code
|_B_EXT
;
362 return (*stream
->write
)(stream
->physical
, &buf
, 1);
366 objc_error(nil
, OBJC_ERR_BAD_OPCODE
,
367 "__objc_write_extension: bad opcode %c\n", code
);
373 __objc_write_object (struct objc_typed_stream
* stream
, id object
)
375 unsigned char buf
= '\0';
376 SEL write_sel
= sel_get_any_uid ("write:");
379 __objc_write_extension (stream
, _BX_OBJECT
);
380 objc_write_class (stream
, object
->class_pointer
);
381 (*objc_msg_lookup(object
, write_sel
))(object
, write_sel
, stream
);
382 return (*stream
->write
)(stream
->physical
, &buf
, 1);
385 return objc_write_use_common(stream
, 0);
389 objc_write_object_reference (struct objc_typed_stream
* stream
, id object
)
392 if ((key
= PTR2LONG(hash_value_for_key (stream
->object_table
, object
))))
393 return objc_write_use_common (stream
, key
);
395 __objc_write_extension (stream
, _BX_OBJREF
);
396 return objc_write_unsigned_long (stream
, PTR2LONG (object
));
400 objc_write_root_object (struct objc_typed_stream
* stream
, id object
)
403 if (stream
->writing_root_p
)
404 objc_error (nil
, OBJC_ERR_RECURSE_ROOT
,
405 "objc_write_root_object called recursively");
408 stream
->writing_root_p
= 1;
409 __objc_write_extension (stream
, _BX_OBJROOT
);
410 if((len
= objc_write_object (stream
, object
)))
411 __objc_finish_write_root_object(stream
);
412 stream
->writing_root_p
= 0;
418 objc_write_object (struct objc_typed_stream
* stream
, id object
)
421 if ((key
= PTR2LONG(hash_value_for_key (stream
->object_table
, object
))))
422 return objc_write_use_common (stream
, key
);
424 else if (object
== nil
)
425 return objc_write_use_common(stream
, 0);
430 hash_add (&stream
->object_table
, LONG2PTR(key
=PTR2LONG(object
)), object
);
431 if ((length
= objc_write_register_common (stream
, key
)))
432 return __objc_write_object (stream
, object
);
438 __objc_write_class (struct objc_typed_stream
* stream
, struct objc_class
* class)
440 __objc_write_extension (stream
, _BX_CLASS
);
441 objc_write_string_atomic(stream
, (char*)class->name
,
442 strlen((char*)class->name
));
443 return objc_write_unsigned_long (stream
, class->version
);
448 objc_write_class (struct objc_typed_stream
* stream
,
449 struct objc_class
* class)
452 if ((key
= PTR2LONG(hash_value_for_key (stream
->stream_table
, class))))
453 return objc_write_use_common (stream
, key
);
457 hash_add (&stream
->stream_table
, 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
, "", 0);
473 sel_name
= sel_get_name (selector
);
474 return objc_write_string (stream
, 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(hash_value_for_key (stream
->stream_table
, sel_name
))))
489 return objc_write_use_common (stream
, key
);
493 hash_add (&stream
->stream_table
,
494 LONG2PTR(key
=PTR2LONG(sel_name
)), (char*)sel_name
);
495 if ((length
= objc_write_register_common (stream
, key
)))
496 return __objc_write_selector (stream
, selector
);
508 objc_read_char (struct objc_typed_stream
* stream
, char* val
)
512 len
= (*stream
->read
)(stream
->physical
, &buf
, 1);
515 if ((buf
& _B_CODE
) == _B_SINT
)
516 (*val
) = (buf
& _B_VALUE
);
518 else if ((buf
& _B_NUMBER
) == 1)
520 len
= (*stream
->read
)(stream
->physical
, val
, 1);
526 objc_error(nil
, OBJC_ERR_BAD_DATA
,
527 "expected 8bit signed int, got %dbit int",
528 (int)(buf
&_B_NUMBER
)*8);
535 objc_read_unsigned_char (struct objc_typed_stream
* stream
, unsigned char* val
)
539 if ((len
= (*stream
->read
)(stream
->physical
, &buf
, 1)))
541 if ((buf
& _B_CODE
) == _B_SINT
)
542 (*val
) = (buf
& _B_VALUE
);
544 else if ((buf
& _B_NUMBER
) == 1)
545 len
= (*stream
->read
)(stream
->physical
, val
, 1);
548 objc_error(nil
, OBJC_ERR_BAD_DATA
,
549 "expected 8bit unsigned int, got %dbit int",
550 (int)(buf
&_B_NUMBER
)*8);
556 objc_read_short (struct objc_typed_stream
* stream
, short* value
)
558 unsigned char buf
[sizeof(short)+1];
560 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
562 if ((buf
[0] & _B_CODE
) == _B_SINT
)
563 (*value
) = (buf
[0] & _B_VALUE
);
568 int nbytes
= buf
[0] & _B_NUMBER
;
569 if (nbytes
> sizeof (short))
570 objc_error(nil
, OBJC_ERR_BAD_DATA
,
571 "expected short, got bigger (%dbits)", nbytes
*8);
572 len
= (*stream
->read
)(stream
->physical
, buf
+1, nbytes
);
574 while (pos
<= nbytes
)
575 (*value
) = ((*value
)*0x100) + buf
[pos
++];
576 if (buf
[0] & _B_SIGN
)
577 (*value
) = -(*value
);
584 objc_read_unsigned_short (struct objc_typed_stream
* stream
,
585 unsigned short* value
)
587 unsigned char buf
[sizeof(unsigned short)+1];
589 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
591 if ((buf
[0] & _B_CODE
) == _B_SINT
)
592 (*value
) = (buf
[0] & _B_VALUE
);
597 int nbytes
= buf
[0] & _B_NUMBER
;
598 if (nbytes
> sizeof (short))
599 objc_error(nil
, OBJC_ERR_BAD_DATA
,
600 "expected short, got int or bigger");
601 len
= (*stream
->read
)(stream
->physical
, 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
, 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
> sizeof (int))
626 objc_error(nil
, OBJC_ERR_BAD_DATA
, "expected int, got bigger");
627 len
= (*stream
->read
)(stream
->physical
, 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
, 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
> sizeof (long))
653 objc_error(nil
, OBJC_ERR_BAD_DATA
, "expected long, got bigger");
654 len
= (*stream
->read
)(stream
->physical
, 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 char buf
[sizeof(unsigned int)+1];
672 if (nbytes
> sizeof (int))
673 objc_error(nil
, OBJC_ERR_BAD_DATA
, "expected int, got bigger");
675 len
= (*stream
->read
)(stream
->physical
, buf
, nbytes
);
678 (*val
) = ((*val
)*0x100) + buf
[pos
++];
684 objc_read_unsigned_int (struct objc_typed_stream
* stream
,
687 unsigned char buf
[sizeof(unsigned int)+1];
689 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
691 if ((buf
[0] & _B_CODE
) == _B_SINT
)
692 (*value
) = (buf
[0] & _B_VALUE
);
695 len
= __objc_read_nbyte_uint (stream
, (buf
[0] & _B_VALUE
), value
);
702 __objc_read_nbyte_ulong (struct objc_typed_stream
* stream
,
703 unsigned int nbytes
, unsigned long* val
)
706 unsigned char buf
[sizeof(unsigned long)+1];
708 if (nbytes
> sizeof (long))
709 objc_error(nil
, OBJC_ERR_BAD_DATA
, "expected long, got bigger");
711 len
= (*stream
->read
)(stream
->physical
, buf
, nbytes
);
714 (*val
) = ((*val
)*0x100) + buf
[pos
++];
720 objc_read_unsigned_long (struct objc_typed_stream
* stream
,
721 unsigned long* value
)
723 unsigned char buf
[sizeof(unsigned long)+1];
725 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
727 if ((buf
[0] & _B_CODE
) == _B_SINT
)
728 (*value
) = (buf
[0] & _B_VALUE
);
731 len
= __objc_read_nbyte_ulong (stream
, (buf
[0] & _B_VALUE
), value
);
738 objc_read_string (struct objc_typed_stream
* stream
,
741 unsigned char buf
[sizeof(unsigned int)+1];
743 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
745 unsigned long key
= 0;
747 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register following */
749 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
750 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
753 switch (buf
[0]&_B_CODE
) {
756 int length
= buf
[0]&_B_VALUE
;
757 (*string
) = (char*)objc_malloc(length
+1);
759 hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
760 len
= (*stream
->read
)(stream
->physical
, *string
, length
);
761 (*string
)[length
] = '\0';
768 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
769 tmp
= hash_value_for_key (stream
->stream_table
, LONG2PTR (key
));
770 *string
= objc_malloc (strlen(tmp
) + 1);
771 strcpy (*string
, tmp
);
777 unsigned int nbytes
= buf
[0]&_B_VALUE
;
778 len
= __objc_read_nbyte_uint(stream
, nbytes
, &nbytes
);
780 (*string
) = (char*)objc_malloc(nbytes
+1);
782 hash_add (&stream
->stream_table
, LONG2PTR(key
), *string
);
783 len
= (*stream
->read
)(stream
->physical
, *string
, nbytes
);
784 (*string
)[nbytes
] = '\0';
790 objc_error(nil
, OBJC_ERR_BAD_DATA
,
791 "expected string, got opcode %c\n", (buf
[0]&_B_CODE
));
800 objc_read_object (struct objc_typed_stream
* stream
, id
* object
)
802 unsigned char buf
[sizeof (unsigned int)];
804 if ((len
= (*stream
->read
)(stream
->physical
, buf
, 1)))
806 SEL read_sel
= sel_get_any_uid ("read:");
807 unsigned long key
= 0;
809 if ((buf
[0]&_B_CODE
) == _B_RCOMM
) /* register common */
811 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
812 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
815 if (buf
[0] == (_B_EXT
| _BX_OBJECT
))
820 len
= objc_read_class (stream
, &class);
822 /* create instance */
823 (*object
) = class_create_instance(class);
827 hash_add (&stream
->object_table
, LONG2PTR(key
), *object
);
830 if (__objc_responds_to (*object
, read_sel
))
831 (*get_imp(class, read_sel
))(*object
, read_sel
, stream
);
833 /* check null-byte */
834 len
= (*stream
->read
)(stream
->physical
, buf
, 1);
836 objc_error(nil
, OBJC_ERR_BAD_DATA
,
837 "expected null-byte, got opcode %c", buf
[0]);
840 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
843 objc_error(nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
844 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
845 (*object
) = hash_value_for_key (stream
->object_table
, LONG2PTR(key
));
848 else if (buf
[0] == (_B_EXT
| _BX_OBJREF
)) /* a forward reference */
850 struct objc_list
* other
;
851 len
= objc_read_unsigned_long (stream
, &key
);
852 other
= (struct objc_list
*)hash_value_for_key (stream
->object_refs
,
854 hash_add (&stream
->object_refs
, LONG2PTR(key
),
855 (void*)list_cons(object
, other
));
858 else if (buf
[0] == (_B_EXT
| _BX_OBJROOT
)) /* a root object */
861 objc_error(nil
, OBJC_ERR_BAD_KEY
,
862 "cannot register root object...");
863 len
= objc_read_object (stream
, object
);
864 __objc_finish_read_root_object (stream
);
868 objc_error(nil
, OBJC_ERR_BAD_DATA
,
869 "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
, 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
, buf
, 1);
889 if (buf
[0] == (_B_EXT
| _BX_CLASS
))
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
, 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
, buf
, 1);
940 if (buf
[0] == (_B_EXT
|_BX_SEL
)) /* selector! */
945 len
= objc_read_string (stream
, &selector_name
);
946 /* To handle NULL selectors */
947 if (0 == strlen(selector_name
))
949 (*selector
) = (SEL
)0;
953 (*selector
) = sel_get_any_uid(selector_name
);
954 objc_free(selector_name
);
958 hash_add (&stream
->stream_table
, LONG2PTR(key
), (void*)*selector
);
961 else if ((buf
[0]&_B_CODE
) == _B_UCOMM
)
964 objc_error(nil
, OBJC_ERR_BAD_KEY
, "cannot register use upcode...");
965 len
= __objc_read_nbyte_ulong(stream
, (buf
[0] & _B_VALUE
), &key
);
966 (*selector
) = hash_value_for_key (stream
->stream_table
,
971 objc_error(nil
, OBJC_ERR_BAD_DATA
,
972 "expected selector, got opcode %c", buf
[0]);
978 ** USER LEVEL FUNCTIONS
982 ** Write one object, encoded in TYPE and pointed to by DATA to the
983 ** typed stream STREAM.
987 objc_write_type(TypedStream
* stream
, const char* type
, const void* data
)
991 return objc_write_object (stream
, *(id
*)data
);
995 return objc_write_class (stream
, *(Class
*)data
);
999 return objc_write_selector (stream
, *(SEL
*)data
);
1003 return objc_write_char(stream
, *(signed char*)data
);
1007 return objc_write_unsigned_char(stream
, *(unsigned char*)data
);
1011 return objc_write_short(stream
, *(short*)data
);
1015 return objc_write_unsigned_short(stream
, *(unsigned short*)data
);
1019 return objc_write_int(stream
, *(int*)data
);
1023 return objc_write_unsigned_int(stream
, *(unsigned int*)data
);
1027 return objc_write_long(stream
, *(long*)data
);
1031 return objc_write_unsigned_long(stream
, *(unsigned long*)data
);
1035 return objc_write_string (stream
, *(char**)data
, strlen(*(char**)data
));
1039 return objc_write_string_atomic (stream
, *(char**)data
,
1040 strlen(*(char**)data
));
1045 int len
= atoi(type
+1);
1046 while (isdigit(*++type
))
1048 return objc_write_array (stream
, type
, len
, data
);
1056 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1057 ; /* skip "<name>=" */
1058 while (*type
!= _C_STRUCT_E
)
1060 align
= objc_alignof_type (type
); /* padd to alignment */
1061 acc_size
+= ROUND (acc_size
, align
);
1062 objc_write_type (stream
, type
, ((char*)data
)+acc_size
);
1063 acc_size
+= objc_sizeof_type (type
); /* add component size */
1064 type
= objc_skip_typespec (type
); /* skip component */
1071 objc_error(nil
, OBJC_ERR_BAD_TYPE
,
1072 "objc_write_type: cannot parse typespec: %s\n", type
);
1079 ** Read one object, encoded in TYPE and pointed to by DATA to the
1080 ** typed stream STREAM. DATA specifies the address of the types to
1081 ** read. Expected type is checked against the type actually present
1086 objc_read_type(TypedStream
* stream
, const char* type
, void* data
)
1091 return objc_read_object (stream
, (id
*)data
);
1095 return objc_read_class (stream
, (Class
*)data
);
1099 return objc_read_selector (stream
, (SEL
*)data
);
1103 return objc_read_char (stream
, (char*)data
);
1107 return objc_read_unsigned_char (stream
, (unsigned char*)data
);
1111 return objc_read_short (stream
, (short*)data
);
1115 return objc_read_unsigned_short (stream
, (unsigned short*)data
);
1119 return objc_read_int (stream
, (int*)data
);
1123 return objc_read_unsigned_int (stream
, (unsigned int*)data
);
1127 return objc_read_long (stream
, (long*)data
);
1131 return objc_read_unsigned_long (stream
, (unsigned long*)data
);
1136 return objc_read_string (stream
, (char**)data
);
1141 int len
= atoi(type
+1);
1142 while (isdigit(*++type
))
1144 return objc_read_array (stream
, type
, len
, data
);
1152 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
1153 ; /* skip "<name>=" */
1154 while (*type
!= _C_STRUCT_E
)
1156 align
= objc_alignof_type (type
); /* padd to alignment */
1157 acc_size
+= ROUND (acc_size
, align
);
1158 objc_read_type (stream
, type
, ((char*)data
)+acc_size
);
1159 acc_size
+= objc_sizeof_type (type
); /* add component size */
1160 type
= objc_skip_typespec (type
); /* skip component */
1167 objc_error(nil
, OBJC_ERR_BAD_TYPE
,
1168 "objc_read_type: cannot parse typespec: %s\n", type
);
1175 ** Write the object specified by the template TYPE to STREAM. Last
1176 ** arguments specify addresses of values to be written. It might
1177 ** seem surprising to specify values by address, but this is extremely
1178 ** convenient for copy-paste with objc_read_types calls. A more
1179 ** down-to-the-earth cause for this passing of addresses is that values
1180 ** of arbitrary size is not well supported in ANSI C for functions with
1181 ** variable number of arguments.
1185 objc_write_types (TypedStream
* stream
, const char* type
, ...)
1191 va_start(args
, type
);
1193 for (c
= type
; *c
; c
= objc_skip_typespec (c
))
1197 res
= objc_write_object (stream
, *va_arg (args
, id
*));
1201 res
= objc_write_class (stream
, *va_arg(args
, Class
*));
1205 res
= objc_write_selector (stream
, *va_arg(args
, SEL
*));
1209 res
= objc_write_char (stream
, *va_arg (args
, char*));
1213 res
= objc_write_unsigned_char (stream
,
1214 *va_arg (args
, unsigned char*));
1218 res
= objc_write_short (stream
, *va_arg(args
, short*));
1222 res
= objc_write_unsigned_short (stream
,
1223 *va_arg(args
, unsigned short*));
1227 res
= objc_write_int(stream
, *va_arg(args
, int*));
1231 res
= objc_write_unsigned_int(stream
, *va_arg(args
, unsigned int*));
1235 res
= objc_write_long(stream
, *va_arg(args
, long*));
1239 res
= objc_write_unsigned_long(stream
, *va_arg(args
, unsigned long*));
1244 char** str
= va_arg(args
, char**);
1245 res
= objc_write_string (stream
, *str
, strlen(*str
));
1251 char** str
= va_arg(args
, char**);
1252 res
= objc_write_string_atomic (stream
, *str
, strlen(*str
));
1258 int len
= atoi(c
+1);
1260 while (isdigit(*++t
))
1262 res
= objc_write_array (stream
, t
, len
, va_arg(args
, void*));
1263 t
= objc_skip_typespec (t
);
1265 objc_error(nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1270 objc_error(nil
, OBJC_ERR_BAD_TYPE
,
1271 "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(*++t
))
1354 res
= objc_read_array (stream
, t
, len
, va_arg(args
, void*));
1355 t
= objc_skip_typespec (t
);
1357 objc_error(nil
, OBJC_ERR_BAD_TYPE
, "expected `]', got: %s", t
);
1362 objc_error(nil
, OBJC_ERR_BAD_TYPE
,
1363 "objc_read_types: cannot parse typespec: %s\n", type
);
1371 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1372 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1376 objc_write_array (TypedStream
* stream
, const char* type
,
1377 int count
, const void* data
)
1379 int off
= objc_sizeof_type(type
);
1380 const char* where
= data
;
1384 objc_write_type(stream
, type
, where
);
1391 ** Read an array of COUNT elements of TYPE into the memory address
1392 ** DATA. The memory pointed to by data is supposed to be allocated
1393 ** by the callee. This is equivalent of
1394 ** objc_read_type (stream, "[N<type>]", data)
1398 objc_read_array (TypedStream
* stream
, const char* type
,
1399 int count
, void* data
)
1401 int off
= objc_sizeof_type(type
);
1402 char* where
= (char*)data
;
1406 objc_read_type(stream
, type
, where
);
1413 __objc_fread(FILE* file
, char* data
, int len
)
1415 return fread(data
, len
, 1, file
);
1419 __objc_fwrite(FILE* file
, char* data
, int len
)
1421 return fwrite(data
, len
, 1, file
);
1425 __objc_feof(FILE* file
)
1431 __objc_no_write(FILE* file
, char* data
, int len
)
1433 objc_error (nil
, OBJC_ERR_NO_WRITE
, "TypedStream not open for writing");
1438 __objc_no_read(FILE* file
, char* data
, int len
)
1440 objc_error (nil
, OBJC_ERR_NO_READ
, "TypedStream not open for reading");
1445 __objc_read_typed_stream_signature (TypedStream
* stream
)
1450 (*stream
->read
)(stream
->physical
, buffer
+pos
, 1);
1451 while (buffer
[pos
++] != '\0')
1453 sscanf (buffer
, "GNU TypedStream %d", &stream
->version
);
1454 if (stream
->version
!= OBJC_TYPED_STREAM_VERSION
)
1455 objc_error (nil
, OBJC_ERR_STREAM_VERSION
,
1456 "cannot handle TypedStream version %d", stream
->version
);
1461 __objc_write_typed_stream_signature (TypedStream
* stream
)
1464 sprintf(buffer
, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION
);
1465 stream
->version
= OBJC_TYPED_STREAM_VERSION
;
1466 (*stream
->write
)(stream
->physical
, buffer
, strlen(buffer
)+1);
1470 static void __objc_finish_write_root_object(struct objc_typed_stream
* stream
)
1472 hash_delete (stream
->object_table
);
1473 stream
->object_table
= hash_new(64,
1474 (hash_func_type
)hash_ptr
,
1475 (compare_func_type
)compare_ptrs
);
1478 static void __objc_finish_read_root_object(struct objc_typed_stream
* stream
)
1481 SEL awake_sel
= sel_get_any_uid ("awake");
1482 cache_ptr free_list
= hash_new (64,
1483 (hash_func_type
) hash_ptr
,
1484 (compare_func_type
) compare_ptrs
);
1486 /* resolve object forward references */
1487 for (node
= hash_next (stream
->object_refs
, NULL
); node
;
1488 node
= hash_next (stream
->object_refs
, node
))
1490 struct objc_list
* reflist
= node
->value
;
1491 const void* key
= node
->key
;
1492 id object
= hash_value_for_key (stream
->object_table
, key
);
1495 *((id
*)reflist
->head
) = object
;
1496 if (hash_value_for_key (free_list
,reflist
) == NULL
)
1497 hash_add (&free_list
,reflist
,reflist
);
1499 reflist
= reflist
->tail
;
1503 /* apply __objc_free to all objects stored in free_list */
1504 for (node
= hash_next (free_list
, NULL
); node
;
1505 node
= hash_next (free_list
, node
))
1506 objc_free ((void *) node
->key
);
1508 hash_delete (free_list
);
1510 /* empty object reference table */
1511 hash_delete (stream
->object_refs
);
1512 stream
->object_refs
= hash_new(8, (hash_func_type
)hash_ptr
,
1513 (compare_func_type
)compare_ptrs
);
1515 /* call -awake for all objects read */
1518 for (node
= hash_next (stream
->object_table
, NULL
); node
;
1519 node
= hash_next (stream
->object_table
, node
))
1521 id object
= node
->value
;
1522 if (__objc_responds_to (object
, awake_sel
))
1523 (*objc_msg_lookup(object
, awake_sel
))(object
, awake_sel
);
1527 /* empty object table */
1528 hash_delete (stream
->object_table
);
1529 stream
->object_table
= hash_new(64,
1530 (hash_func_type
)hash_ptr
,
1531 (compare_func_type
)compare_ptrs
);
1535 ** Open the stream PHYSICAL in MODE
1539 objc_open_typed_stream (FILE* physical
, int mode
)
1541 TypedStream
* s
= (TypedStream
*)objc_malloc(sizeof(TypedStream
));
1544 s
->physical
= physical
;
1545 s
->stream_table
= hash_new(64,
1546 (hash_func_type
)hash_ptr
,
1547 (compare_func_type
)compare_ptrs
);
1548 s
->object_table
= hash_new(64,
1549 (hash_func_type
)hash_ptr
,
1550 (compare_func_type
)compare_ptrs
);
1551 s
->eof
= (objc_typed_eof_func
)__objc_feof
;
1552 s
->flush
= (objc_typed_flush_func
)fflush
;
1553 s
->writing_root_p
= 0;
1554 if (mode
== OBJC_READONLY
)
1556 s
->class_table
= hash_new(8, (hash_func_type
)hash_string
,
1557 (compare_func_type
)compare_strings
);
1558 s
->object_refs
= hash_new(8, (hash_func_type
)hash_ptr
,
1559 (compare_func_type
)compare_ptrs
);
1560 s
->read
= (objc_typed_read_func
)__objc_fread
;
1561 s
->write
= (objc_typed_write_func
)__objc_no_write
;
1562 __objc_read_typed_stream_signature (s
);
1564 else if (mode
== OBJC_WRITEONLY
)
1568 s
->read
= (objc_typed_read_func
)__objc_no_read
;
1569 s
->write
= (objc_typed_write_func
)__objc_fwrite
;
1570 __objc_write_typed_stream_signature (s
);
1574 objc_close_typed_stream (s
);
1577 s
->type
= OBJC_FILE_STREAM
;
1582 ** Open the file named by FILE_NAME in MODE
1586 objc_open_typed_stream_for_file (const char* file_name
, int mode
)
1591 if (mode
== OBJC_READONLY
)
1592 file
= fopen (file_name
, "r");
1594 file
= fopen (file_name
, "w");
1598 s
= objc_open_typed_stream (file
, mode
);
1600 s
->type
|= OBJC_MANAGED_STREAM
;
1608 ** Close STREAM freeing the structure it self. If it was opened with
1609 ** objc_open_typed_stream_for_file, the file will also be closed.
1613 objc_close_typed_stream (TypedStream
* stream
)
1615 if (stream
->mode
== OBJC_READONLY
)
1617 __objc_finish_read_root_object (stream
); /* Just in case... */
1618 hash_delete (stream
->class_table
);
1619 hash_delete (stream
->object_refs
);
1622 hash_delete (stream
->stream_table
);
1623 hash_delete (stream
->object_table
);
1625 if (stream
->type
== (OBJC_MANAGED_STREAM
| OBJC_FILE_STREAM
))
1626 fclose ((FILE*)stream
->physical
);
1632 objc_end_of_typed_stream (TypedStream
* stream
)
1634 return (*stream
->eof
)(stream
->physical
);
1638 objc_flush_typed_stream (TypedStream
* stream
)
1640 (*stream
->flush
)(stream
->physical
);
1644 objc_get_stream_class_version (TypedStream
* stream
, Class
class)
1646 if (stream
->class_table
)
1647 return PTR2LONG(hash_value_for_key (stream
->class_table
, class->name
));
1649 return class_get_version (class);