Add bugs corresponding to PRs 16243 and 16245
[official-gcc.git] / gcc / objc / archive.c
blob2edb056acbac1ed61163e167cc736a6bd9bf46cb
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 "runtime.h"
28 #include "typedstream.h"
29 #include "encoding.h"
31 extern int fflush(FILE*);
33 #define ROUND(V, A) \
34 ({ typeof(V) __v=(V); typeof(A) __a=(A); \
35 __a*((__v+__a-1)/__a); })
37 #define PTR2LONG(P) (((char*)(P))-(char*)0)
38 #define LONG2PTR(L) (((char*)0)+(L))
40 /* Declare some functions... */
42 static int
43 objc_read_class (struct objc_typed_stream* stream, Class* class);
45 int objc_sizeof_type(const char* type);
47 static int
48 objc_write_use_common (struct objc_typed_stream* stream, unsigned long key);
50 static int
51 objc_write_register_common (struct objc_typed_stream* stream,
52 unsigned long key);
54 static int
55 objc_write_class (struct objc_typed_stream* stream,
56 struct objc_class* class);
58 const char* objc_skip_type (const char* type);
60 static void __objc_finish_write_root_object(struct objc_typed_stream*);
61 static void __objc_finish_read_root_object(struct objc_typed_stream*);
63 static __inline__ int
64 __objc_code_unsigned_char (unsigned char* buf, unsigned char val)
66 if ((val&_B_VALUE) == val)
68 buf[0] = val|_B_SINT;
69 return 1;
71 else
73 buf[0] = _B_NINT|0x01;
74 buf[1] = val;
75 return 2;
79 int
80 objc_write_unsigned_char (struct objc_typed_stream* stream,
81 unsigned char value)
83 unsigned char buf[sizeof (unsigned char)+1];
84 int len = __objc_code_unsigned_char (buf, value);
85 return (*stream->write)(stream->physical, buf, len);
88 static __inline__ int
89 __objc_code_char (unsigned char* buf, char val)
91 if (val >= 0)
92 return __objc_code_unsigned_char (buf, val);
93 else
95 buf[0] = _B_NINT|_B_SIGN|0x01;
96 buf[1] = -val;
97 return 2;
102 objc_write_char (struct objc_typed_stream* stream, char value)
104 unsigned char buf[sizeof (char)+1];
105 int len = __objc_code_char (buf, value);
106 return (*stream->write)(stream->physical, buf, len);
109 static __inline__ int
110 __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
112 if ((val&_B_VALUE) == val)
114 buf[0] = val|_B_SINT;
115 return 1;
117 else
119 int c, b;
121 buf[0] = _B_NINT;
123 for (c= sizeof(short); c != 0; c -= 1)
124 if (((val>>(8*(c-1)))%0x100) != 0)
125 break;
127 buf[0] |= c;
129 for (b = 1; c != 0; c--, b++)
131 buf[b] = (val >> (8*(c-1)))%0x100;
134 return b;
139 objc_write_unsigned_short (struct objc_typed_stream* stream,
140 unsigned short value)
142 unsigned char buf[sizeof (unsigned short)+1];
143 int len = __objc_code_unsigned_short (buf, value);
144 return (*stream->write)(stream->physical, buf, len);
147 static __inline__ int
148 __objc_code_short (unsigned char* buf, short val)
150 int sign = (val < 0);
151 int size = __objc_code_unsigned_short (buf, sign ? -val : val);
152 if (sign)
153 buf[0] |= _B_SIGN;
154 return size;
158 objc_write_short (struct objc_typed_stream* stream, short value)
160 unsigned char buf[sizeof (short)+1];
161 int len = __objc_code_short (buf, value);
162 return (*stream->write)(stream->physical, buf, len);
166 static __inline__ int
167 __objc_code_unsigned_int (unsigned char* buf, unsigned int val)
169 if ((val&_B_VALUE) == val)
171 buf[0] = val|_B_SINT;
172 return 1;
174 else
176 int c, b;
178 buf[0] = _B_NINT;
180 for (c= sizeof(int); c != 0; c -= 1)
181 if (((val>>(8*(c-1)))%0x100) != 0)
182 break;
184 buf[0] |= c;
186 for (b = 1; c != 0; c--, b++)
188 buf[b] = (val >> (8*(c-1)))%0x100;
191 return b;
196 objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value)
198 unsigned char buf[sizeof(unsigned int)+1];
199 int len = __objc_code_unsigned_int (buf, value);
200 return (*stream->write)(stream->physical, buf, len);
203 static __inline__ int
204 __objc_code_int (unsigned char* buf, int val)
206 int sign = (val < 0);
207 int size = __objc_code_unsigned_int (buf, sign ? -val : val);
208 if (sign)
209 buf[0] |= _B_SIGN;
210 return size;
214 objc_write_int (struct objc_typed_stream* stream, int value)
216 unsigned char buf[sizeof(int)+1];
217 int len = __objc_code_int (buf, value);
218 return (*stream->write)(stream->physical, buf, len);
221 static __inline__ int
222 __objc_code_unsigned_long (unsigned char* buf, unsigned long val)
224 if ((val&_B_VALUE) == val)
226 buf[0] = val|_B_SINT;
227 return 1;
229 else
231 int c, b;
233 buf[0] = _B_NINT;
235 for (c= sizeof(long); c != 0; c -= 1)
236 if (((val>>(8*(c-1)))%0x100) != 0)
237 break;
239 buf[0] |= c;
241 for (b = 1; c != 0; c--, b++)
243 buf[b] = (val >> (8*(c-1)))%0x100;
246 return b;
251 objc_write_unsigned_long (struct objc_typed_stream* stream,
252 unsigned long value)
254 unsigned char buf[sizeof(unsigned long)+1];
255 int len = __objc_code_unsigned_long (buf, value);
256 return (*stream->write)(stream->physical, buf, len);
259 static __inline__ int
260 __objc_code_long (unsigned char* buf, long val)
262 int sign = (val < 0);
263 int size = __objc_code_unsigned_long (buf, sign ? -val : val);
264 if (sign)
265 buf[0] |= _B_SIGN;
266 return size;
270 objc_write_long (struct objc_typed_stream* stream, long value)
272 unsigned char buf[sizeof(long)+1];
273 int len = __objc_code_long (buf, value);
274 return (*stream->write)(stream->physical, buf, len);
279 objc_write_string (struct objc_typed_stream* stream,
280 const unsigned char* string, unsigned int nbytes)
282 unsigned char buf[sizeof(unsigned int)+1];
283 int len = __objc_code_unsigned_int (buf, nbytes);
285 if ((buf[0]&_B_CODE) == _B_SINT)
286 buf[0] = (buf[0]&_B_VALUE)|_B_SSTR;
288 else /* _B_NINT */
289 buf[0] = (buf[0]&_B_VALUE)|_B_NSTR;
291 if ((*stream->write)(stream->physical, buf, len) != 0)
292 return (*stream->write)(stream->physical, string, nbytes);
293 else
294 return 0;
298 objc_write_string_atomic (struct objc_typed_stream* stream,
299 unsigned char* string, unsigned int nbytes)
301 unsigned long key;
302 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string))))
303 return objc_write_use_common (stream, key);
304 else
306 int length;
307 hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string);
308 if ((length = objc_write_register_common (stream, key)))
309 return objc_write_string (stream, string, nbytes);
310 return length;
314 static int
315 objc_write_register_common (struct objc_typed_stream* stream,
316 unsigned long key)
318 unsigned char buf[sizeof (unsigned long)+2];
319 int len = __objc_code_unsigned_long (buf+1, key);
320 if (len == 1)
322 buf[0] = _B_RCOMM|0x01;
323 buf[1] &= _B_VALUE;
324 return (*stream->write)(stream->physical, buf, len+1);
326 else
328 buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM;
329 return (*stream->write)(stream->physical, buf+1, len);
333 static int
334 objc_write_use_common (struct objc_typed_stream* stream, unsigned long key)
336 unsigned char buf[sizeof (unsigned long)+2];
337 int len = __objc_code_unsigned_long (buf+1, key);
338 if (len == 1)
340 buf[0] = _B_UCOMM|0x01;
341 buf[1] &= _B_VALUE;
342 return (*stream->write)(stream->physical, buf, 2);
344 else
346 buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM;
347 return (*stream->write)(stream->physical, buf+1, len);
351 static __inline__ int
352 __objc_write_extension (struct objc_typed_stream* stream, unsigned char code)
354 if (code <= _B_VALUE)
356 unsigned char buf = code|_B_EXT;
357 return (*stream->write)(stream->physical, &buf, 1);
359 else
360 objc_error(nil, OBJC_ERR_BAD_OPCODE,
361 "__objc_write_extension: bad opcode %c\n", code);
364 __inline__ int
365 __objc_write_object (struct objc_typed_stream* stream, id object)
367 unsigned char buf = '\0';
368 SEL write_sel = sel_get_any_uid ("write:");
369 if (object)
371 __objc_write_extension (stream, _BX_OBJECT);
372 objc_write_class (stream, object->class_pointer);
373 (*objc_msg_lookup(object, write_sel))(object, write_sel, stream);
374 return (*stream->write)(stream->physical, &buf, 1);
376 else
377 return objc_write_use_common(stream, 0);
380 int
381 objc_write_object_reference (struct objc_typed_stream* stream, id object)
383 unsigned long key;
384 if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
385 return objc_write_use_common (stream, key);
387 __objc_write_extension (stream, _BX_OBJREF);
388 return objc_write_unsigned_long (stream, PTR2LONG (object));
391 int
392 objc_write_root_object (struct objc_typed_stream* stream, id object)
394 int len;
395 if (stream->writing_root_p)
396 objc_error (nil, OBJC_ERR_RECURSE_ROOT,
397 "objc_write_root_object called recursively");
398 else
400 stream->writing_root_p = 1;
401 __objc_write_extension (stream, _BX_OBJROOT);
402 if((len = objc_write_object (stream, object)))
403 __objc_finish_write_root_object(stream);
404 stream->writing_root_p = 0;
406 return len;
409 int
410 objc_write_object (struct objc_typed_stream* stream, id object)
412 unsigned long key;
413 if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
414 return objc_write_use_common (stream, key);
416 else if (object == nil)
417 return objc_write_use_common(stream, 0);
419 else
421 int length;
422 hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object);
423 if ((length = objc_write_register_common (stream, key)))
424 return __objc_write_object (stream, object);
425 return length;
429 #ifdef __alpha__
430 extern int atoi (const char*);
431 extern size_t strlen(const char*);
432 extern size_t strcpy(char*, const char*);
433 #endif
435 __inline__ int
436 __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class)
438 __objc_write_extension (stream, _BX_CLASS);
439 objc_write_string_atomic(stream, (char*)class->name,
440 strlen((char*)class->name));
441 return objc_write_unsigned_long (stream, class->version);
445 static int
446 objc_write_class (struct objc_typed_stream* stream,
447 struct objc_class* class)
449 unsigned long key;
450 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class))))
451 return objc_write_use_common (stream, key);
452 else
454 int length;
455 hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class);
456 if ((length = objc_write_register_common (stream, key)))
457 return __objc_write_class (stream, class);
458 return length;
463 __inline__ int
464 __objc_write_selector (struct objc_typed_stream* stream, SEL selector)
466 const char* sel_name;
467 __objc_write_extension (stream, _BX_SEL);
468 /* to handle NULL selectors */
469 if ((SEL)0 == selector)
470 return objc_write_string (stream, "", 0);
471 sel_name = sel_get_name (selector);
472 return objc_write_string (stream, sel_name, strlen ((char*)sel_name));
475 int
476 objc_write_selector (struct objc_typed_stream* stream, SEL selector)
478 const char* sel_name;
479 unsigned long key;
481 /* to handle NULL selectors */
482 if ((SEL)0 == selector)
483 return __objc_write_selector (stream, selector);
485 sel_name = sel_get_name (selector);
486 if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name))))
487 return objc_write_use_common (stream, key);
488 else
490 int length;
491 hash_add (&stream->stream_table,
492 LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
493 if ((length = objc_write_register_common (stream, key)))
494 return __objc_write_selector (stream, selector);
495 return length;
502 ** Read operations
505 __inline__ int
506 objc_read_char (struct objc_typed_stream* stream, char* val)
508 unsigned char buf;
509 int len;
510 len = (*stream->read)(stream->physical, &buf, 1);
511 if (len != 0)
513 if ((buf & _B_CODE) == _B_SINT)
514 (*val) = (buf & _B_VALUE);
516 else if ((buf & _B_NUMBER) == 1)
518 len = (*stream->read)(stream->physical, val, 1);
519 if (buf&_B_SIGN)
520 (*val) = -1*(*val);
523 else
524 objc_error(nil, OBJC_ERR_BAD_DATA,
525 "expected 8bit signed int, got %dbit int",
526 (int)(buf&_B_NUMBER)*8);
528 return len;
532 __inline__ int
533 objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val)
535 unsigned char buf;
536 int len;
537 if ((len = (*stream->read)(stream->physical, &buf, 1)))
539 if ((buf & _B_CODE) == _B_SINT)
540 (*val) = (buf & _B_VALUE);
542 else if ((buf & _B_NUMBER) == 1)
543 len = (*stream->read)(stream->physical, val, 1);
545 else
546 objc_error(nil, OBJC_ERR_BAD_DATA,
547 "expected 8bit unsigned int, got %dbit int",
548 (int)(buf&_B_NUMBER)*8);
550 return len;
553 __inline__ int
554 objc_read_short (struct objc_typed_stream* stream, short* value)
556 unsigned char buf[sizeof(short)+1];
557 int len;
558 if ((len = (*stream->read)(stream->physical, buf, 1)))
560 if ((buf[0] & _B_CODE) == _B_SINT)
561 (*value) = (buf[0] & _B_VALUE);
563 else
565 int pos = 1;
566 int nbytes = buf[0] & _B_NUMBER;
567 if (nbytes > sizeof (short))
568 objc_error(nil, OBJC_ERR_BAD_DATA,
569 "expected short, got bigger (%dbits)", nbytes*8);
570 len = (*stream->read)(stream->physical, buf+1, nbytes);
571 (*value) = 0;
572 while (pos <= nbytes)
573 (*value) = ((*value)*0x100) + buf[pos++];
574 if (buf[0] & _B_SIGN)
575 (*value) = -(*value);
578 return len;
581 __inline__ int
582 objc_read_unsigned_short (struct objc_typed_stream* stream,
583 unsigned short* value)
585 unsigned char buf[sizeof(unsigned short)+1];
586 int len;
587 if ((len = (*stream->read)(stream->physical, buf, 1)))
589 if ((buf[0] & _B_CODE) == _B_SINT)
590 (*value) = (buf[0] & _B_VALUE);
592 else
594 int pos = 1;
595 int nbytes = buf[0] & _B_NUMBER;
596 if (nbytes > sizeof (short))
597 objc_error(nil, OBJC_ERR_BAD_DATA,
598 "expected short, got int or bigger");
599 len = (*stream->read)(stream->physical, buf+1, nbytes);
600 (*value) = 0;
601 while (pos <= nbytes)
602 (*value) = ((*value)*0x100) + buf[pos++];
605 return len;
609 __inline__ int
610 objc_read_int (struct objc_typed_stream* stream, int* value)
612 unsigned char buf[sizeof(int)+1];
613 int len;
614 if ((len = (*stream->read)(stream->physical, buf, 1)))
616 if ((buf[0] & _B_CODE) == _B_SINT)
617 (*value) = (buf[0] & _B_VALUE);
619 else
621 int pos = 1;
622 int nbytes = buf[0] & _B_NUMBER;
623 if (nbytes > sizeof (int))
624 objc_error(nil, OBJC_ERR_BAD_DATA, "expected int, got bigger");
625 len = (*stream->read)(stream->physical, buf+1, nbytes);
626 (*value) = 0;
627 while (pos <= nbytes)
628 (*value) = ((*value)*0x100) + buf[pos++];
629 if (buf[0] & _B_SIGN)
630 (*value) = -(*value);
633 return len;
636 __inline__ int
637 objc_read_long (struct objc_typed_stream* stream, long* value)
639 unsigned char buf[sizeof(long)+1];
640 int len;
641 if ((len = (*stream->read)(stream->physical, buf, 1)))
643 if ((buf[0] & _B_CODE) == _B_SINT)
644 (*value) = (buf[0] & _B_VALUE);
646 else
648 int pos = 1;
649 int nbytes = buf[0] & _B_NUMBER;
650 if (nbytes > sizeof (long))
651 objc_error(nil, OBJC_ERR_BAD_DATA, "expected long, got bigger");
652 len = (*stream->read)(stream->physical, buf+1, nbytes);
653 (*value) = 0;
654 while (pos <= nbytes)
655 (*value) = ((*value)*0x100) + buf[pos++];
656 if (buf[0] & _B_SIGN)
657 (*value) = -(*value);
660 return len;
663 __inline__ int
664 __objc_read_nbyte_uint (struct objc_typed_stream* stream,
665 unsigned int nbytes, unsigned int* val)
667 int len, 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, pos = 0;
704 unsigned char buf[sizeof(unsigned long)+1];
706 if (nbytes > sizeof (long))
707 objc_error(nil, OBJC_ERR_BAD_DATA, "expected long, got bigger");
709 len = (*stream->read)(stream->physical, buf, nbytes);
710 (*val) = 0;
711 while (pos < nbytes)
712 (*val) = ((*val)*0x100) + buf[pos++];
713 return len;
717 __inline__ int
718 objc_read_unsigned_long (struct objc_typed_stream* stream,
719 unsigned long* value)
721 unsigned char buf[sizeof(unsigned long)+1];
722 int len;
723 if ((len = (*stream->read)(stream->physical, buf, 1)))
725 if ((buf[0] & _B_CODE) == _B_SINT)
726 (*value) = (buf[0] & _B_VALUE);
728 else
729 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value);
732 return len;
735 __inline__ int
736 objc_read_string (struct objc_typed_stream* stream,
737 char** string)
739 unsigned char buf[sizeof(unsigned int)+1];
740 int len;
741 if ((len = (*stream->read)(stream->physical, buf, 1)))
743 unsigned long key = 0;
745 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
747 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
748 len = (*stream->read)(stream->physical, buf, 1);
751 switch (buf[0]&_B_CODE) {
752 case _B_SSTR:
754 int length = buf[0]&_B_VALUE;
755 (*string) = (char*)objc_malloc(length+1);
756 if (key)
757 hash_add (&stream->stream_table, LONG2PTR(key), *string);
758 len = (*stream->read)(stream->physical, *string, length);
759 (*string)[length] = '\0';
761 break;
763 case _B_UCOMM:
765 char *tmp;
766 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
767 tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key));
768 *string = objc_malloc (strlen(tmp) + 1);
769 strcpy (*string, tmp);
771 break;
773 case _B_NSTR:
775 unsigned int nbytes = buf[0]&_B_VALUE;
776 len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
777 if (len) {
778 (*string) = (char*)objc_malloc(nbytes+1);
779 if (key)
780 hash_add (&stream->stream_table, LONG2PTR(key), *string);
781 len = (*stream->read)(stream->physical, *string, nbytes);
782 (*string)[nbytes] = '\0';
785 break;
787 default:
788 objc_error(nil, OBJC_ERR_BAD_DATA,
789 "expected string, got opcode %c\n", (buf[0]&_B_CODE));
793 return len;
798 objc_read_object (struct objc_typed_stream* stream, id* object)
800 unsigned char buf[sizeof (unsigned int)];
801 int len;
802 if ((len = (*stream->read)(stream->physical, buf, 1)))
804 SEL read_sel = sel_get_any_uid ("read:");
805 unsigned long key = 0;
807 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
809 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
810 len = (*stream->read)(stream->physical, buf, 1);
813 if (buf[0] == (_B_EXT | _BX_OBJECT))
815 Class class;
817 /* get class */
818 len = objc_read_class (stream, &class);
820 /* create instance */
821 (*object) = class_create_instance(class);
823 /* register? */
824 if (key)
825 hash_add (&stream->object_table, LONG2PTR(key), *object);
827 /* send -read: */
828 if (__objc_responds_to (*object, read_sel))
829 (*get_imp(class, read_sel))(*object, read_sel, stream);
831 /* check null-byte */
832 len = (*stream->read)(stream->physical, buf, 1);
833 if (buf[0] != '\0')
834 objc_error(nil, OBJC_ERR_BAD_DATA,
835 "expected null-byte, got opcode %c", buf[0]);
838 else if ((buf[0]&_B_CODE) == _B_UCOMM)
840 if (key)
841 objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
842 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
843 (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
846 else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
848 struct objc_list* other;
849 len = objc_read_unsigned_long (stream, &key);
850 other = (struct objc_list*)hash_value_for_key (stream->object_refs,
851 LONG2PTR(key));
852 hash_add (&stream->object_refs, LONG2PTR(key),
853 (void*)list_cons(object, other));
856 else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
858 if (key)
859 objc_error(nil, OBJC_ERR_BAD_KEY,
860 "cannot register root object...");
861 len = objc_read_object (stream, object);
862 __objc_finish_read_root_object (stream);
865 else
866 objc_error(nil, OBJC_ERR_BAD_DATA,
867 "expected object, got opcode %c", buf[0]);
869 return len;
872 static int
873 objc_read_class (struct objc_typed_stream* stream, Class* class)
875 unsigned char buf[sizeof (unsigned int)];
876 int len;
877 if ((len = (*stream->read)(stream->physical, buf, 1)))
879 unsigned long key = 0;
881 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
883 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
884 len = (*stream->read)(stream->physical, buf, 1);
887 if (buf[0] == (_B_EXT | _BX_CLASS))
889 char* class_name;
890 unsigned long version;
892 /* get class */
893 len = objc_read_string (stream, &class_name);
894 (*class) = objc_get_class(class_name);
895 objc_free(class_name);
897 /* register */
898 if (key)
899 hash_add (&stream->stream_table, LONG2PTR(key), *class);
901 objc_read_unsigned_long(stream, &version);
902 hash_add (&stream->class_table, (*class)->name, (void*)version);
905 else if ((buf[0]&_B_CODE) == _B_UCOMM)
907 if (key)
908 objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
909 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
910 (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
911 if (!*class)
912 objc_error(nil, OBJC_ERR_BAD_CLASS,
913 "cannot find class for key %lu", key);
916 else
917 objc_error(nil, OBJC_ERR_BAD_DATA,
918 "expected class, got opcode %c", buf[0]);
920 return len;
924 objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
926 unsigned char buf[sizeof (unsigned int)];
927 int len;
928 if ((len = (*stream->read)(stream->physical, buf, 1)))
930 unsigned long key = 0;
932 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
934 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
935 len = (*stream->read)(stream->physical, buf, 1);
938 if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
940 char* selector_name;
942 /* get selector */
943 len = objc_read_string (stream, &selector_name);
944 /* To handle NULL selectors */
945 if (0 == strlen(selector_name))
947 (*selector) = (SEL)0;
948 return 0;
950 else
951 (*selector) = sel_get_any_uid(selector_name);
952 objc_free(selector_name);
954 /* register */
955 if (key)
956 hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
959 else if ((buf[0]&_B_CODE) == _B_UCOMM)
961 if (key)
962 objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
963 len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
964 (*selector) = hash_value_for_key (stream->stream_table,
965 LONG2PTR(key));
968 else
969 objc_error(nil, OBJC_ERR_BAD_DATA,
970 "expected selector, got opcode %c", buf[0]);
972 return len;
976 ** USER LEVEL FUNCTIONS
980 ** Write one object, encoded in TYPE and pointed to by DATA to the
981 ** typed stream STREAM.
985 objc_write_type(TypedStream* stream, const char* type, const void* data)
987 switch(*type) {
988 case _C_ID:
989 return objc_write_object (stream, *(id*)data);
990 break;
992 case _C_CLASS:
993 return objc_write_class (stream, *(Class*)data);
994 break;
996 case _C_SEL:
997 return objc_write_selector (stream, *(SEL*)data);
998 break;
1000 case _C_CHR:
1001 return objc_write_char(stream, *(char*)data);
1002 break;
1004 case _C_UCHR:
1005 return objc_write_unsigned_char(stream, *(unsigned char*)data);
1006 break;
1008 case _C_SHT:
1009 return objc_write_short(stream, *(short*)data);
1010 break;
1012 case _C_USHT:
1013 return objc_write_unsigned_short(stream, *(unsigned short*)data);
1014 break;
1016 case _C_INT:
1017 return objc_write_int(stream, *(int*)data);
1018 break;
1020 case _C_UINT:
1021 return objc_write_unsigned_int(stream, *(unsigned int*)data);
1022 break;
1024 case _C_LNG:
1025 return objc_write_long(stream, *(long*)data);
1026 break;
1028 case _C_ULNG:
1029 return objc_write_unsigned_long(stream, *(unsigned long*)data);
1030 break;
1032 case _C_CHARPTR:
1033 return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
1034 break;
1036 case _C_ATOM:
1037 return objc_write_string_atomic (stream, *(char**)data,
1038 strlen(*(char**)data));
1039 break;
1041 case _C_ARY_B:
1043 int len = atoi(type+1);
1044 while (isdigit(*++type))
1046 return objc_write_array (stream, type, len, data);
1048 break;
1050 case _C_STRUCT_B:
1052 int acc_size = 0;
1053 int align;
1054 while (*type != _C_STRUCT_E && *type++ != '=')
1055 ; /* skip "<name>=" */
1056 while (*type != _C_STRUCT_E)
1058 align = objc_alignof_type (type); /* padd to alignment */
1059 acc_size += ROUND (acc_size, align);
1060 objc_write_type (stream, type, ((char*)data)+acc_size);
1061 acc_size += objc_sizeof_type (type); /* add component size */
1062 type = objc_skip_typespec (type); /* skip component */
1064 return 1;
1067 default:
1068 objc_error(nil, OBJC_ERR_BAD_TYPE,
1069 "objc_write_type: cannot parse typespec: %s\n", type);
1074 ** Read one object, encoded in TYPE and pointed to by DATA to the
1075 ** typed stream STREAM. DATA specifies the address of the types to
1076 ** read. Expected type is checked against the type actually present
1077 ** on the stream.
1081 objc_read_type(TypedStream* stream, const char* type, void* data)
1083 char c;
1084 switch(c = *type) {
1085 case _C_ID:
1086 return objc_read_object (stream, (id*)data);
1087 break;
1089 case _C_CLASS:
1090 return objc_read_class (stream, (Class*)data);
1091 break;
1093 case _C_SEL:
1094 return objc_read_selector (stream, (SEL*)data);
1095 break;
1097 case _C_CHR:
1098 return objc_read_char (stream, (char*)data);
1099 break;
1101 case _C_UCHR:
1102 return objc_read_unsigned_char (stream, (unsigned char*)data);
1103 break;
1105 case _C_SHT:
1106 return objc_read_short (stream, (short*)data);
1107 break;
1109 case _C_USHT:
1110 return objc_read_unsigned_short (stream, (unsigned short*)data);
1111 break;
1113 case _C_INT:
1114 return objc_read_int (stream, (int*)data);
1115 break;
1117 case _C_UINT:
1118 return objc_read_unsigned_int (stream, (unsigned int*)data);
1119 break;
1121 case _C_LNG:
1122 return objc_read_long (stream, (long*)data);
1123 break;
1125 case _C_ULNG:
1126 return objc_read_unsigned_long (stream, (unsigned long*)data);
1127 break;
1129 case _C_CHARPTR:
1130 case _C_ATOM:
1131 return objc_read_string (stream, (char**)data);
1132 break;
1134 case _C_ARY_B:
1136 int len = atoi(type+1);
1137 while (isdigit(*++type))
1139 return objc_read_array (stream, type, len, data);
1141 break;
1143 case _C_STRUCT_B:
1145 int acc_size = 0;
1146 int align;
1147 while (*type != _C_STRUCT_E && *type++ != '=')
1148 ; /* skip "<name>=" */
1149 while (*type != _C_STRUCT_E)
1151 align = objc_alignof_type (type); /* padd to alignment */
1152 acc_size += ROUND (acc_size, align);
1153 objc_read_type (stream, type, ((char*)data)+acc_size);
1154 acc_size += objc_sizeof_type (type); /* add component size */
1155 type = objc_skip_typespec (type); /* skip component */
1157 return 1;
1160 default:
1161 objc_error(nil, OBJC_ERR_BAD_TYPE,
1162 "objc_read_type: cannot parse typespec: %s\n", type);
1167 ** Write the object specified by the template TYPE to STREAM. Last
1168 ** arguments specify addresses of values to be written. It might
1169 ** seem surprising to specify values by address, but this is extremely
1170 ** convenient for copy-paste with objc_read_types calls. A more
1171 ** down-to-the-earth cause for this passing of addresses is that values
1172 ** of arbitrary size is not well supported in ANSI C for functions with
1173 ** variable number of arguments.
1176 int
1177 objc_write_types (TypedStream* stream, const char* type, ...)
1179 va_list args;
1180 const char *c;
1181 int res = 0;
1183 va_start(args, type);
1185 for (c = type; *c; c = objc_skip_typespec (c))
1187 switch(*c) {
1188 case _C_ID:
1189 res = objc_write_object (stream, *va_arg (args, id*));
1190 break;
1192 case _C_CLASS:
1193 res = objc_write_class (stream, *va_arg(args, Class*));
1194 break;
1196 case _C_SEL:
1197 res = objc_write_selector (stream, *va_arg(args, SEL*));
1198 break;
1200 case _C_CHR:
1201 res = objc_write_char (stream, *va_arg (args, char*));
1202 break;
1204 case _C_UCHR:
1205 res = objc_write_unsigned_char (stream,
1206 *va_arg (args, unsigned char*));
1207 break;
1209 case _C_SHT:
1210 res = objc_write_short (stream, *va_arg(args, short*));
1211 break;
1213 case _C_USHT:
1214 res = objc_write_unsigned_short (stream,
1215 *va_arg(args, unsigned short*));
1216 break;
1218 case _C_INT:
1219 res = objc_write_int(stream, *va_arg(args, int*));
1220 break;
1222 case _C_UINT:
1223 res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
1224 break;
1226 case _C_LNG:
1227 res = objc_write_long(stream, *va_arg(args, long*));
1228 break;
1230 case _C_ULNG:
1231 res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*));
1232 break;
1234 case _C_CHARPTR:
1236 char** str = va_arg(args, char**);
1237 res = objc_write_string (stream, *str, strlen(*str));
1239 break;
1241 case _C_ATOM:
1243 char** str = va_arg(args, char**);
1244 res = objc_write_string_atomic (stream, *str, strlen(*str));
1246 break;
1248 case _C_ARY_B:
1250 int len = atoi(c+1);
1251 const char* t = c;
1252 while (isdigit(*++t))
1254 res = objc_write_array (stream, t, len, va_arg(args, void*));
1255 t = objc_skip_typespec (t);
1256 if (*t != _C_ARY_E)
1257 objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
1259 break;
1261 default:
1262 objc_error(nil, OBJC_ERR_BAD_TYPE,
1263 "objc_write_types: cannot parse typespec: %s\n", type);
1266 va_end(args);
1267 return res;
1272 ** Last arguments specify addresses of values to be read. Expected
1273 ** type is checked against the type actually present on the stream.
1276 int
1277 objc_read_types(TypedStream* stream, const char* type, ...)
1279 va_list args;
1280 const char *c;
1281 int res = 0;
1283 va_start(args, type);
1285 for (c = type; *c; c = objc_skip_typespec(c))
1287 switch(*c) {
1288 case _C_ID:
1289 res = objc_read_object(stream, va_arg(args, id*));
1290 break;
1292 case _C_CLASS:
1293 res = objc_read_class(stream, va_arg(args, Class*));
1294 break;
1296 case _C_SEL:
1297 res = objc_read_selector(stream, va_arg(args, SEL*));
1298 break;
1300 case _C_CHR:
1301 res = objc_read_char(stream, va_arg(args, char*));
1302 break;
1304 case _C_UCHR:
1305 res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
1306 break;
1308 case _C_SHT:
1309 res = objc_read_short(stream, va_arg(args, short*));
1310 break;
1312 case _C_USHT:
1313 res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
1314 break;
1316 case _C_INT:
1317 res = objc_read_int(stream, va_arg(args, int*));
1318 break;
1320 case _C_UINT:
1321 res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
1322 break;
1324 case _C_LNG:
1325 res = objc_read_long(stream, va_arg(args, long*));
1326 break;
1328 case _C_ULNG:
1329 res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*));
1330 break;
1332 case _C_CHARPTR:
1333 case _C_ATOM:
1335 char** str = va_arg(args, char**);
1336 res = objc_read_string (stream, str);
1338 break;
1340 case _C_ARY_B:
1342 int len = atoi(c+1);
1343 const char* t = c;
1344 while (isdigit(*++t))
1346 res = objc_read_array (stream, t, len, va_arg(args, void*));
1347 t = objc_skip_typespec (t);
1348 if (*t != _C_ARY_E)
1349 objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
1351 break;
1353 default:
1354 objc_error(nil, OBJC_ERR_BAD_TYPE,
1355 "objc_read_types: cannot parse typespec: %s\n", type);
1358 va_end(args);
1359 return res;
1363 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1364 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1368 objc_write_array (TypedStream* stream, const char* type,
1369 int count, const void* data)
1371 int off = objc_sizeof_type(type);
1372 const char* where = data;
1374 while (count-- > 0)
1376 objc_write_type(stream, type, where);
1377 where += off;
1379 return 1;
1383 ** Read an array of COUNT elements of TYPE into the memory address
1384 ** DATA. The memory pointed to by data is supposed to be allocated
1385 ** by the callee. This is equivalent of
1386 ** objc_read_type (stream, "[N<type>]", data)
1390 objc_read_array (TypedStream* stream, const char* type,
1391 int count, void* data)
1393 int off = objc_sizeof_type(type);
1394 char* where = (char*)data;
1396 while (count-- > 0)
1398 objc_read_type(stream, type, where);
1399 where += off;
1401 return 1;
1404 static int
1405 __objc_fread(FILE* file, char* data, int len)
1407 return fread(data, len, 1, file);
1410 static int
1411 __objc_fwrite(FILE* file, char* data, int len)
1413 return fwrite(data, len, 1, file);
1416 static int
1417 __objc_feof(FILE* file)
1419 return feof(file);
1422 static int
1423 __objc_no_write(FILE* file, char* data, int len)
1425 objc_error (nil, OBJC_ERR_NO_WRITE, "TypedStream not open for writing");
1428 static int
1429 __objc_no_read(FILE* file, char* data, int len)
1431 objc_error (nil, OBJC_ERR_NO_READ, "TypedStream not open for reading");
1434 static int
1435 __objc_read_typed_stream_signature (TypedStream* stream)
1437 char buffer[80];
1438 int pos = 0;
1440 (*stream->read)(stream->physical, buffer+pos, 1);
1441 while (buffer[pos++] != '\0')
1443 sscanf (buffer, "GNU TypedStream %d", &stream->version);
1444 if (stream->version != OBJC_TYPED_STREAM_VERSION)
1445 objc_error (nil, OBJC_ERR_STREAM_VERSION,
1446 "cannot handle TypedStream version %d", stream->version);
1447 return 1;
1450 static int
1451 __objc_write_typed_stream_signature (TypedStream* stream)
1453 char buffer[80];
1454 sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
1455 stream->version = OBJC_TYPED_STREAM_VERSION;
1456 (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
1457 return 1;
1460 static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
1462 hash_delete (stream->object_table);
1463 stream->object_table = hash_new(64,
1464 (hash_func_type)hash_ptr,
1465 (compare_func_type)compare_ptrs);
1468 static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
1470 node_ptr node;
1471 SEL awake_sel = sel_get_any_uid ("awake");
1472 cache_ptr free_list = hash_new (64,
1473 (hash_func_type) hash_ptr,
1474 (compare_func_type) compare_ptrs);
1476 /* resolve object forward references */
1477 for (node = hash_next (stream->object_refs, NULL); node;
1478 node = hash_next (stream->object_refs, node))
1480 struct objc_list* reflist = node->value;
1481 const void* key = node->key;
1482 id object = hash_value_for_key (stream->object_table, key);
1483 while(reflist)
1485 *((id*)reflist->head) = object;
1486 if (hash_value_for_key (free_list,reflist) == NULL)
1487 hash_add (&free_list,reflist,reflist);
1489 reflist = reflist->tail;
1493 /* apply __objc_free to all objects stored in free_list */
1494 for (node = hash_next (free_list, NULL); node;
1495 node = hash_next (free_list, node))
1496 objc_free ((void *) node->key);
1498 hash_delete (free_list);
1500 /* empty object reference table */
1501 hash_delete (stream->object_refs);
1502 stream->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1503 (compare_func_type)compare_ptrs);
1505 /* call -awake for all objects read */
1506 if (awake_sel)
1508 for (node = hash_next (stream->object_table, NULL); node;
1509 node = hash_next (stream->object_table, node))
1511 id object = node->value;
1512 if (__objc_responds_to (object, awake_sel))
1513 (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
1517 /* empty object table */
1518 hash_delete (stream->object_table);
1519 stream->object_table = hash_new(64,
1520 (hash_func_type)hash_ptr,
1521 (compare_func_type)compare_ptrs);
1525 ** Open the stream PHYSICAL in MODE
1528 TypedStream*
1529 objc_open_typed_stream (FILE* physical, int mode)
1531 TypedStream* s = (TypedStream*)objc_malloc(sizeof(TypedStream));
1533 s->mode = mode;
1534 s->physical = physical;
1535 s->stream_table = hash_new(64,
1536 (hash_func_type)hash_ptr,
1537 (compare_func_type)compare_ptrs);
1538 s->object_table = hash_new(64,
1539 (hash_func_type)hash_ptr,
1540 (compare_func_type)compare_ptrs);
1541 s->eof = (objc_typed_eof_func)__objc_feof;
1542 s->flush = (objc_typed_flush_func)fflush;
1543 s->writing_root_p = 0;
1544 if (mode == OBJC_READONLY)
1546 s->class_table = hash_new(8, (hash_func_type)hash_string,
1547 (compare_func_type)compare_strings);
1548 s->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1549 (compare_func_type)compare_ptrs);
1550 s->read = (objc_typed_read_func)__objc_fread;
1551 s->write = (objc_typed_write_func)__objc_no_write;
1552 __objc_read_typed_stream_signature (s);
1554 else if (mode == OBJC_WRITEONLY)
1556 s->class_table = 0;
1557 s->object_refs = 0;
1558 s->read = (objc_typed_read_func)__objc_no_read;
1559 s->write = (objc_typed_write_func)__objc_fwrite;
1560 __objc_write_typed_stream_signature (s);
1562 else
1564 objc_close_typed_stream (s);
1565 return NULL;
1567 s->type = OBJC_FILE_STREAM;
1568 return s;
1572 ** Open the file named by FILE_NAME in MODE
1575 TypedStream*
1576 objc_open_typed_stream_for_file (const char* file_name, int mode)
1578 FILE* file = NULL;
1579 TypedStream* s;
1581 if (mode == OBJC_READONLY)
1582 file = fopen (file_name, "r");
1583 else
1584 file = fopen (file_name, "w");
1586 if (file)
1588 s = objc_open_typed_stream (file, mode);
1589 if (s)
1590 s->type |= OBJC_MANAGED_STREAM;
1591 return s;
1593 else
1594 return NULL;
1598 ** Close STREAM freeing the structure it self. If it was opened with
1599 ** objc_open_typed_stream_for_file, the file will also be closed.
1602 void
1603 objc_close_typed_stream (TypedStream* stream)
1605 if (stream->mode == OBJC_READONLY)
1607 __objc_finish_read_root_object (stream); /* Just in case... */
1608 hash_delete (stream->class_table);
1609 hash_delete (stream->object_refs);
1612 hash_delete (stream->stream_table);
1613 hash_delete (stream->object_table);
1615 if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1616 fclose ((FILE*)stream->physical);
1618 objc_free(stream);
1621 BOOL
1622 objc_end_of_typed_stream (TypedStream* stream)
1624 return (*stream->eof)(stream->physical);
1627 void
1628 objc_flush_typed_stream (TypedStream* stream)
1630 (*stream->flush)(stream->physical);
1633 long
1634 objc_get_stream_class_version (TypedStream* stream, Class class)
1636 if (stream->class_table)
1637 return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
1638 else
1639 return class_get_version (class);