configure: For in-source builds, make a subdir and re-exec there.
[official-gcc.git] / libobjc / archive.c
blobe6b6d2f946d0634723164b35b53d169f4b3057af
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
14 details.
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. */
27 #include "tconfig.h"
28 #include "runtime.h"
29 #include "typedstream.h"
30 #include "encoding.h"
31 #include <stdlib.h>
33 extern int fflush(FILE*);
35 #define ROUND(V, A) \
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... */
44 static int
45 objc_read_class (struct objc_typed_stream* stream, Class* class);
47 int objc_sizeof_type(const char* type);
49 static int
50 objc_write_use_common (struct objc_typed_stream* stream, unsigned long key);
52 static int
53 objc_write_register_common (struct objc_typed_stream* stream,
54 unsigned long key);
56 static int
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*);
65 static __inline__ int
66 __objc_code_unsigned_char (unsigned char* buf, unsigned char val)
68 if ((val&_B_VALUE) == val)
70 buf[0] = val|_B_SINT;
71 return 1;
73 else
75 buf[0] = _B_NINT|0x01;
76 buf[1] = val;
77 return 2;
81 int
82 objc_write_unsigned_char (struct objc_typed_stream* stream,
83 unsigned char value)
85 unsigned char buf[sizeof (unsigned char)+1];
86 int len = __objc_code_unsigned_char (buf, value);
87 return (*stream->write)(stream->physical, buf, len);
90 static __inline__ int
91 __objc_code_char (unsigned char* buf, signed char val)
93 if (val >= 0)
94 return __objc_code_unsigned_char (buf, val);
95 else
97 buf[0] = _B_NINT|_B_SIGN|0x01;
98 buf[1] = -val;
99 return 2;
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, buf, len);
111 static __inline__ int
112 __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
114 if ((val&_B_VALUE) == val)
116 buf[0] = val|_B_SINT;
117 return 1;
119 else
121 int c, b;
123 buf[0] = _B_NINT;
125 for (c= sizeof(short); c != 0; c -= 1)
126 if (((val>>(8*(c-1)))%0x100) != 0)
127 break;
129 buf[0] |= c;
131 for (b = 1; c != 0; c--, b++)
133 buf[b] = (val >> (8*(c-1)))%0x100;
136 return b;
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, buf, len);
149 static __inline__ int
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);
154 if (sign)
155 buf[0] |= _B_SIGN;
156 return size;
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, buf, len);
168 static __inline__ int
169 __objc_code_unsigned_int (unsigned char* buf, unsigned int val)
171 if ((val&_B_VALUE) == val)
173 buf[0] = val|_B_SINT;
174 return 1;
176 else
178 int c, b;
180 buf[0] = _B_NINT;
182 for (c= sizeof(int); c != 0; c -= 1)
183 if (((val>>(8*(c-1)))%0x100) != 0)
184 break;
186 buf[0] |= c;
188 for (b = 1; c != 0; c--, b++)
190 buf[b] = (val >> (8*(c-1)))%0x100;
193 return b;
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, buf, len);
205 static __inline__ int
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);
210 if (sign)
211 buf[0] |= _B_SIGN;
212 return size;
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, buf, len);
223 static __inline__ int
224 __objc_code_unsigned_long (unsigned char* buf, unsigned long val)
226 if ((val&_B_VALUE) == val)
228 buf[0] = val|_B_SINT;
229 return 1;
231 else
233 int c, b;
235 buf[0] = _B_NINT;
237 for (c= sizeof(long); c != 0; c -= 1)
238 if (((val>>(8*(c-1)))%0x100) != 0)
239 break;
241 buf[0] |= c;
243 for (b = 1; c != 0; c--, b++)
245 buf[b] = (val >> (8*(c-1)))%0x100;
248 return b;
253 objc_write_unsigned_long (struct objc_typed_stream* stream,
254 unsigned long value)
256 unsigned char buf[sizeof(unsigned long)+1];
257 int len = __objc_code_unsigned_long (buf, value);
258 return (*stream->write)(stream->physical, buf, len);
261 static __inline__ int
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);
266 if (sign)
267 buf[0] |= _B_SIGN;
268 return size;
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, 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;
290 else /* _B_NINT */
291 buf[0] = (buf[0]&_B_VALUE)|_B_NSTR;
293 if ((*stream->write)(stream->physical, buf, len) != 0)
294 return (*stream->write)(stream->physical, string, nbytes);
295 else
296 return 0;
300 objc_write_string_atomic (struct objc_typed_stream* stream,
301 unsigned char* string, unsigned int nbytes)
303 unsigned long key;
304 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string))))
305 return objc_write_use_common (stream, key);
306 else
308 int length;
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);
312 return length;
316 static int
317 objc_write_register_common (struct objc_typed_stream* stream,
318 unsigned long key)
320 unsigned char buf[sizeof (unsigned long)+2];
321 int len = __objc_code_unsigned_long (buf+1, key);
322 if (len == 1)
324 buf[0] = _B_RCOMM|0x01;
325 buf[1] &= _B_VALUE;
326 return (*stream->write)(stream->physical, buf, len+1);
328 else
330 buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM;
331 return (*stream->write)(stream->physical, buf+1, len);
335 static int
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);
340 if (len == 1)
342 buf[0] = _B_UCOMM|0x01;
343 buf[1] &= _B_VALUE;
344 return (*stream->write)(stream->physical, buf, 2);
346 else
348 buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM;
349 return (*stream->write)(stream->physical, buf+1, len);
353 static __inline__ int
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, &buf, 1);
361 else
363 objc_error(nil, OBJC_ERR_BAD_OPCODE,
364 "__objc_write_extension: bad opcode %c\n", code);
365 return -1;
369 __inline__ int
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:");
374 if (object)
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, &buf, 1);
381 else
382 return objc_write_use_common(stream, 0);
385 int
386 objc_write_object_reference (struct objc_typed_stream* stream, id object)
388 unsigned long key;
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));
396 int
397 objc_write_root_object (struct objc_typed_stream* stream, id object)
399 int len = 0;
400 if (stream->writing_root_p)
401 objc_error (nil, OBJC_ERR_RECURSE_ROOT,
402 "objc_write_root_object called recursively");
403 else
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;
411 return len;
414 int
415 objc_write_object (struct objc_typed_stream* stream, id object)
417 unsigned long key;
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);
424 else
426 int length;
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);
430 return length;
434 __inline__ int
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, (char*)class->name,
439 strlen((char*)class->name));
440 return objc_write_unsigned_long (stream, class->version);
444 static int
445 objc_write_class (struct objc_typed_stream* stream,
446 struct objc_class* class)
448 unsigned long key;
449 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class))))
450 return objc_write_use_common (stream, key);
451 else
453 int length;
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);
457 return length;
462 __inline__ int
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, "", 0);
470 sel_name = sel_get_name (selector);
471 return objc_write_string (stream, sel_name, strlen ((char*)sel_name));
474 int
475 objc_write_selector (struct objc_typed_stream* stream, SEL selector)
477 const char* sel_name;
478 unsigned long key;
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);
487 else
489 int length;
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);
494 return length;
501 ** Read operations
504 __inline__ int
505 objc_read_char (struct objc_typed_stream* stream, char* val)
507 unsigned char buf;
508 int len;
509 len = (*stream->read)(stream->physical, &buf, 1);
510 if (len != 0)
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);
518 if (buf&_B_SIGN)
519 (*val) = -1*(*val);
522 else
523 objc_error(nil, OBJC_ERR_BAD_DATA,
524 "expected 8bit signed int, got %dbit int",
525 (int)(buf&_B_NUMBER)*8);
527 return len;
531 __inline__ int
532 objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val)
534 unsigned char buf;
535 int len;
536 if ((len = (*stream->read)(stream->physical, &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, val, 1);
544 else
545 objc_error(nil, OBJC_ERR_BAD_DATA,
546 "expected 8bit unsigned int, got %dbit int",
547 (int)(buf&_B_NUMBER)*8);
549 return len;
552 __inline__ int
553 objc_read_short (struct objc_typed_stream* stream, short* value)
555 unsigned char buf[sizeof(short)+1];
556 int len;
557 if ((len = (*stream->read)(stream->physical, buf, 1)))
559 if ((buf[0] & _B_CODE) == _B_SINT)
560 (*value) = (buf[0] & _B_VALUE);
562 else
564 int pos = 1;
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, buf+1, nbytes);
570 (*value) = 0;
571 while (pos <= nbytes)
572 (*value) = ((*value)*0x100) + buf[pos++];
573 if (buf[0] & _B_SIGN)
574 (*value) = -(*value);
577 return len;
580 __inline__ int
581 objc_read_unsigned_short (struct objc_typed_stream* stream,
582 unsigned short* value)
584 unsigned char buf[sizeof(unsigned short)+1];
585 int len;
586 if ((len = (*stream->read)(stream->physical, buf, 1)))
588 if ((buf[0] & _B_CODE) == _B_SINT)
589 (*value) = (buf[0] & _B_VALUE);
591 else
593 int pos = 1;
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, buf+1, nbytes);
599 (*value) = 0;
600 while (pos <= nbytes)
601 (*value) = ((*value)*0x100) + buf[pos++];
604 return len;
608 __inline__ int
609 objc_read_int (struct objc_typed_stream* stream, int* value)
611 unsigned char buf[sizeof(int)+1];
612 int len;
613 if ((len = (*stream->read)(stream->physical, buf, 1)))
615 if ((buf[0] & _B_CODE) == _B_SINT)
616 (*value) = (buf[0] & _B_VALUE);
618 else
620 int pos = 1;
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, buf+1, nbytes);
625 (*value) = 0;
626 while (pos <= nbytes)
627 (*value) = ((*value)*0x100) + buf[pos++];
628 if (buf[0] & _B_SIGN)
629 (*value) = -(*value);
632 return len;
635 __inline__ int
636 objc_read_long (struct objc_typed_stream* stream, long* value)
638 unsigned char buf[sizeof(long)+1];
639 int len;
640 if ((len = (*stream->read)(stream->physical, buf, 1)))
642 if ((buf[0] & _B_CODE) == _B_SINT)
643 (*value) = (buf[0] & _B_VALUE);
645 else
647 int pos = 1;
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, buf+1, nbytes);
652 (*value) = 0;
653 while (pos <= nbytes)
654 (*value) = ((*value)*0x100) + buf[pos++];
655 if (buf[0] & _B_SIGN)
656 (*value) = -(*value);
659 return len;
662 __inline__ int
663 __objc_read_nbyte_uint (struct objc_typed_stream* stream,
664 unsigned int nbytes, unsigned int* val)
666 int len;
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, buf, nbytes);
674 (*val) = 0;
675 while (pos < nbytes)
676 (*val) = ((*val)*0x100) + buf[pos++];
677 return len;
681 __inline__ int
682 objc_read_unsigned_int (struct objc_typed_stream* stream,
683 unsigned int* value)
685 unsigned char buf[sizeof(unsigned int)+1];
686 int len;
687 if ((len = (*stream->read)(stream->physical, buf, 1)))
689 if ((buf[0] & _B_CODE) == _B_SINT)
690 (*value) = (buf[0] & _B_VALUE);
692 else
693 len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value);
696 return len;
700 __objc_read_nbyte_ulong (struct objc_typed_stream* stream,
701 unsigned int nbytes, unsigned long* val)
703 int len;
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, buf, nbytes);
711 (*val) = 0;
712 while (pos < nbytes)
713 (*val) = ((*val)*0x100) + buf[pos++];
714 return len;
718 __inline__ int
719 objc_read_unsigned_long (struct objc_typed_stream* stream,
720 unsigned long* value)
722 unsigned char buf[sizeof(unsigned long)+1];
723 int len;
724 if ((len = (*stream->read)(stream->physical, buf, 1)))
726 if ((buf[0] & _B_CODE) == _B_SINT)
727 (*value) = (buf[0] & _B_VALUE);
729 else
730 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value);
733 return len;
736 __inline__ int
737 objc_read_string (struct objc_typed_stream* stream,
738 char** string)
740 unsigned char buf[sizeof(unsigned int)+1];
741 int len;
742 if ((len = (*stream->read)(stream->physical, 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, buf, 1);
752 switch (buf[0]&_B_CODE) {
753 case _B_SSTR:
755 int length = buf[0]&_B_VALUE;
756 (*string) = (char*)objc_malloc(length+1);
757 if (key)
758 hash_add (&stream->stream_table, LONG2PTR(key), *string);
759 len = (*stream->read)(stream->physical, *string, length);
760 (*string)[length] = '\0';
762 break;
764 case _B_UCOMM:
766 char *tmp;
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);
772 break;
774 case _B_NSTR:
776 unsigned int nbytes = buf[0]&_B_VALUE;
777 len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
778 if (len) {
779 (*string) = (char*)objc_malloc(nbytes+1);
780 if (key)
781 hash_add (&stream->stream_table, LONG2PTR(key), *string);
782 len = (*stream->read)(stream->physical, *string, nbytes);
783 (*string)[nbytes] = '\0';
786 break;
788 default:
789 objc_error(nil, OBJC_ERR_BAD_DATA,
790 "expected string, got opcode %c\n", (buf[0]&_B_CODE));
794 return len;
799 objc_read_object (struct objc_typed_stream* stream, id* object)
801 unsigned char buf[sizeof (unsigned int)];
802 int len;
803 if ((len = (*stream->read)(stream->physical, 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, buf, 1);
814 if (buf[0] == (_B_EXT | _BX_OBJECT))
816 Class class;
818 /* get class */
819 len = objc_read_class (stream, &class);
821 /* create instance */
822 (*object) = class_create_instance(class);
824 /* register? */
825 if (key)
826 hash_add (&stream->object_table, LONG2PTR(key), *object);
828 /* send -read: */
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, buf, 1);
834 if (buf[0] != '\0')
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)
841 if (key)
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,
852 LONG2PTR(key));
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 */
859 if (key)
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);
866 else
867 objc_error(nil, OBJC_ERR_BAD_DATA,
868 "expected object, got opcode %c", buf[0]);
870 return len;
873 static int
874 objc_read_class (struct objc_typed_stream* stream, Class* class)
876 unsigned char buf[sizeof (unsigned int)];
877 int len;
878 if ((len = (*stream->read)(stream->physical, 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, buf, 1);
888 if (buf[0] == (_B_EXT | _BX_CLASS))
890 char* class_name;
891 unsigned long version;
893 /* get class */
894 len = objc_read_string (stream, &class_name);
895 (*class) = objc_get_class(class_name);
896 objc_free(class_name);
898 /* register */
899 if (key)
900 hash_add (&stream->stream_table, LONG2PTR(key), *class);
902 objc_read_unsigned_long(stream, &version);
903 hash_add (&stream->class_table, (*class)->name, (void*)version);
906 else if ((buf[0]&_B_CODE) == _B_UCOMM)
908 if (key)
909 objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
910 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
911 (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
912 if (!*class)
913 objc_error(nil, OBJC_ERR_BAD_CLASS,
914 "cannot find class for key %lu", key);
917 else
918 objc_error(nil, OBJC_ERR_BAD_DATA,
919 "expected class, got opcode %c", buf[0]);
921 return len;
925 objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
927 unsigned char buf[sizeof (unsigned int)];
928 int len;
929 if ((len = (*stream->read)(stream->physical, buf, 1)))
931 unsigned long key = 0;
933 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
935 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
936 len = (*stream->read)(stream->physical, buf, 1);
939 if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
941 char* selector_name;
943 /* get selector */
944 len = objc_read_string (stream, &selector_name);
945 /* To handle NULL selectors */
946 if (0 == strlen(selector_name))
948 (*selector) = (SEL)0;
949 return 0;
951 else
952 (*selector) = sel_get_any_uid(selector_name);
953 objc_free(selector_name);
955 /* register */
956 if (key)
957 hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
960 else if ((buf[0]&_B_CODE) == _B_UCOMM)
962 if (key)
963 objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
964 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
965 (*selector) = hash_value_for_key (stream->stream_table,
966 LONG2PTR(key));
969 else
970 objc_error(nil, OBJC_ERR_BAD_DATA,
971 "expected selector, got opcode %c", buf[0]);
973 return len;
977 ** USER LEVEL FUNCTIONS
981 ** Write one object, encoded in TYPE and pointed to by DATA to the
982 ** typed stream STREAM.
986 objc_write_type(TypedStream* stream, const char* type, const void* data)
988 switch(*type) {
989 case _C_ID:
990 return objc_write_object (stream, *(id*)data);
991 break;
993 case _C_CLASS:
994 return objc_write_class (stream, *(Class*)data);
995 break;
997 case _C_SEL:
998 return objc_write_selector (stream, *(SEL*)data);
999 break;
1001 case _C_CHR:
1002 return objc_write_char(stream, *(signed char*)data);
1003 break;
1005 case _C_UCHR:
1006 return objc_write_unsigned_char(stream, *(unsigned char*)data);
1007 break;
1009 case _C_SHT:
1010 return objc_write_short(stream, *(short*)data);
1011 break;
1013 case _C_USHT:
1014 return objc_write_unsigned_short(stream, *(unsigned short*)data);
1015 break;
1017 case _C_INT:
1018 return objc_write_int(stream, *(int*)data);
1019 break;
1021 case _C_UINT:
1022 return objc_write_unsigned_int(stream, *(unsigned int*)data);
1023 break;
1025 case _C_LNG:
1026 return objc_write_long(stream, *(long*)data);
1027 break;
1029 case _C_ULNG:
1030 return objc_write_unsigned_long(stream, *(unsigned long*)data);
1031 break;
1033 case _C_CHARPTR:
1034 return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
1035 break;
1037 case _C_ATOM:
1038 return objc_write_string_atomic (stream, *(char**)data,
1039 strlen(*(char**)data));
1040 break;
1042 case _C_ARY_B:
1044 int len = atoi(type+1);
1045 while (isdigit((unsigned char)*++type))
1047 return objc_write_array (stream, type, len, data);
1049 break;
1051 case _C_STRUCT_B:
1053 int acc_size = 0;
1054 int align;
1055 while (*type != _C_STRUCT_E && *type++ != '=')
1056 ; /* skip "<name>=" */
1057 while (*type != _C_STRUCT_E)
1059 align = objc_alignof_type (type); /* padd to alignment */
1060 acc_size += ROUND (acc_size, align);
1061 objc_write_type (stream, type, ((char*)data)+acc_size);
1062 acc_size += objc_sizeof_type (type); /* add component size */
1063 type = objc_skip_typespec (type); /* skip component */
1065 return 1;
1068 default:
1070 objc_error(nil, OBJC_ERR_BAD_TYPE,
1071 "objc_write_type: cannot parse typespec: %s\n", type);
1072 return 0;
1078 ** Read one object, encoded in TYPE and pointed to by DATA to the
1079 ** typed stream STREAM. DATA specifies the address of the types to
1080 ** read. Expected type is checked against the type actually present
1081 ** on the stream.
1085 objc_read_type(TypedStream* stream, const char* type, void* data)
1087 char c;
1088 switch(c = *type) {
1089 case _C_ID:
1090 return objc_read_object (stream, (id*)data);
1091 break;
1093 case _C_CLASS:
1094 return objc_read_class (stream, (Class*)data);
1095 break;
1097 case _C_SEL:
1098 return objc_read_selector (stream, (SEL*)data);
1099 break;
1101 case _C_CHR:
1102 return objc_read_char (stream, (char*)data);
1103 break;
1105 case _C_UCHR:
1106 return objc_read_unsigned_char (stream, (unsigned char*)data);
1107 break;
1109 case _C_SHT:
1110 return objc_read_short (stream, (short*)data);
1111 break;
1113 case _C_USHT:
1114 return objc_read_unsigned_short (stream, (unsigned short*)data);
1115 break;
1117 case _C_INT:
1118 return objc_read_int (stream, (int*)data);
1119 break;
1121 case _C_UINT:
1122 return objc_read_unsigned_int (stream, (unsigned int*)data);
1123 break;
1125 case _C_LNG:
1126 return objc_read_long (stream, (long*)data);
1127 break;
1129 case _C_ULNG:
1130 return objc_read_unsigned_long (stream, (unsigned long*)data);
1131 break;
1133 case _C_CHARPTR:
1134 case _C_ATOM:
1135 return objc_read_string (stream, (char**)data);
1136 break;
1138 case _C_ARY_B:
1140 int len = atoi(type+1);
1141 while (isdigit((unsigned char)*++type))
1143 return objc_read_array (stream, type, len, data);
1145 break;
1147 case _C_STRUCT_B:
1149 int acc_size = 0;
1150 int align;
1151 while (*type != _C_STRUCT_E && *type++ != '=')
1152 ; /* skip "<name>=" */
1153 while (*type != _C_STRUCT_E)
1155 align = objc_alignof_type (type); /* padd to alignment */
1156 acc_size += ROUND (acc_size, align);
1157 objc_read_type (stream, type, ((char*)data)+acc_size);
1158 acc_size += objc_sizeof_type (type); /* add component size */
1159 type = objc_skip_typespec (type); /* skip component */
1161 return 1;
1164 default:
1166 objc_error(nil, OBJC_ERR_BAD_TYPE,
1167 "objc_read_type: cannot parse typespec: %s\n", type);
1168 return 0;
1174 ** Write the object specified by the template TYPE to STREAM. Last
1175 ** arguments specify addresses of values to be written. It might
1176 ** seem surprising to specify values by address, but this is extremely
1177 ** convenient for copy-paste with objc_read_types calls. A more
1178 ** down-to-the-earth cause for this passing of addresses is that values
1179 ** of arbitrary size is not well supported in ANSI C for functions with
1180 ** variable number of arguments.
1183 int
1184 objc_write_types (TypedStream* stream, const char* type, ...)
1186 va_list args;
1187 const char *c;
1188 int res = 0;
1190 va_start(args, type);
1192 for (c = type; *c; c = objc_skip_typespec (c))
1194 switch(*c) {
1195 case _C_ID:
1196 res = objc_write_object (stream, *va_arg (args, id*));
1197 break;
1199 case _C_CLASS:
1200 res = objc_write_class (stream, *va_arg(args, Class*));
1201 break;
1203 case _C_SEL:
1204 res = objc_write_selector (stream, *va_arg(args, SEL*));
1205 break;
1207 case _C_CHR:
1208 res = objc_write_char (stream, *va_arg (args, char*));
1209 break;
1211 case _C_UCHR:
1212 res = objc_write_unsigned_char (stream,
1213 *va_arg (args, unsigned char*));
1214 break;
1216 case _C_SHT:
1217 res = objc_write_short (stream, *va_arg(args, short*));
1218 break;
1220 case _C_USHT:
1221 res = objc_write_unsigned_short (stream,
1222 *va_arg(args, unsigned short*));
1223 break;
1225 case _C_INT:
1226 res = objc_write_int(stream, *va_arg(args, int*));
1227 break;
1229 case _C_UINT:
1230 res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
1231 break;
1233 case _C_LNG:
1234 res = objc_write_long(stream, *va_arg(args, long*));
1235 break;
1237 case _C_ULNG:
1238 res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*));
1239 break;
1241 case _C_CHARPTR:
1243 char** str = va_arg(args, char**);
1244 res = objc_write_string (stream, *str, strlen(*str));
1246 break;
1248 case _C_ATOM:
1250 char** str = va_arg(args, char**);
1251 res = objc_write_string_atomic (stream, *str, strlen(*str));
1253 break;
1255 case _C_ARY_B:
1257 int len = atoi(c+1);
1258 const char* t = c;
1259 while (isdigit((unsigned char)*++t))
1261 res = objc_write_array (stream, t, len, va_arg(args, void*));
1262 t = objc_skip_typespec (t);
1263 if (*t != _C_ARY_E)
1264 objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
1266 break;
1268 default:
1269 objc_error(nil, OBJC_ERR_BAD_TYPE,
1270 "objc_write_types: cannot parse typespec: %s\n", type);
1273 va_end(args);
1274 return res;
1279 ** Last arguments specify addresses of values to be read. Expected
1280 ** type is checked against the type actually present on the stream.
1283 int
1284 objc_read_types(TypedStream* stream, const char* type, ...)
1286 va_list args;
1287 const char *c;
1288 int res = 0;
1290 va_start(args, type);
1292 for (c = type; *c; c = objc_skip_typespec(c))
1294 switch(*c) {
1295 case _C_ID:
1296 res = objc_read_object(stream, va_arg(args, id*));
1297 break;
1299 case _C_CLASS:
1300 res = objc_read_class(stream, va_arg(args, Class*));
1301 break;
1303 case _C_SEL:
1304 res = objc_read_selector(stream, va_arg(args, SEL*));
1305 break;
1307 case _C_CHR:
1308 res = objc_read_char(stream, va_arg(args, char*));
1309 break;
1311 case _C_UCHR:
1312 res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
1313 break;
1315 case _C_SHT:
1316 res = objc_read_short(stream, va_arg(args, short*));
1317 break;
1319 case _C_USHT:
1320 res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
1321 break;
1323 case _C_INT:
1324 res = objc_read_int(stream, va_arg(args, int*));
1325 break;
1327 case _C_UINT:
1328 res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
1329 break;
1331 case _C_LNG:
1332 res = objc_read_long(stream, va_arg(args, long*));
1333 break;
1335 case _C_ULNG:
1336 res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*));
1337 break;
1339 case _C_CHARPTR:
1340 case _C_ATOM:
1342 char** str = va_arg(args, char**);
1343 res = objc_read_string (stream, str);
1345 break;
1347 case _C_ARY_B:
1349 int len = atoi(c+1);
1350 const char* t = c;
1351 while (isdigit((unsigned char)*++t))
1353 res = objc_read_array (stream, t, len, va_arg(args, void*));
1354 t = objc_skip_typespec (t);
1355 if (*t != _C_ARY_E)
1356 objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
1358 break;
1360 default:
1361 objc_error(nil, OBJC_ERR_BAD_TYPE,
1362 "objc_read_types: cannot parse typespec: %s\n", type);
1365 va_end(args);
1366 return res;
1370 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1371 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1375 objc_write_array (TypedStream* stream, const char* type,
1376 int count, const void* data)
1378 int off = objc_sizeof_type(type);
1379 const char* where = data;
1381 while (count-- > 0)
1383 objc_write_type(stream, type, where);
1384 where += off;
1386 return 1;
1390 ** Read an array of COUNT elements of TYPE into the memory address
1391 ** DATA. The memory pointed to by data is supposed to be allocated
1392 ** by the callee. This is equivalent of
1393 ** objc_read_type (stream, "[N<type>]", data)
1397 objc_read_array (TypedStream* stream, const char* type,
1398 int count, void* data)
1400 int off = objc_sizeof_type(type);
1401 char* where = (char*)data;
1403 while (count-- > 0)
1405 objc_read_type(stream, type, where);
1406 where += off;
1408 return 1;
1411 static int
1412 __objc_fread(FILE* file, char* data, int len)
1414 return fread(data, len, 1, file);
1417 static int
1418 __objc_fwrite(FILE* file, char* data, int len)
1420 return fwrite(data, len, 1, file);
1423 static int
1424 __objc_feof(FILE* file)
1426 return feof(file);
1429 static int
1430 __objc_no_write(FILE* file __attribute__ ((__unused__)),
1431 const char *data __attribute__ ((__unused__)),
1432 int len __attribute__ ((__unused__)))
1434 objc_error (nil, OBJC_ERR_NO_WRITE, "TypedStream not open for writing");
1435 return 0;
1438 static int
1439 __objc_no_read(FILE* file __attribute__ ((__unused__)),
1440 const char *data __attribute__ ((__unused__)),
1441 int len __attribute__ ((__unused__)))
1443 objc_error (nil, OBJC_ERR_NO_READ, "TypedStream not open for reading");
1444 return 0;
1447 static int
1448 __objc_read_typed_stream_signature (TypedStream* stream)
1450 char buffer[80];
1451 int pos = 0;
1453 (*stream->read)(stream->physical, buffer+pos, 1);
1454 while (buffer[pos++] != '\0')
1456 sscanf (buffer, "GNU TypedStream %d", &stream->version);
1457 if (stream->version != OBJC_TYPED_STREAM_VERSION)
1458 objc_error (nil, OBJC_ERR_STREAM_VERSION,
1459 "cannot handle TypedStream version %d", stream->version);
1460 return 1;
1463 static int
1464 __objc_write_typed_stream_signature (TypedStream* stream)
1466 char buffer[80];
1467 sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
1468 stream->version = OBJC_TYPED_STREAM_VERSION;
1469 (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
1470 return 1;
1473 static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
1475 hash_delete (stream->object_table);
1476 stream->object_table = hash_new(64,
1477 (hash_func_type)hash_ptr,
1478 (compare_func_type)compare_ptrs);
1481 static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
1483 node_ptr node;
1484 SEL awake_sel = sel_get_any_uid ("awake");
1485 cache_ptr free_list = hash_new (64,
1486 (hash_func_type) hash_ptr,
1487 (compare_func_type) compare_ptrs);
1489 /* resolve object forward references */
1490 for (node = hash_next (stream->object_refs, NULL); node;
1491 node = hash_next (stream->object_refs, node))
1493 struct objc_list* reflist = node->value;
1494 const void* key = node->key;
1495 id object = hash_value_for_key (stream->object_table, key);
1496 while(reflist)
1498 *((id*)reflist->head) = object;
1499 if (hash_value_for_key (free_list,reflist) == NULL)
1500 hash_add (&free_list,reflist,reflist);
1502 reflist = reflist->tail;
1506 /* apply __objc_free to all objects stored in free_list */
1507 for (node = hash_next (free_list, NULL); node;
1508 node = hash_next (free_list, node))
1509 objc_free ((void *) node->key);
1511 hash_delete (free_list);
1513 /* empty object reference table */
1514 hash_delete (stream->object_refs);
1515 stream->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1516 (compare_func_type)compare_ptrs);
1518 /* call -awake for all objects read */
1519 if (awake_sel)
1521 for (node = hash_next (stream->object_table, NULL); node;
1522 node = hash_next (stream->object_table, node))
1524 id object = node->value;
1525 if (__objc_responds_to (object, awake_sel))
1526 (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
1530 /* empty object table */
1531 hash_delete (stream->object_table);
1532 stream->object_table = hash_new(64,
1533 (hash_func_type)hash_ptr,
1534 (compare_func_type)compare_ptrs);
1538 ** Open the stream PHYSICAL in MODE
1541 TypedStream*
1542 objc_open_typed_stream (FILE* physical, int mode)
1544 TypedStream* s = (TypedStream*)objc_malloc(sizeof(TypedStream));
1546 s->mode = mode;
1547 s->physical = physical;
1548 s->stream_table = hash_new(64,
1549 (hash_func_type)hash_ptr,
1550 (compare_func_type)compare_ptrs);
1551 s->object_table = hash_new(64,
1552 (hash_func_type)hash_ptr,
1553 (compare_func_type)compare_ptrs);
1554 s->eof = (objc_typed_eof_func)__objc_feof;
1555 s->flush = (objc_typed_flush_func)fflush;
1556 s->writing_root_p = 0;
1557 if (mode == OBJC_READONLY)
1559 s->class_table = hash_new(8, (hash_func_type)hash_string,
1560 (compare_func_type)compare_strings);
1561 s->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1562 (compare_func_type)compare_ptrs);
1563 s->read = (objc_typed_read_func)__objc_fread;
1564 s->write = (objc_typed_write_func)__objc_no_write;
1565 __objc_read_typed_stream_signature (s);
1567 else if (mode == OBJC_WRITEONLY)
1569 s->class_table = 0;
1570 s->object_refs = 0;
1571 s->read = (objc_typed_read_func)__objc_no_read;
1572 s->write = (objc_typed_write_func)__objc_fwrite;
1573 __objc_write_typed_stream_signature (s);
1575 else
1577 objc_close_typed_stream (s);
1578 return NULL;
1580 s->type = OBJC_FILE_STREAM;
1581 return s;
1585 ** Open the file named by FILE_NAME in MODE
1588 TypedStream*
1589 objc_open_typed_stream_for_file (const char* file_name, int mode)
1591 FILE* file = NULL;
1592 TypedStream* s;
1594 if (mode == OBJC_READONLY)
1595 file = fopen (file_name, "r");
1596 else
1597 file = fopen (file_name, "w");
1599 if (file)
1601 s = objc_open_typed_stream (file, mode);
1602 if (s)
1603 s->type |= OBJC_MANAGED_STREAM;
1604 return s;
1606 else
1607 return NULL;
1611 ** Close STREAM freeing the structure it self. If it was opened with
1612 ** objc_open_typed_stream_for_file, the file will also be closed.
1615 void
1616 objc_close_typed_stream (TypedStream* stream)
1618 if (stream->mode == OBJC_READONLY)
1620 __objc_finish_read_root_object (stream); /* Just in case... */
1621 hash_delete (stream->class_table);
1622 hash_delete (stream->object_refs);
1625 hash_delete (stream->stream_table);
1626 hash_delete (stream->object_table);
1628 if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1629 fclose ((FILE*)stream->physical);
1631 objc_free(stream);
1634 BOOL
1635 objc_end_of_typed_stream (TypedStream* stream)
1637 return (*stream->eof)(stream->physical);
1640 void
1641 objc_flush_typed_stream (TypedStream* stream)
1643 (*stream->flush)(stream->physical);
1646 long
1647 objc_get_stream_class_version (TypedStream* stream, Class class)
1649 if (stream->class_table)
1650 return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
1651 else
1652 return class_get_version (class);