(all insn and peephole patterns): Rewrite without using arm_output_asm_insn.
[official-gcc.git] / gcc / objc / archive.c
blob1e776c71598d5d6a81c43b7e3a02852e6cee1552
1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993 Free Software Foundation, Inc.
4 Author: Kresten Krab Thorup
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2, or (at your option) any later version.
12 GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 details.
17 You should have received a copy of the GNU General Public License along with
18 GNU CC; see the file COPYING. If not, write to the Free Software
19 Foundation, 675 Mass Ave, Cambridge, MA 02139, 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. */
28 ** Note: This version assumes that int and longs are both 32bit.
31 #ifndef __alpha__
33 #include "runtime.h"
34 #include "typedstream.h"
36 #define __objc_fatal(format, args...) \
37 { fprintf(stderr, "archiving: "); \
38 fprintf(stderr, format, ## args); \
39 fprintf(stderr, "\n"); abort(); }
41 /* Declare some functions... */
43 static int
44 objc_read_class (struct objc_typed_stream* stream, Class** class);
46 static int
47 objc_sizeof_type(const char* type);
49 static int
50 objc_write_use_common (struct objc_typed_stream* stream, unsigned int key);
52 static int
53 objc_write_register_common (struct objc_typed_stream* stream,
54 unsigned int key);
56 static int
57 objc_write_class (struct objc_typed_stream* stream,
58 struct objc_class* class);
60 static const char*
61 __objc_skip_type (const char* type);
63 static void __objc_finish_write_root_object(struct objc_typed_stream*);
64 static void __objc_finish_read_root_object(struct objc_typed_stream*);
66 static __inline__ int
67 __objc_code_unsigned_char (unsigned char* buf, unsigned char val)
69 if ((val&_B_VALUE) == val)
71 buf[0] = val|_B_SINT;
72 return 1;
74 else
76 buf[0] = _B_NINT|0x01;
77 buf[1] = val;
78 return 2;
82 int
83 objc_write_unsigned_char (struct objc_typed_stream* stream,
84 unsigned char value)
86 unsigned char buf[sizeof (unsigned char)+1];
87 int len = __objc_code_unsigned_char (buf, value);
88 return (*stream->write)(stream->physical, buf, len);
91 static __inline__ int
92 __objc_code_char (unsigned char* buf, char val)
94 if (val >= 0)
95 return __objc_code_unsigned_char (buf, val);
96 else
98 buf[0] = _B_NINT|_B_SIGN|0x01;
99 buf[1] = -val;
100 return 2;
105 objc_write_char (struct objc_typed_stream* stream, char value)
107 unsigned char buf[sizeof (char)+1];
108 int len = __objc_code_char (buf, value);
109 return (*stream->write)(stream->physical, buf, len);
112 static __inline__ int
113 __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
115 if (val <= 0xffU)
116 return __objc_code_unsigned_char (buf, val);
118 else
120 buf[0] = _B_NINT|0x02;
121 buf[1] = val/0x100;
122 buf[2] = val%0x100;
123 return 3;
128 objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short value)
130 unsigned char buf[sizeof (unsigned short)+1];
131 int len = __objc_code_unsigned_short (buf, value);
132 return (*stream->write)(stream->physical, buf, len);
135 static __inline__ int
136 __objc_code_short (unsigned char* buf, short val)
138 if (val > 0)
139 return __objc_code_unsigned_short (buf, val);
141 if (val > -0x7f) /* val > -128 */
142 return __objc_code_char (buf, val);
144 else
146 int len = __objc_code_unsigned_short (buf, -val);
147 buf[0] |= _B_SIGN;
148 return len;
153 objc_write_short (struct objc_typed_stream* stream, short value)
155 unsigned char buf[sizeof (short)+1];
156 int len = __objc_code_short (buf, value);
157 return (*stream->write)(stream->physical, buf, len);
161 static __inline__ int
162 __objc_code_unsigned_int (unsigned char* buf, unsigned int val)
164 if (val < 0x10000)
165 return __objc_code_unsigned_short (buf, val%0x10000);
167 else if (val < 0x1000000)
169 buf[0] = _B_NINT|3;
170 buf[1] = val/0x10000;
171 buf[2] = (val%0x10000)/0x100;
172 buf[3] = val%0x100;
173 return 4;
176 else
178 buf[0] = _B_NINT|4;
179 buf[1] = val/0x1000000;
180 buf[2] = (val%0x1000000)/0x10000;
181 buf[3] = (val%0x10000)/0x100;
182 buf[4] = val%0x100;
183 return 5;
188 objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value)
190 unsigned char buf[sizeof(unsigned int)+1];
191 int len = __objc_code_unsigned_int (buf, value);
192 return (*stream->write)(stream->physical, buf, len);
195 static __inline__ int
196 __objc_code_int (unsigned char* buf, int val)
198 if (val >= 0)
199 return __objc_code_unsigned_int (buf, val);
201 if (val > -0x7f)
202 return __objc_code_char (buf, val);
204 else
206 int len = __objc_code_unsigned_int (buf, -val);
207 buf[0] |= _B_SIGN;
208 return len;
213 objc_write_int (struct objc_typed_stream* stream, int value)
215 unsigned char buf[sizeof(int)+1];
216 int len = __objc_code_int (buf, value);
217 return (*stream->write)(stream->physical, buf, len);
221 objc_write_string (struct objc_typed_stream* stream,
222 const unsigned char* string, unsigned int nbytes)
224 unsigned char buf[sizeof(unsigned int)+1];
225 int len = __objc_code_unsigned_int (buf, nbytes);
227 if ((buf[0]&_B_CODE) == _B_SINT)
228 buf[0] = (buf[0]&_B_VALUE)|_B_SSTR;
230 else /* _B_NINT */
231 buf[0] = (buf[0]&_B_VALUE)|_B_NSTR;
233 if ((*stream->write)(stream->physical, buf, len) != 0)
234 return (*stream->write)(stream->physical, string, nbytes);
235 else
236 return 0;
240 objc_write_string_atomic (struct objc_typed_stream* stream,
241 unsigned char* string, unsigned int nbytes)
243 unsigned int key;
244 if ((key = (unsigned int)hash_value_for_key (stream->stream_table, string)))
245 return objc_write_use_common (stream, key);
246 else
248 int length;
249 hash_add (&stream->stream_table, (void*)key=(unsigned int)string, string);
250 if ((length = objc_write_register_common (stream, key)))
251 return objc_write_string (stream, string, nbytes);
252 return length;
256 static int
257 objc_write_register_common (struct objc_typed_stream* stream, unsigned int key)
259 unsigned char buf[sizeof (unsigned int)+2];
260 int len = __objc_code_unsigned_int (buf+1, key);
261 if (len == 1)
263 buf[0] = _B_RCOMM|0x01;
264 buf[1] &= _B_VALUE;
265 return (*stream->write)(stream->physical, buf, len+1);
267 else
269 buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM;
270 return (*stream->write)(stream->physical, buf+1, len);
274 static int
275 objc_write_use_common (struct objc_typed_stream* stream, unsigned int key)
277 unsigned char buf[sizeof (unsigned int)+2];
278 int len = __objc_code_unsigned_int (buf+1, key);
279 if (len == 1)
281 buf[0] = _B_UCOMM|0x01;
282 buf[1] &= _B_VALUE;
283 return (*stream->write)(stream->physical, buf, 2);
285 else
287 buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM;
288 return (*stream->write)(stream->physical, buf+1, len);
292 static __inline__ int
293 __objc_write_extension (struct objc_typed_stream* stream, unsigned char code)
295 if (code <= _B_VALUE)
297 unsigned char buf = code|_B_EXT;
298 return (*stream->write)(stream->physical, &buf, 1);
300 else
301 abort();
304 __inline__ int
305 __objc_write_object (struct objc_typed_stream* stream, id object)
307 unsigned char buf = '\0';
308 SEL write_sel = sel_get_uid ("write:");
309 if (object)
311 __objc_write_extension (stream, _BX_OBJECT);
312 objc_write_class (stream, object->class_pointer);
313 (*objc_msg_lookup(object, write_sel))(object, write_sel, stream);
314 return (*stream->write)(stream->physical, &buf, 1);
316 else
317 return objc_write_use_common(stream, 0);
320 int
321 objc_write_object_reference (struct objc_typed_stream* stream, id object)
323 unsigned int key;
324 if ((key = (unsigned int)hash_value_for_key (stream->object_table, object)))
325 return objc_write_use_common (stream, key);
327 __objc_write_extension (stream, _BX_OBJREF);
328 return objc_write_unsigned_int (stream, (unsigned int)object);
331 int
332 objc_write_root_object (struct objc_typed_stream* stream, id object)
334 int len;
335 if (stream->writing_root_p)
336 __objc_fatal ("objc_write_root_object called recursively")
337 else
339 stream->writing_root_p = 1;
340 __objc_write_extension (stream, _BX_OBJROOT);
341 if((len = objc_write_object (stream, object)))
342 __objc_finish_write_root_object(stream);
343 stream->writing_root_p = 0;
345 return len;
348 int
349 objc_write_object (struct objc_typed_stream* stream, id object)
351 unsigned int key;
352 if ((key = (unsigned int)hash_value_for_key (stream->object_table, object)))
353 return objc_write_use_common (stream, key);
355 else if (object == nil)
356 return objc_write_use_common(stream, 0);
358 else
360 int length;
361 hash_add (&stream->object_table, (void*)key=(unsigned int)object, object);
362 if ((length = objc_write_register_common (stream, key)))
363 return __objc_write_object (stream, object);
364 return length;
368 __inline__ int
369 __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class)
371 __objc_write_extension (stream, _BX_CLASS);
372 objc_write_string_atomic(stream, (char*)class->name,
373 strlen((char*)class->name));
374 return objc_write_unsigned_int (stream, CLS_GETNUMBER(class));
378 static int
379 objc_write_class (struct objc_typed_stream* stream,
380 struct objc_class* class)
382 unsigned int key;
383 if ((key = (unsigned int)hash_value_for_key (stream->stream_table, class)))
384 return objc_write_use_common (stream, key);
385 else
387 int length;
388 hash_add (&stream->stream_table, (void*)key=(unsigned int)class, class);
389 if ((length = objc_write_register_common (stream, key)))
390 return __objc_write_class (stream, class);
391 return length;
396 __inline__ int
397 __objc_write_selector (struct objc_typed_stream* stream, SEL selector)
399 const char* sel_name = sel_get_name (selector);
400 __objc_write_extension (stream, _BX_SEL);
401 return objc_write_string (stream, sel_name, strlen ((char*)sel_name));
404 int
405 objc_write_selector (struct objc_typed_stream* stream, SEL selector)
407 const char* sel_name = sel_get_name (selector);
408 unsigned int key;
409 if ((key = (unsigned int)hash_value_for_key (stream->stream_table, sel_name)))
410 return objc_write_use_common (stream, key);
411 else
413 int length;
414 hash_add (&stream->stream_table, (void*)key=(unsigned int)sel_name, (char*)sel_name);
415 if ((length = objc_write_register_common (stream, key)))
416 return __objc_write_selector (stream, selector);
417 return length;
424 ** Read operations
427 __inline__ int
428 objc_read_char (struct objc_typed_stream* stream, char* val)
430 unsigned char buf;
431 int len;
432 len = (*stream->read)(stream->physical, &buf, 1);
433 if (len != 0)
435 if ((buf & _B_CODE) == _B_SINT)
436 (*val) = (buf & _B_VALUE);
438 else if ((buf & _B_NUMBER) == 1)
440 len = (*stream->read)(stream->physical, val, 1);
441 if (buf&_B_SIGN)
442 (*val) = -1*(*val);
445 else
446 __objc_fatal("expected 8bit signed int, got %dbit int",
447 (int)(buf&_B_NUMBER)*8);
449 return len;
453 __inline__ int
454 objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val)
456 unsigned char buf;
457 int len;
458 if ((len = (*stream->read)(stream->physical, &buf, 1)))
460 if ((buf & _B_CODE) == _B_SINT)
461 (*val) = (buf & _B_VALUE);
463 else if ((buf & _B_NUMBER) == 1)
464 len = (*stream->read)(stream->physical, val, 1);
466 else
467 __objc_fatal("expected 8bit unsigned int, got %dbit int",
468 (int)(buf&_B_NUMBER)*8);
470 return len;
473 __inline__ int
474 objc_read_short (struct objc_typed_stream* stream, short* value)
476 unsigned char buf[sizeof(short)+1];
477 int len;
478 if ((len = (*stream->read)(stream->physical, buf, 1)))
480 if ((buf[0] & _B_CODE) == _B_SINT)
481 (*value) = (buf[0] & _B_VALUE);
483 else
485 int pos = 1;
486 int nbytes = buf[0] & _B_NUMBER;
487 if (nbytes > sizeof (short))
488 __objc_fatal("expected short, got bigger (%dbits)", nbytes*8);
489 len = (*stream->read)(stream->physical, buf+1, nbytes);
490 (*value) = 0;
491 while (pos <= nbytes)
492 (*value) = ((*value)*0x100) + buf[pos++];
493 if (buf[0] & _B_SIGN)
494 (*value) = -(*value);
497 return len;
500 __inline__ int
501 objc_read_unsigned_short (struct objc_typed_stream* stream,
502 unsigned short* value)
504 unsigned char buf[sizeof(unsigned short)+1];
505 int len;
506 if ((len = (*stream->read)(stream->physical, buf, 1)))
508 if ((buf[0] & _B_CODE) == _B_SINT)
509 (*value) = (buf[0] & _B_VALUE);
511 else
513 int pos = 1;
514 int nbytes = buf[0] & _B_NUMBER;
515 if (nbytes > sizeof (short))
516 __objc_fatal("expected short, got int or bigger");
517 len = (*stream->read)(stream->physical, buf+1, nbytes);
518 (*value) = 0;
519 while (pos <= nbytes)
520 (*value) = ((*value)*0x100) + buf[pos++];
523 return len;
527 __inline__ int
528 objc_read_int (struct objc_typed_stream* stream, int* value)
530 unsigned char buf[sizeof(int)+1];
531 int len;
532 if ((len = (*stream->read)(stream->physical, buf, 1)))
534 if ((buf[0] & _B_CODE) == _B_SINT)
535 (*value) = (buf[0] & _B_VALUE);
537 else
539 int pos = 1;
540 int nbytes = buf[0] & _B_NUMBER;
541 if (nbytes > sizeof (int))
542 __objc_fatal("expected int, got bigger");
543 len = (*stream->read)(stream->physical, buf+1, nbytes);
544 (*value) = 0;
545 while (pos <= nbytes)
546 (*value) = ((*value)*0x100) + buf[pos++];
547 if (buf[0] & _B_SIGN)
548 (*value) = -(*value);
551 return len;
554 __inline__ int
555 __objc_read_nbyte_uint (struct objc_typed_stream* stream,
556 unsigned int nbytes, unsigned int* val)
558 int len, pos = 0;
559 unsigned char buf[sizeof(unsigned int)+1];
561 if (nbytes > sizeof (int))
562 __objc_fatal("expected int, got bigger");
564 len = (*stream->read)(stream->physical, buf, nbytes);
565 (*val) = 0;
566 while (pos < nbytes)
567 (*val) = ((*val)*0x100) + buf[pos++];
568 return len;
572 __inline__ int
573 objc_read_unsigned_int (struct objc_typed_stream* stream,
574 unsigned int* value)
576 unsigned char buf[sizeof(unsigned int)+1];
577 int len;
578 if ((len = (*stream->read)(stream->physical, buf, 1)))
580 if ((buf[0] & _B_CODE) == _B_SINT)
581 (*value) = (buf[0] & _B_VALUE);
583 else
584 len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value);
587 return len;
590 __inline__ int
591 objc_read_string (struct objc_typed_stream* stream,
592 char** string)
594 unsigned char buf[sizeof(unsigned int)+1];
595 int len;
596 if ((len = (*stream->read)(stream->physical, buf, 1)))
598 unsigned int key = 0;
600 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
602 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
603 len = (*stream->read)(stream->physical, buf, 1);
606 switch (buf[0]&_B_CODE) {
607 case _B_SSTR:
609 int length = buf[0]&_B_VALUE;
610 (*string) = (char*)__objc_xmalloc(length+1);
611 if (key)
612 hash_add (&stream->stream_table, (void*)key, *string);
613 len = (*stream->read)(stream->physical, *string, length);
614 (*string)[length] = '\0';
616 break;
618 case _B_UCOMM:
620 char *tmp;
621 len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), &key);
622 tmp = hash_value_for_key (stream->stream_table, (void*)key);
623 *string = __objc_xmalloc (strlen (tmp) + 1);
624 strcpy (*string, tmp);
626 break;
628 case _B_NSTR:
630 unsigned int nbytes = buf[0]&_B_VALUE;
631 len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
632 if (len) {
633 (*string) = (char*)__objc_xmalloc(nbytes+1);
634 if (key)
635 hash_add (&stream->stream_table, (void*)key, *string);
636 len = (*stream->read)(stream->physical, *string, nbytes);
637 (*string)[nbytes] = '\0';
640 break;
642 default:
643 __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE));
647 return len;
652 objc_read_object (struct objc_typed_stream* stream, id* object)
654 unsigned char buf[sizeof (unsigned int)];
655 int len;
656 if ((len = (*stream->read)(stream->physical, buf, 1)))
658 SEL read_sel = sel_get_uid ("read:");
659 unsigned int key = 0;
661 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
663 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
664 len = (*stream->read)(stream->physical, buf, 1);
667 if (buf[0] == (_B_EXT | _BX_OBJECT))
669 Class* class;
671 /* get class */
672 len = objc_read_class (stream, &class);
674 /* create instance */
675 (*object) = class_create_instance(class);
677 /* register? */
678 if (key)
679 hash_add (&stream->object_table, (void*)key, *object);
681 /* send -read: */
682 if (__objc_responds_to (*object, read_sel))
683 (*get_imp(class, read_sel))(*object, read_sel, stream);
685 /* check null-byte */
686 len = (*stream->read)(stream->physical, buf, 1);
687 if (buf[0] != '\0')
688 __objc_fatal("expected null-byte, got opcode %c", buf[0]);
691 else if ((buf[0]&_B_CODE) == _B_UCOMM)
693 if (key)
694 __objc_fatal("cannot register use upcode...");
695 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
696 (*object) = hash_value_for_key (stream->object_table, (void*)key);
699 else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
701 struct objc_list* other;
702 len = objc_read_unsigned_int (stream, &key);
703 other = (struct objc_list*)hash_value_for_key (stream->object_refs, (void*)key);
704 hash_add (&stream->object_refs, (void*)key, (void*)list_cons(object, other));
707 else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
709 if (key)
710 __objc_fatal("cannot register root object...");
711 len = objc_read_object (stream, object);
712 __objc_finish_read_root_object (stream);
715 else
716 __objc_fatal("expected object, got opcode %c", buf[0]);
718 return len;
721 static int
722 objc_read_class (struct objc_typed_stream* stream, Class** class)
724 unsigned char buf[sizeof (unsigned int)];
725 int len;
726 if ((len = (*stream->read)(stream->physical, buf, 1)))
728 unsigned int key = 0;
730 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
732 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
733 len = (*stream->read)(stream->physical, buf, 1);
736 if (buf[0] == (_B_EXT | _BX_CLASS))
738 char* class_name;
739 int version;
741 /* get class */
742 len = objc_read_string (stream, &class_name);
743 (*class) = objc_get_class(class_name);
744 free (class_name);
746 /* register */
747 if (key)
748 hash_add (&stream->stream_table, (void*)key, *class);
750 objc_read_unsigned_int(stream, &version);
751 hash_add (&stream->class_table, (*class)->name, (void*)version);
754 else if ((buf[0]&_B_CODE) == _B_UCOMM)
756 if (key)
757 __objc_fatal("cannot register use upcode...");
758 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
759 (*class) = hash_value_for_key (stream->stream_table, (void*)key);
760 if (!*class)
761 __objc_fatal("cannot find class for key %x", key);
764 else
765 __objc_fatal("expected class, got opcode %c", buf[0]);
767 return len;
771 objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
773 unsigned char buf[sizeof (unsigned int)];
774 int len;
775 if ((len = (*stream->read)(stream->physical, buf, 1)))
777 unsigned int key = 0;
779 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
781 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
782 len = (*stream->read)(stream->physical, buf, 1);
785 if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
787 char* selector_name;
789 /* get selector */
790 len = objc_read_string (stream, &selector_name);
791 (*selector) = sel_get_uid(selector_name);
792 free (selector_name);
794 /* register */
795 if (key)
796 hash_add (&stream->stream_table, (void*)key, *selector);
799 else if ((buf[0]&_B_CODE) == _B_UCOMM)
801 if (key)
802 __objc_fatal("cannot register use upcode...");
803 len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
804 (*selector) = hash_value_for_key (stream->stream_table, (void*)key);
807 else
808 __objc_fatal("expected selector, got opcode %c", buf[0]);
810 return len;
813 static int
814 objc_sizeof_type(const char* type)
816 switch(*type) {
817 case _C_ID: return sizeof(id);
818 break;
820 case _C_CLASS:
821 return sizeof(Class*);
822 break;
824 case _C_SEL:
825 return sizeof(SEL);
826 break;
828 case _C_CHR:
829 return sizeof(char);
830 break;
832 case _C_UCHR:
833 return sizeof(unsigned char);
834 break;
836 case _C_SHT:
837 return sizeof(short);
838 break;
840 case _C_USHT:
841 return sizeof(unsigned short);
842 break;
844 case _C_INT:
845 case _C_LNG:
846 return sizeof(int);
847 break;
849 case _C_UINT:
850 case _C_ULNG:
851 return sizeof(unsigned int);
852 break;
854 case _C_ATOM:
855 case _C_CHARPTR:
856 return sizeof(char*);
857 break;
859 default:
860 fprintf(stderr, "objc_sizeof_type: cannot parse typespec: %s\n", type);
861 abort();
866 static const char*
867 __objc_skip_type (const char* type)
869 switch (*type) {
870 case _C_ID:
871 case _C_CLASS:
872 case _C_SEL:
873 case _C_CHR:
874 case _C_UCHR:
875 case _C_CHARPTR:
876 case _C_ATOM:
877 case _C_SHT:
878 case _C_USHT:
879 case _C_INT:
880 case _C_UINT:
881 case _C_LNG:
882 case _C_ULNG:
883 case _C_FLT:
884 case _C_DBL:
885 return ++type;
886 break;
888 case _C_ARY_B:
889 while(isdigit(*++type));
890 type = __objc_skip_type(type);
891 if (*type == _C_ARY_E)
892 return ++type;
893 else
894 __objc_fatal("cannot parse typespec: %s", type);
895 break;
897 default:
898 fprintf(stderr, "__objc_skip_type: cannot parse typespec: %s\n", type);
899 abort();
904 ** USER LEVEL FUNCTIONS
908 ** Write one object, encoded in TYPE and pointed to by DATA to the
909 ** typed stream STREAM.
913 objc_write_type(TypedStream* stream, const char* type, const void* data)
915 switch(*type) {
916 case _C_ID:
917 return objc_write_object (stream, *(id*)data);
918 break;
920 case _C_CLASS:
921 return objc_write_class (stream, *(Class**)data);
922 break;
924 case _C_SEL:
925 return objc_write_selector (stream, *(SEL*)data);
926 break;
928 case _C_CHR:
929 return objc_write_char(stream, *(char*)data);
930 break;
932 case _C_UCHR:
933 return objc_write_unsigned_char(stream, *(unsigned char*)data);
934 break;
936 case _C_SHT:
937 return objc_write_short(stream, *(short*)data);
938 break;
940 case _C_USHT:
941 return objc_write_unsigned_short(stream, *(unsigned short*)data);
942 break;
944 case _C_INT:
945 case _C_LNG:
946 return objc_write_int(stream, *(int*)data);
947 break;
949 case _C_UINT:
950 case _C_ULNG:
951 return objc_write_unsigned_int(stream, *(unsigned int*)data);
952 break;
954 case _C_CHARPTR:
955 return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
956 break;
958 case _C_ATOM:
959 return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data));
960 break;
962 case _C_ARY_B:
964 int len = atoi(type+1);
965 while (isdigit(*++type));
966 return objc_write_array (stream, type, len, data);
968 break;
970 default:
971 fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
972 abort();
977 ** Read one object, encoded in TYPE and pointed to by DATA to the
978 ** typed stream STREAM. DATA specifies the address of the types to
979 ** read. Expected type is checked against the type actually present
980 ** on the stream.
984 objc_read_type(TypedStream* stream, const char* type, void* data)
986 char c;
987 switch(c = *type) {
988 case _C_ID:
989 return objc_read_object (stream, (id*)data);
990 break;
992 case _C_CLASS:
993 return objc_read_class (stream, (Class**)data);
994 break;
996 case _C_SEL:
997 return objc_read_selector (stream, (SEL*)data);
998 break;
1000 case _C_CHR:
1001 return objc_read_char (stream, (char*)data);
1002 break;
1004 case _C_UCHR:
1005 return objc_read_unsigned_char (stream, (unsigned char*)data);
1006 break;
1008 case _C_SHT:
1009 return objc_read_short (stream, (short*)data);
1010 break;
1012 case _C_USHT:
1013 return objc_read_unsigned_short (stream, (unsigned short*)data);
1014 break;
1016 case _C_INT:
1017 case _C_LNG:
1018 return objc_read_int (stream, (int*)data);
1019 break;
1021 case _C_UINT:
1022 case _C_ULNG:
1023 return objc_read_unsigned_int (stream, (unsigned int*)data);
1024 break;
1026 case _C_CHARPTR:
1027 case _C_ATOM:
1028 return objc_read_string (stream, (char**)data);
1029 break;
1031 case _C_ARY_B:
1033 int len = atoi(type+1);
1034 while (isdigit(*++type));
1035 return objc_read_array (stream, type, len, data);
1037 break;
1039 default:
1040 fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
1041 abort();
1046 ** Write the object specified by the template TYPE to STREAM. Last
1047 ** arguments specify addresses of values to be written. It might
1048 ** seem surprising to specify values by address, but this is extremely
1049 ** convenient for copy-paste with objc_read_types calls. A more
1050 ** down-to-the-earth cause for this passing of addresses is that values
1051 ** of arbitrary size is not well supported in ANSI C for functions with
1052 ** variable number of arguments.
1055 int
1056 objc_write_types (TypedStream* stream, const char* type, ...)
1058 va_list args;
1059 const char *c;
1060 int res = 0;
1062 va_start(args, type);
1064 for (c = type; *c; c = __objc_skip_type (c))
1066 switch(*c) {
1067 case _C_ID:
1068 res = objc_write_object (stream, *va_arg (args, id*));
1069 break;
1071 case _C_CLASS:
1072 res = objc_write_class (stream, *va_arg(args, Class**));
1073 break;
1075 case _C_SEL:
1076 res = objc_write_selector (stream, *va_arg(args, SEL*));
1077 break;
1079 case _C_CHR:
1080 res = objc_write_char (stream, *va_arg (args, char*));
1081 break;
1083 case _C_UCHR:
1084 res = objc_write_unsigned_char (stream,
1085 *va_arg (args, unsigned char*));
1086 break;
1088 case _C_SHT:
1089 res = objc_write_short (stream, *va_arg(args, short*));
1090 break;
1092 case _C_USHT:
1093 res = objc_write_unsigned_short (stream,
1094 *va_arg(args, unsigned short*));
1095 break;
1097 case _C_INT:
1098 case _C_LNG:
1099 res = objc_write_int(stream, *va_arg(args, int*));
1100 break;
1102 case _C_UINT:
1103 case _C_ULNG:
1104 res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
1105 break;
1107 case _C_CHARPTR:
1109 char** str = va_arg(args, char**);
1110 res = objc_write_string (stream, *str, strlen(*str));
1112 break;
1114 case _C_ATOM:
1116 char** str = va_arg(args, char**);
1117 res = objc_write_string_atomic (stream, *str, strlen(*str));
1119 break;
1121 case _C_ARY_B:
1123 int len = atoi(c+1);
1124 const char* t = c;
1125 while (isdigit(*++t));
1126 res = objc_write_array (stream, t, len, va_arg(args, void*));
1127 t = __objc_skip_type (t);
1128 if (*t != _C_ARY_E)
1129 __objc_fatal("expected `]', got: %s", t);
1131 break;
1133 default:
1134 fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type);
1135 abort();
1138 va_end(args);
1139 return res;
1144 ** Last arguments specify addresses of values to be read. Expected
1145 ** type is checked against the type actually present on the stream.
1148 int
1149 objc_read_types(TypedStream* stream, const char* type, ...)
1151 va_list args;
1152 const char *c;
1153 int res = 0;
1155 va_start(args, type);
1157 for (c = type; *c; c = __objc_skip_type(c))
1159 switch(*c) {
1160 case _C_ID:
1161 res = objc_read_object(stream, va_arg(args, id*));
1162 break;
1164 case _C_CLASS:
1165 res = objc_read_class(stream, va_arg(args, Class**));
1166 break;
1168 case _C_SEL:
1169 res = objc_read_selector(stream, va_arg(args, SEL*));
1170 break;
1172 case _C_CHR:
1173 res = objc_read_char(stream, va_arg(args, char*));
1174 break;
1176 case _C_UCHR:
1177 res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
1178 break;
1180 case _C_SHT:
1181 res = objc_read_short(stream, va_arg(args, short*));
1182 break;
1184 case _C_USHT:
1185 res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
1186 break;
1188 case _C_INT:
1189 case _C_LNG:
1190 res = objc_read_int(stream, va_arg(args, int*));
1191 break;
1193 case _C_UINT:
1194 case _C_ULNG:
1195 res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
1196 break;
1198 case _C_CHARPTR:
1199 case _C_ATOM:
1201 char** str = va_arg(args, char**);
1202 res = objc_read_string (stream, str);
1204 break;
1206 case _C_ARY_B:
1208 int len = atoi(c+1);
1209 const char* t = c;
1210 while (isdigit(*++t));
1211 res = objc_read_array (stream, t, len, va_arg(args, void*));
1212 t = __objc_skip_type (t);
1213 if (*t != _C_ARY_E)
1214 __objc_fatal("expected `]', got: %s", t);
1216 break;
1218 default:
1219 fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
1220 abort();
1223 va_end(args);
1224 return res;
1228 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1229 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1233 objc_write_array (TypedStream* stream, const char* type,
1234 int count, const void* data)
1236 int off = objc_sizeof_type(type);
1237 const char* where = data;
1239 while (count-- > 0)
1241 objc_write_type(stream, type, where);
1242 where += off;
1244 return 1;
1248 ** Read an array of COUNT elements of TYPE into the memory address
1249 ** DATA. The memory pointed to by data is supposed to be allocated
1250 ** by the callee. This is equivalent of
1251 ** objc_read_type (stream, "[N<type>]", data)
1255 objc_read_array (TypedStream* stream, const char* type,
1256 int count, void* data)
1258 int off = objc_sizeof_type(type);
1259 char* where = (char*)data;
1261 while (count-- > 0)
1263 objc_read_type(stream, type, where);
1264 where += off;
1266 return 1;
1269 static int
1270 __objc_fread(FILE* file, char* data, int len)
1272 return fread(data, len, 1, file);
1275 static int
1276 __objc_fwrite(FILE* file, char* data, int len)
1278 return fwrite(data, len, 1, file);
1281 static int
1282 __objc_feof(FILE* file)
1284 return feof(file);
1287 static int
1288 __objc_no_write(FILE* file, char* data, int len)
1290 __objc_fatal ("TypedStream not open for writing");
1293 static int
1294 __objc_no_read(FILE* file, char* data, int len)
1296 __objc_fatal ("TypedStream not open for reading");
1299 static int
1300 __objc_read_typed_stream_signature (TypedStream* stream)
1302 char buffer[80];
1303 int pos = 0;
1305 (*stream->read)(stream->physical, buffer+pos, 1);
1306 while (buffer[pos++] != '\0');
1307 sscanf (buffer, "GNU TypedStream %d", &stream->version);
1308 if (stream->version != OBJC_TYPED_STREAM_VERSION)
1309 __objc_fatal ("cannot handle TypedStream version %d", stream->version);
1310 return 1;
1313 static int
1314 __objc_write_typed_stream_signature (TypedStream* stream)
1316 char buffer[80];
1317 sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
1318 stream->version = OBJC_TYPED_STREAM_VERSION;
1319 (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
1320 return 1;
1323 static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
1325 hash_delete (stream->object_table);
1326 stream->object_table = hash_new(64,
1327 (hash_func_type)hash_ptr,
1328 (compare_func_type)compare_ptrs);
1331 static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
1333 node_ptr node;
1334 SEL awake_sel = sel_get_uid ("awake");
1336 /* resolve object forward references */
1337 for (node = hash_next (stream->object_refs, NULL); node;
1338 node = hash_next (stream->object_refs, node))
1340 struct objc_list* reflist = node->value;
1341 const void* key = node->key;
1342 id object = hash_value_for_key (stream->object_table, key);
1343 while(reflist)
1345 *((id*)reflist->head) = object;
1346 reflist = reflist->tail;
1348 list_free (node->value);
1351 /* empty object reference table */
1352 hash_delete (stream->object_refs);
1353 stream->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1354 (compare_func_type)compare_ptrs);
1356 /* call -awake for all objects read */
1357 if (awake_sel)
1359 for (node = hash_next (stream->object_table, NULL); node;
1360 node = hash_next (stream->object_table, node))
1362 id object = node->value;
1363 if (__objc_responds_to (object, awake_sel))
1364 (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
1368 /* empty object table */
1369 hash_delete (stream->object_table);
1370 stream->object_table = hash_new(64,
1371 (hash_func_type)hash_ptr,
1372 (compare_func_type)compare_ptrs);
1376 ** Open the stream PHYSICAL in MODE
1379 TypedStream*
1380 objc_open_typed_stream (FILE* physical, int mode)
1382 int fflush(FILE*);
1384 TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
1386 s->mode = mode;
1387 s->physical = physical;
1388 s->stream_table = hash_new(64,
1389 (hash_func_type)hash_ptr,
1390 (compare_func_type)compare_ptrs);
1391 s->object_table = hash_new(64,
1392 (hash_func_type)hash_ptr,
1393 (compare_func_type)compare_ptrs);
1394 s->eof = (objc_typed_eof_func)__objc_feof;
1395 s->flush = (objc_typed_flush_func)fflush;
1396 s->writing_root_p = 0;
1397 if (mode == OBJC_READONLY)
1399 s->class_table = hash_new(8, (hash_func_type)hash_string,
1400 (compare_func_type)compare_strings);
1401 s->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1402 (compare_func_type)compare_ptrs);
1403 s->read = (objc_typed_read_func)__objc_fread;
1404 s->write = (objc_typed_write_func)__objc_no_write;
1405 __objc_read_typed_stream_signature (s);
1407 else if (mode == OBJC_WRITEONLY)
1409 s->class_table = 0;
1410 s->object_refs = 0;
1411 s->read = (objc_typed_read_func)__objc_no_read;
1412 s->write = (objc_typed_write_func)__objc_fwrite;
1413 __objc_write_typed_stream_signature (s);
1415 else
1417 objc_close_typed_stream (s);
1418 return NULL;
1420 s->type = OBJC_FILE_STREAM;
1421 return s;
1425 ** Open the file named by FILE_NAME in MODE
1428 TypedStream*
1429 objc_open_typed_stream_for_file (const char* file_name, int mode)
1431 FILE* file = NULL;
1432 TypedStream* s;
1434 if (mode == OBJC_READONLY)
1435 file = fopen (file_name, "r");
1436 else
1437 file = fopen (file_name, "w");
1439 if (file)
1441 s = objc_open_typed_stream (file, mode);
1442 if (s)
1443 s->type |= OBJC_MANAGED_STREAM;
1444 return s;
1446 else
1447 return NULL;
1451 ** Close STREAM freeing the structure it self. If it was opened with
1452 ** objc_open_typed_stream_for_file, the file will also be closed.
1455 void
1456 objc_close_typed_stream (TypedStream* stream)
1458 if (stream->mode == OBJC_READONLY)
1460 __objc_finish_read_root_object (stream); /* Just in case... */
1461 hash_delete (stream->class_table);
1462 hash_delete (stream->object_refs);
1465 hash_delete (stream->stream_table);
1466 hash_delete (stream->object_table);
1468 if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1469 fclose ((FILE*)stream->physical);
1471 free (stream);
1474 BOOL
1475 objc_end_of_typed_stream (TypedStream* stream)
1477 return (*stream->eof)(stream->physical);
1480 void
1481 objc_flush_typed_stream (TypedStream* stream)
1483 (*stream->flush)(stream->physical);
1486 int
1487 objc_get_stream_class_version (TypedStream* stream, Class* class)
1489 if (stream->class_table)
1490 return (int) hash_value_for_key (stream->class_table, class->name);
1491 else
1492 return class_get_version (class);
1495 #endif /* __alpha__ */