|
|
1.1 root 1: /* GNU Objective C Runtime archiving
2: Copyright (C) 1993 Free Software Foundation, Inc.
3:
4: Author: Kresten Krab Thorup
5:
6: This file is part of GNU CC.
7:
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.
11:
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.
16:
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. */
20:
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. */
26:
27: /*
28: ** Note: This version assumes that int and longs are both 32bit.
29: */
30:
31: #ifndef __alpha__
32:
33: #include "runtime.h"
34: #include "typedstream.h"
35:
36: #define __objc_fatal(format, args...) \
1.1.1.2 ! root 37: { fprintf(stderr, "archiving: "); \
1.1 root 38: fprintf(stderr, format, ## args); \
39: fprintf(stderr, "\n"); abort(); }
40:
41: /* Declare some functions... */
42:
43: static int
44: objc_read_class (struct objc_typed_stream* stream, Class** class);
45:
46: static int
47: objc_sizeof_type(const char* type);
48:
49: static int
50: objc_write_use_common (struct objc_typed_stream* stream, unsigned int key);
51:
52: static int
53: objc_write_register_common (struct objc_typed_stream* stream,
54: unsigned int key);
55:
56: static int
57: objc_write_class (struct objc_typed_stream* stream,
58: struct objc_class* class);
59:
60: static const char*
61: __objc_skip_type (const char* type);
62:
63: static void __objc_finish_write_root_object(struct objc_typed_stream*);
64: static void __objc_finish_read_root_object(struct objc_typed_stream*);
65:
66: static __inline__ int
67: __objc_code_unsigned_char (unsigned char* buf, unsigned char val)
68: {
69: if ((val&_B_VALUE) == val)
70: {
71: buf[0] = val|_B_SINT;
72: return 1;
73: }
74: else
75: {
76: buf[0] = _B_NINT|0x01;
77: buf[1] = val;
78: return 2;
79: }
80: }
81:
82: int
83: objc_write_unsigned_char (struct objc_typed_stream* stream,
84: unsigned char value)
85: {
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);
89: }
90:
91: static __inline__ int
92: __objc_code_char (unsigned char* buf, char val)
93: {
94: if (val >= 0)
95: return __objc_code_unsigned_char (buf, val);
96: else
97: {
98: buf[0] = _B_NINT|_B_SIGN|0x01;
99: buf[1] = -val;
100: return 2;
101: }
102: }
103:
104: int
105: objc_write_char (struct objc_typed_stream* stream, char value)
106: {
107: unsigned char buf[sizeof (char)+1];
108: int len = __objc_code_char (buf, value);
109: return (*stream->write)(stream->physical, buf, len);
110: }
111:
112: static __inline__ int
113: __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
114: {
115: if (val <= 0xffU)
116: return __objc_code_unsigned_char (buf, val);
117:
118: else
119: {
120: buf[0] = _B_NINT|0x02;
121: buf[1] = val/0x100;
122: buf[2] = val%0x100;
123: return 3;
124: }
125: }
126:
127: int
128: objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short value)
129: {
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);
133: }
134:
135: static __inline__ int
136: __objc_code_short (unsigned char* buf, short val)
137: {
138: if (val > 0)
139: return __objc_code_unsigned_short (buf, val);
140:
141: if (val > -0x7f) /* val > -128 */
142: return __objc_code_char (buf, val);
143:
144: else
145: {
146: int len = __objc_code_unsigned_short (buf, -val);
147: buf[0] |= _B_SIGN;
148: return len;
149: }
150: }
151:
152: int
153: objc_write_short (struct objc_typed_stream* stream, short value)
154: {
155: unsigned char buf[sizeof (short)+1];
156: int len = __objc_code_short (buf, value);
157: return (*stream->write)(stream->physical, buf, len);
158: }
159:
160:
161: static __inline__ int
162: __objc_code_unsigned_int (unsigned char* buf, unsigned int val)
163: {
164: if (val < 0x10000)
165: return __objc_code_unsigned_short (buf, val%0x10000);
166:
167: else if (val < 0x1000000)
168: {
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;
174: }
175:
176: else
177: {
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;
184: }
185: }
186:
187: int
188: objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value)
189: {
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);
193: }
194:
195: static __inline__ int
196: __objc_code_int (unsigned char* buf, int val)
197: {
198: if (val >= 0)
199: return __objc_code_unsigned_int (buf, val);
200:
201: if (val > -0x7f)
202: return __objc_code_char (buf, val);
203:
204: else
205: {
206: int len = __objc_code_unsigned_int (buf, -val);
207: buf[0] |= _B_SIGN;
208: return len;
209: }
210: }
211:
212: int
213: objc_write_int (struct objc_typed_stream* stream, int value)
214: {
215: unsigned char buf[sizeof(int)+1];
216: int len = __objc_code_int (buf, value);
217: return (*stream->write)(stream->physical, buf, len);
218: }
219:
220: int
221: objc_write_string (struct objc_typed_stream* stream,
222: const unsigned char* string, unsigned int nbytes)
223: {
224: unsigned char buf[sizeof(unsigned int)+1];
225: int len = __objc_code_unsigned_int (buf, nbytes);
226:
227: if ((buf[0]&_B_CODE) == _B_SINT)
228: buf[0] = (buf[0]&_B_VALUE)|_B_SSTR;
229:
230: else /* _B_NINT */
231: buf[0] = (buf[0]&_B_VALUE)|_B_NSTR;
232:
233: if ((*stream->write)(stream->physical, buf, len) != 0)
234: return (*stream->write)(stream->physical, string, nbytes);
235: else
236: return 0;
237: }
238:
239: int
240: objc_write_string_atomic (struct objc_typed_stream* stream,
241: unsigned char* string, unsigned int nbytes)
242: {
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
247: {
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;
253: }
254: }
255:
256: static int
257: objc_write_register_common (struct objc_typed_stream* stream, unsigned int key)
258: {
259: unsigned char buf[sizeof (unsigned int)+2];
260: int len = __objc_code_unsigned_int (buf+1, key);
261: if (len == 1)
262: {
263: buf[0] = _B_RCOMM|0x01;
264: buf[1] &= _B_VALUE;
265: return (*stream->write)(stream->physical, buf, len+1);
266: }
267: else
268: {
269: buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM;
270: return (*stream->write)(stream->physical, buf+1, len);
271: }
272: }
273:
274: static int
275: objc_write_use_common (struct objc_typed_stream* stream, unsigned int key)
276: {
277: unsigned char buf[sizeof (unsigned int)+2];
278: int len = __objc_code_unsigned_int (buf+1, key);
279: if (len == 1)
280: {
281: buf[0] = _B_UCOMM|0x01;
282: buf[1] &= _B_VALUE;
283: return (*stream->write)(stream->physical, buf, 2);
284: }
285: else
286: {
287: buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM;
288: return (*stream->write)(stream->physical, buf+1, len);
289: }
290: }
291:
292: static __inline__ int
293: __objc_write_extension (struct objc_typed_stream* stream, unsigned char code)
294: {
295: if (code <= _B_VALUE)
296: {
297: unsigned char buf = code|_B_EXT;
298: return (*stream->write)(stream->physical, &buf, 1);
299: }
300: else
301: abort();
302: }
303:
304: __inline__ int
305: __objc_write_object (struct objc_typed_stream* stream, id object)
306: {
307: unsigned char buf = '\0';
308: SEL write_sel = sel_get_uid ("write:");
309: if (object)
310: {
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);
315: }
316: else
317: return objc_write_use_common(stream, 0);
318: }
319:
320: int
321: objc_write_object_reference (struct objc_typed_stream* stream, id object)
322: {
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);
326:
327: __objc_write_extension (stream, _BX_OBJREF);
328: return objc_write_unsigned_int (stream, (unsigned int)object);
329: }
330:
331: int
332: objc_write_root_object (struct objc_typed_stream* stream, id object)
333: {
334: int len;
335: if (stream->writing_root_p)
336: __objc_fatal ("objc_write_root_object called recursively")
337: else
338: {
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;
344: }
345: return len;
346: }
347:
348: int
349: objc_write_object (struct objc_typed_stream* stream, id object)
350: {
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);
354:
355: else if (object == nil)
356: return objc_write_use_common(stream, 0);
357:
358: else
359: {
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;
365: }
366: }
367:
368: __inline__ int
369: __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class)
370: {
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));
375: }
376:
377:
378: static int
379: objc_write_class (struct objc_typed_stream* stream,
380: struct objc_class* class)
381: {
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
386: {
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;
392: }
393: }
394:
395:
396: __inline__ int
397: __objc_write_selector (struct objc_typed_stream* stream, SEL selector)
398: {
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));
402: }
403:
404: int
405: objc_write_selector (struct objc_typed_stream* stream, SEL selector)
406: {
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
412: {
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;
418: }
419: }
420:
421:
422:
423: /*
424: ** Read operations
425: */
426:
427: __inline__ int
428: objc_read_char (struct objc_typed_stream* stream, char* val)
429: {
430: unsigned char buf;
431: int len;
432: len = (*stream->read)(stream->physical, &buf, 1);
433: if (len != 0)
434: {
435: if ((buf & _B_CODE) == _B_SINT)
436: (*val) = (buf & _B_VALUE);
437:
438: else if ((buf & _B_NUMBER) == 1)
439: {
440: len = (*stream->read)(stream->physical, val, 1);
441: if (buf&_B_SIGN)
442: (*val) = -1*(*val);
443: }
444:
445: else
446: __objc_fatal("expected 8bit signed int, got %dbit int",
447: (int)(buf&_B_NUMBER)*8);
448: }
449: return len;
450: }
451:
452:
453: __inline__ int
454: objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val)
455: {
456: unsigned char buf;
457: int len;
458: if ((len = (*stream->read)(stream->physical, &buf, 1)))
459: {
460: if ((buf & _B_CODE) == _B_SINT)
461: (*val) = (buf & _B_VALUE);
462:
463: else if ((buf & _B_NUMBER) == 1)
464: len = (*stream->read)(stream->physical, val, 1);
465:
466: else
467: __objc_fatal("expected 8bit unsigned int, got %dbit int",
468: (int)(buf&_B_NUMBER)*8);
469: }
470: return len;
471: }
472:
473: __inline__ int
474: objc_read_short (struct objc_typed_stream* stream, short* value)
475: {
476: unsigned char buf[sizeof(short)+1];
477: int len;
478: if ((len = (*stream->read)(stream->physical, buf, 1)))
479: {
480: if ((buf[0] & _B_CODE) == _B_SINT)
481: (*value) = (buf[0] & _B_VALUE);
482:
483: else
484: {
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);
495: }
496: }
497: return len;
498: }
499:
500: __inline__ int
501: objc_read_unsigned_short (struct objc_typed_stream* stream,
502: unsigned short* value)
503: {
504: unsigned char buf[sizeof(unsigned short)+1];
505: int len;
506: if ((len = (*stream->read)(stream->physical, buf, 1)))
507: {
508: if ((buf[0] & _B_CODE) == _B_SINT)
509: (*value) = (buf[0] & _B_VALUE);
510:
511: else
512: {
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++];
521: }
522: }
523: return len;
524: }
525:
526:
527: __inline__ int
528: objc_read_int (struct objc_typed_stream* stream, int* value)
529: {
530: unsigned char buf[sizeof(int)+1];
531: int len;
532: if ((len = (*stream->read)(stream->physical, buf, 1)))
533: {
534: if ((buf[0] & _B_CODE) == _B_SINT)
535: (*value) = (buf[0] & _B_VALUE);
536:
537: else
538: {
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);
549: }
550: }
551: return len;
552: }
553:
554: __inline__ int
555: __objc_read_nbyte_uint (struct objc_typed_stream* stream,
556: unsigned int nbytes, unsigned int* val)
557: {
558: int len, pos = 0;
559: unsigned char buf[sizeof(unsigned int)+1];
560:
561: if (nbytes > sizeof (int))
562: __objc_fatal("expected int, got bigger");
563:
564: len = (*stream->read)(stream->physical, buf, nbytes);
565: (*val) = 0;
566: while (pos < nbytes)
567: (*val) = ((*val)*0x100) + buf[pos++];
568: return len;
569: }
570:
571:
572: __inline__ int
573: objc_read_unsigned_int (struct objc_typed_stream* stream,
574: unsigned int* value)
575: {
576: unsigned char buf[sizeof(unsigned int)+1];
577: int len;
578: if ((len = (*stream->read)(stream->physical, buf, 1)))
579: {
580: if ((buf[0] & _B_CODE) == _B_SINT)
581: (*value) = (buf[0] & _B_VALUE);
582:
583: else
584: len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value);
585:
586: }
587: return len;
588: }
589:
590: __inline__ int
591: objc_read_string (struct objc_typed_stream* stream,
592: char** string)
593: {
594: unsigned char buf[sizeof(unsigned int)+1];
595: int len;
596: if ((len = (*stream->read)(stream->physical, buf, 1)))
597: {
598: unsigned int key = 0;
599:
600: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
601: {
602: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
603: len = (*stream->read)(stream->physical, buf, 1);
604: }
605:
606: switch (buf[0]&_B_CODE) {
607: case _B_SSTR:
608: {
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';
615: }
616: break;
617:
618: case _B_UCOMM:
619: {
1.1.1.2 ! root 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);
1.1 root 625: }
626: break;
627:
628: case _B_NSTR:
629: {
630: unsigned int nbytes = buf[0]&_B_VALUE;
631: len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
632: if (len) {
1.1.1.2 ! root 633: (*string) = (char*)__objc_xmalloc(nbytes+1);
1.1 root 634: if (key)
635: hash_add (&stream->stream_table, (void*)key, *string);
1.1.1.2 ! root 636: len = (*stream->read)(stream->physical, *string, nbytes);
1.1 root 637: (*string)[nbytes] = '\0';
638: }
639: }
640: break;
641:
642: default:
643: __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE));
644: }
645: }
646:
647: return len;
648: }
649:
650:
651: int
652: objc_read_object (struct objc_typed_stream* stream, id* object)
653: {
654: unsigned char buf[sizeof (unsigned int)];
655: int len;
656: if ((len = (*stream->read)(stream->physical, buf, 1)))
657: {
658: SEL read_sel = sel_get_uid ("read:");
659: unsigned int key = 0;
660:
661: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
662: {
663: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
664: len = (*stream->read)(stream->physical, buf, 1);
665: }
666:
667: if (buf[0] == (_B_EXT | _BX_OBJECT))
668: {
669: Class* class;
670:
671: /* get class */
672: len = objc_read_class (stream, &class);
673:
674: /* create instance */
675: (*object) = class_create_instance(class);
676:
677: /* register? */
678: if (key)
679: hash_add (&stream->object_table, (void*)key, *object);
680:
681: /* send -read: */
682: if (__objc_responds_to (*object, read_sel))
683: (*get_imp(class, read_sel))(*object, read_sel, stream);
684:
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]);
689: }
690:
691: else if ((buf[0]&_B_CODE) == _B_UCOMM)
692: {
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);
697: }
698:
699: else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
700: {
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));
705: }
706:
707: else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
708: {
709: if (key)
710: __objc_fatal("cannot register root object...");
711: len = objc_read_object (stream, object);
712: __objc_finish_read_root_object (stream);
713: }
714:
715: else
716: __objc_fatal("expected object, got opcode %c", buf[0]);
717: }
718: return len;
719: }
720:
721: static int
722: objc_read_class (struct objc_typed_stream* stream, Class** class)
723: {
724: unsigned char buf[sizeof (unsigned int)];
725: int len;
726: if ((len = (*stream->read)(stream->physical, buf, 1)))
727: {
728: unsigned int key = 0;
729:
730: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
731: {
732: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
733: len = (*stream->read)(stream->physical, buf, 1);
734: }
735:
736: if (buf[0] == (_B_EXT | _BX_CLASS))
737: {
738: char* class_name;
739: int version;
740:
741: /* get class */
742: len = objc_read_string (stream, &class_name);
743: (*class) = objc_get_class(class_name);
744: free (class_name);
745:
746: /* register */
747: if (key)
748: hash_add (&stream->stream_table, (void*)key, *class);
749:
750: objc_read_unsigned_int(stream, &version);
751: hash_add (&stream->class_table, (*class)->name, (void*)version);
752: }
753:
754: else if ((buf[0]&_B_CODE) == _B_UCOMM)
755: {
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);
762: }
763:
764: else
765: __objc_fatal("expected class, got opcode %c", buf[0]);
766: }
767: return len;
768: }
769:
770: int
771: objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
772: {
773: unsigned char buf[sizeof (unsigned int)];
774: int len;
775: if ((len = (*stream->read)(stream->physical, buf, 1)))
776: {
777: unsigned int key = 0;
778:
779: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
780: {
781: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
782: len = (*stream->read)(stream->physical, buf, 1);
783: }
784:
785: if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
786: {
787: char* selector_name;
788:
789: /* get selector */
790: len = objc_read_string (stream, &selector_name);
791: (*selector) = sel_get_uid(selector_name);
792: free (selector_name);
793:
794: /* register */
795: if (key)
796: hash_add (&stream->stream_table, (void*)key, *selector);
797: }
798:
799: else if ((buf[0]&_B_CODE) == _B_UCOMM)
800: {
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);
805: }
806:
807: else
808: __objc_fatal("expected selector, got opcode %c", buf[0]);
809: }
810: return len;
811: }
812:
813: static int
814: objc_sizeof_type(const char* type)
815: {
816: switch(*type) {
817: case _C_ID: return sizeof(id);
818: break;
819:
820: case _C_CLASS:
821: return sizeof(Class*);
822: break;
823:
824: case _C_SEL:
825: return sizeof(SEL);
826: break;
827:
828: case _C_CHR:
829: return sizeof(char);
830: break;
831:
832: case _C_UCHR:
833: return sizeof(unsigned char);
834: break;
835:
836: case _C_SHT:
837: return sizeof(short);
838: break;
839:
840: case _C_USHT:
841: return sizeof(unsigned short);
842: break;
843:
844: case _C_INT:
845: case _C_LNG:
846: return sizeof(int);
847: break;
848:
849: case _C_UINT:
850: case _C_ULNG:
851: return sizeof(unsigned int);
852: break;
853:
854: case _C_ATOM:
855: case _C_CHARPTR:
856: return sizeof(char*);
857: break;
858:
859: default:
1.1.1.2 ! root 860: fprintf(stderr, "objc_sizeof_type: cannot parse typespec: %s\n", type);
1.1 root 861: abort();
862: }
863: }
864:
865:
866: static const char*
867: __objc_skip_type (const char* type)
868: {
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;
887:
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;
896:
897: default:
1.1.1.2 ! root 898: fprintf(stderr, "__objc_skip_type: cannot parse typespec: %s\n", type);
1.1 root 899: abort();
900: }
901: }
902:
903: /*
904: ** USER LEVEL FUNCTIONS
905: */
906:
907: /*
908: ** Write one object, encoded in TYPE and pointed to by DATA to the
909: ** typed stream STREAM.
910: */
911:
912: int
913: objc_write_type(TypedStream* stream, const char* type, const void* data)
914: {
915: switch(*type) {
916: case _C_ID:
917: return objc_write_object (stream, *(id*)data);
918: break;
919:
920: case _C_CLASS:
921: return objc_write_class (stream, *(Class**)data);
922: break;
923:
924: case _C_SEL:
925: return objc_write_selector (stream, *(SEL*)data);
926: break;
927:
928: case _C_CHR:
929: return objc_write_char(stream, *(char*)data);
930: break;
931:
932: case _C_UCHR:
933: return objc_write_unsigned_char(stream, *(unsigned char*)data);
934: break;
935:
936: case _C_SHT:
937: return objc_write_short(stream, *(short*)data);
938: break;
939:
940: case _C_USHT:
941: return objc_write_unsigned_short(stream, *(unsigned short*)data);
942: break;
943:
944: case _C_INT:
945: case _C_LNG:
946: return objc_write_int(stream, *(int*)data);
947: break;
948:
949: case _C_UINT:
950: case _C_ULNG:
951: return objc_write_unsigned_int(stream, *(unsigned int*)data);
952: break;
953:
954: case _C_CHARPTR:
1.1.1.2 ! root 955: return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
1.1 root 956: break;
957:
958: case _C_ATOM:
1.1.1.2 ! root 959: return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data));
1.1 root 960: break;
961:
962: case _C_ARY_B:
963: {
964: int len = atoi(type+1);
965: while (isdigit(*++type));
966: return objc_write_array (stream, type, len, data);
967: }
968: break;
969:
970: default:
971: fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
972: abort();
973: }
974: }
975:
976: /*
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.
981: */
982:
983: int
984: objc_read_type(TypedStream* stream, const char* type, void* data)
985: {
986: char c;
987: switch(c = *type) {
988: case _C_ID:
989: return objc_read_object (stream, (id*)data);
990: break;
991:
992: case _C_CLASS:
993: return objc_read_class (stream, (Class**)data);
994: break;
995:
996: case _C_SEL:
997: return objc_read_selector (stream, (SEL*)data);
998: break;
999:
1000: case _C_CHR:
1001: return objc_read_char (stream, (char*)data);
1002: break;
1003:
1004: case _C_UCHR:
1005: return objc_read_unsigned_char (stream, (unsigned char*)data);
1006: break;
1007:
1008: case _C_SHT:
1009: return objc_read_short (stream, (short*)data);
1010: break;
1011:
1012: case _C_USHT:
1013: return objc_read_unsigned_short (stream, (unsigned short*)data);
1014: break;
1015:
1016: case _C_INT:
1017: case _C_LNG:
1018: return objc_read_int (stream, (int*)data);
1019: break;
1020:
1021: case _C_UINT:
1022: case _C_ULNG:
1023: return objc_read_unsigned_int (stream, (unsigned int*)data);
1024: break;
1025:
1026: case _C_CHARPTR:
1027: case _C_ATOM:
1028: return objc_read_string (stream, (char**)data);
1029: break;
1030:
1031: case _C_ARY_B:
1032: {
1033: int len = atoi(type+1);
1034: while (isdigit(*++type));
1035: return objc_read_array (stream, type, len, data);
1036: }
1037: break;
1038:
1039: default:
1.1.1.2 ! root 1040: fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
1.1 root 1041: abort();
1042: }
1043: }
1044:
1045: /*
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.
1053: */
1054:
1055: int
1056: objc_write_types (TypedStream* stream, const char* type, ...)
1057: {
1058: va_list args;
1059: const char *c;
1060: int res = 0;
1061:
1062: va_start(args, type);
1063:
1064: for (c = type; *c; c = __objc_skip_type (c))
1065: {
1066: switch(*c) {
1067: case _C_ID:
1068: res = objc_write_object (stream, *va_arg (args, id*));
1069: break;
1070:
1071: case _C_CLASS:
1072: res = objc_write_class (stream, *va_arg(args, Class**));
1073: break;
1074:
1075: case _C_SEL:
1076: res = objc_write_selector (stream, *va_arg(args, SEL*));
1077: break;
1078:
1079: case _C_CHR:
1080: res = objc_write_char (stream, *va_arg (args, char*));
1081: break;
1082:
1083: case _C_UCHR:
1084: res = objc_write_unsigned_char (stream,
1085: *va_arg (args, unsigned char*));
1086: break;
1087:
1088: case _C_SHT:
1089: res = objc_write_short (stream, *va_arg(args, short*));
1090: break;
1091:
1092: case _C_USHT:
1093: res = objc_write_unsigned_short (stream,
1094: *va_arg(args, unsigned short*));
1095: break;
1096:
1097: case _C_INT:
1098: case _C_LNG:
1099: res = objc_write_int(stream, *va_arg(args, int*));
1100: break;
1101:
1102: case _C_UINT:
1103: case _C_ULNG:
1104: res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
1105: break;
1106:
1107: case _C_CHARPTR:
1108: {
1.1.1.2 ! root 1109: char** str = va_arg(args, char**);
! 1110: res = objc_write_string (stream, *str, strlen(*str));
1.1 root 1111: }
1112: break;
1113:
1114: case _C_ATOM:
1115: {
1.1.1.2 ! root 1116: char** str = va_arg(args, char**);
! 1117: res = objc_write_string_atomic (stream, *str, strlen(*str));
1.1 root 1118: }
1119: break;
1120:
1121: case _C_ARY_B:
1122: {
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);
1130: }
1131: break;
1132:
1133: default:
1.1.1.2 ! root 1134: fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type);
1.1 root 1135: abort();
1136: }
1137: }
1138: va_end(args);
1139: return res;
1140: }
1141:
1142:
1143: /*
1144: ** Last arguments specify addresses of values to be read. Expected
1145: ** type is checked against the type actually present on the stream.
1146: */
1147:
1148: int
1149: objc_read_types(TypedStream* stream, const char* type, ...)
1150: {
1151: va_list args;
1152: const char *c;
1153: int res = 0;
1154:
1155: va_start(args, type);
1156:
1157: for (c = type; *c; c = __objc_skip_type(c))
1158: {
1159: switch(*c) {
1160: case _C_ID:
1161: res = objc_read_object(stream, va_arg(args, id*));
1162: break;
1163:
1164: case _C_CLASS:
1165: res = objc_read_class(stream, va_arg(args, Class**));
1166: break;
1167:
1168: case _C_SEL:
1169: res = objc_read_selector(stream, va_arg(args, SEL*));
1170: break;
1171:
1172: case _C_CHR:
1173: res = objc_read_char(stream, va_arg(args, char*));
1174: break;
1175:
1176: case _C_UCHR:
1177: res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
1178: break;
1179:
1180: case _C_SHT:
1181: res = objc_read_short(stream, va_arg(args, short*));
1182: break;
1183:
1184: case _C_USHT:
1185: res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
1186: break;
1187:
1188: case _C_INT:
1189: case _C_LNG:
1190: res = objc_read_int(stream, va_arg(args, int*));
1191: break;
1192:
1193: case _C_UINT:
1194: case _C_ULNG:
1195: res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
1196: break;
1197:
1198: case _C_CHARPTR:
1199: case _C_ATOM:
1200: {
1201: char** str = va_arg(args, char**);
1202: res = objc_read_string (stream, str);
1203: }
1204: break;
1205:
1206: case _C_ARY_B:
1207: {
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);
1215: }
1216: break;
1217:
1218: default:
1.1.1.2 ! root 1219: fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
1.1 root 1220: abort();
1221: }
1222: }
1223: va_end(args);
1224: return res;
1225: }
1226:
1227: /*
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)
1230: */
1231:
1232: int
1233: objc_write_array (TypedStream* stream, const char* type,
1234: int count, const void* data)
1235: {
1236: int off = objc_sizeof_type(type);
1237: const char* where = data;
1238:
1239: while (count-- > 0)
1240: {
1241: objc_write_type(stream, type, where);
1242: where += off;
1243: }
1244: return 1;
1245: }
1246:
1247: /*
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)
1252: */
1253:
1254: int
1255: objc_read_array (TypedStream* stream, const char* type,
1256: int count, void* data)
1257: {
1258: int off = objc_sizeof_type(type);
1259: char* where = (char*)data;
1260:
1261: while (count-- > 0)
1262: {
1263: objc_read_type(stream, type, where);
1264: where += off;
1265: }
1266: return 1;
1267: }
1268:
1269: static int
1270: __objc_fread(FILE* file, char* data, int len)
1271: {
1272: return fread(data, len, 1, file);
1273: }
1274:
1275: static int
1276: __objc_fwrite(FILE* file, char* data, int len)
1277: {
1278: return fwrite(data, len, 1, file);
1279: }
1280:
1281: static int
1282: __objc_feof(FILE* file)
1283: {
1284: return feof(file);
1285: }
1286:
1287: static int
1288: __objc_no_write(FILE* file, char* data, int len)
1289: {
1290: __objc_fatal ("TypedStream not open for writing");
1291: }
1292:
1293: static int
1294: __objc_no_read(FILE* file, char* data, int len)
1295: {
1296: __objc_fatal ("TypedStream not open for reading");
1297: }
1298:
1299: static int
1300: __objc_read_typed_stream_signature (TypedStream* stream)
1301: {
1302: char buffer[80];
1303: int pos = 0;
1304: do
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;
1311: }
1312:
1313: static int
1314: __objc_write_typed_stream_signature (TypedStream* stream)
1315: {
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;
1321: }
1322:
1323: static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
1324: {
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);
1329: }
1330:
1331: static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
1332: {
1333: node_ptr node;
1334: SEL awake_sel = sel_get_uid ("awake");
1335:
1336: /* resolve object forward references */
1337: for (node = hash_next (stream->object_refs, NULL); node;
1338: node = hash_next (stream->object_refs, node))
1339: {
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)
1344: {
1345: *((id*)reflist->head) = object;
1346: reflist = reflist->tail;
1347: }
1348: list_free (node->value);
1349: }
1350:
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);
1355:
1356: /* call -awake for all objects read */
1357: if (awake_sel)
1358: {
1359: for (node = hash_next (stream->object_table, NULL); node;
1360: node = hash_next (stream->object_table, node))
1361: {
1362: id object = node->value;
1363: if (__objc_responds_to (object, awake_sel))
1364: (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
1365: }
1366: }
1367:
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);
1373: }
1374:
1375: /*
1376: ** Open the stream PHYSICAL in MODE
1377: */
1378:
1379: TypedStream*
1380: objc_open_typed_stream (FILE* physical, int mode)
1381: {
1382: int fflush(FILE*);
1383:
1384: TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
1385:
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)
1398: {
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);
1406: }
1407: else if (mode == OBJC_WRITEONLY)
1408: {
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);
1414: }
1415: else
1416: {
1417: objc_close_typed_stream (s);
1418: return NULL;
1419: }
1420: s->type = OBJC_FILE_STREAM;
1421: return s;
1422: }
1423:
1424: /*
1425: ** Open the file named by FILE_NAME in MODE
1426: */
1427:
1428: TypedStream*
1429: objc_open_typed_stream_for_file (const char* file_name, int mode)
1430: {
1431: FILE* file = NULL;
1432: TypedStream* s;
1433:
1434: if (mode == OBJC_READONLY)
1435: file = fopen (file_name, "r");
1436: else
1437: file = fopen (file_name, "w");
1438:
1439: if (file)
1440: {
1441: s = objc_open_typed_stream (file, mode);
1442: if (s)
1443: s->type |= OBJC_MANAGED_STREAM;
1444: return s;
1445: }
1446: else
1447: return NULL;
1448: }
1449:
1450: /*
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.
1453: */
1454:
1455: void
1456: objc_close_typed_stream (TypedStream* stream)
1457: {
1458: if (stream->mode == OBJC_READONLY)
1459: {
1460: __objc_finish_read_root_object (stream); /* Just in case... */
1461: hash_delete (stream->class_table);
1462: hash_delete (stream->object_refs);
1463: }
1464:
1465: hash_delete (stream->stream_table);
1466: hash_delete (stream->object_table);
1467:
1468: if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1469: fclose ((FILE*)stream->physical);
1470:
1471: free (stream);
1472: }
1473:
1474: BOOL
1475: objc_end_of_typed_stream (TypedStream* stream)
1476: {
1477: return (*stream->eof)(stream->physical);
1478: }
1479:
1480: void
1481: objc_flush_typed_stream (TypedStream* stream)
1482: {
1483: (*stream->flush)(stream->physical);
1484: }
1485:
1486: int
1487: objc_get_stream_class_version (TypedStream* stream, Class* class)
1488: {
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);
1493: }
1494:
1495: #endif /* __alpha__ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.