|
|
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...) \
37: { fprintf(stderr, "archining: "); \
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: {
620: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
621: (*string) = hash_value_for_key (stream->stream_table, (void*)key);
622: }
623: break;
624:
625: case _B_NSTR:
626: {
627: unsigned int nbytes = buf[0]&_B_VALUE;
628: len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
629: if (len) {
630: (*string) = (char*)__objc_xmalloc(nbytes);
631: if (key)
632: hash_add (&stream->stream_table, (void*)key, *string);
633: len = (*stream->read)(stream->physical, *string, buf[0]&_B_VALUE);
634: (*string)[nbytes] = '\0';
635: }
636: }
637: break;
638:
639: default:
640: __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE));
641: }
642: }
643:
644: return len;
645: }
646:
647:
648: int
649: objc_read_object (struct objc_typed_stream* stream, id* object)
650: {
651: unsigned char buf[sizeof (unsigned int)];
652: int len;
653: if ((len = (*stream->read)(stream->physical, buf, 1)))
654: {
655: SEL read_sel = sel_get_uid ("read:");
656: unsigned int key = 0;
657:
658: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
659: {
660: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
661: len = (*stream->read)(stream->physical, buf, 1);
662: }
663:
664: if (buf[0] == (_B_EXT | _BX_OBJECT))
665: {
666: Class* class;
667:
668: /* get class */
669: len = objc_read_class (stream, &class);
670:
671: /* create instance */
672: (*object) = class_create_instance(class);
673:
674: /* register? */
675: if (key)
676: hash_add (&stream->object_table, (void*)key, *object);
677:
678: /* send -read: */
679: if (__objc_responds_to (*object, read_sel))
680: (*get_imp(class, read_sel))(*object, read_sel, stream);
681:
682: /* check null-byte */
683: len = (*stream->read)(stream->physical, buf, 1);
684: if (buf[0] != '\0')
685: __objc_fatal("expected null-byte, got opcode %c", buf[0]);
686: }
687:
688: else if ((buf[0]&_B_CODE) == _B_UCOMM)
689: {
690: if (key)
691: __objc_fatal("cannot register use upcode...");
692: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
693: (*object) = hash_value_for_key (stream->object_table, (void*)key);
694: }
695:
696: else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
697: {
698: struct objc_list* other;
699: len = objc_read_unsigned_int (stream, &key);
700: other = (struct objc_list*)hash_value_for_key (stream->object_refs, (void*)key);
701: hash_add (&stream->object_refs, (void*)key, (void*)list_cons(object, other));
702: }
703:
704: else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
705: {
706: if (key)
707: __objc_fatal("cannot register root object...");
708: len = objc_read_object (stream, object);
709: __objc_finish_read_root_object (stream);
710: }
711:
712: else
713: __objc_fatal("expected object, got opcode %c", buf[0]);
714: }
715: return len;
716: }
717:
718: static int
719: objc_read_class (struct objc_typed_stream* stream, Class** class)
720: {
721: unsigned char buf[sizeof (unsigned int)];
722: int len;
723: if ((len = (*stream->read)(stream->physical, buf, 1)))
724: {
725: unsigned int key = 0;
726:
727: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
728: {
729: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
730: len = (*stream->read)(stream->physical, buf, 1);
731: }
732:
733: if (buf[0] == (_B_EXT | _BX_CLASS))
734: {
735: char* class_name;
736: int version;
737:
738: /* get class */
739: len = objc_read_string (stream, &class_name);
740: (*class) = objc_get_class(class_name);
741: free (class_name);
742:
743: /* register */
744: if (key)
745: hash_add (&stream->stream_table, (void*)key, *class);
746:
747: objc_read_unsigned_int(stream, &version);
748: hash_add (&stream->class_table, (*class)->name, (void*)version);
749: }
750:
751: else if ((buf[0]&_B_CODE) == _B_UCOMM)
752: {
753: if (key)
754: __objc_fatal("cannot register use upcode...");
755: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
756: (*class) = hash_value_for_key (stream->stream_table, (void*)key);
757: if (!*class)
758: __objc_fatal("cannot find class for key %x", key);
759: }
760:
761: else
762: __objc_fatal("expected class, got opcode %c", buf[0]);
763: }
764: return len;
765: }
766:
767: int
768: objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
769: {
770: unsigned char buf[sizeof (unsigned int)];
771: int len;
772: if ((len = (*stream->read)(stream->physical, buf, 1)))
773: {
774: unsigned int key = 0;
775:
776: if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
777: {
778: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
779: len = (*stream->read)(stream->physical, buf, 1);
780: }
781:
782: if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
783: {
784: char* selector_name;
785:
786: /* get selector */
787: len = objc_read_string (stream, &selector_name);
788: (*selector) = sel_get_uid(selector_name);
789: free (selector_name);
790:
791: /* register */
792: if (key)
793: hash_add (&stream->stream_table, (void*)key, *selector);
794: }
795:
796: else if ((buf[0]&_B_CODE) == _B_UCOMM)
797: {
798: if (key)
799: __objc_fatal("cannot register use upcode...");
800: len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
801: (*selector) = hash_value_for_key (stream->stream_table, (void*)key);
802: }
803:
804: else
805: __objc_fatal("expected selector, got opcode %c", buf[0]);
806: }
807: return len;
808: }
809:
810: static int
811: objc_sizeof_type(const char* type)
812: {
813: switch(*type) {
814: case _C_ID: return sizeof(id);
815: break;
816:
817: case _C_CLASS:
818: return sizeof(Class*);
819: break;
820:
821: case _C_SEL:
822: return sizeof(SEL);
823: break;
824:
825: case _C_CHR:
826: return sizeof(char);
827: break;
828:
829: case _C_UCHR:
830: return sizeof(unsigned char);
831: break;
832:
833: case _C_SHT:
834: return sizeof(short);
835: break;
836:
837: case _C_USHT:
838: return sizeof(unsigned short);
839: break;
840:
841: case _C_INT:
842: case _C_LNG:
843: return sizeof(int);
844: break;
845:
846: case _C_UINT:
847: case _C_ULNG:
848: return sizeof(unsigned int);
849: break;
850:
851: case _C_ATOM:
852: case _C_CHARPTR:
853: return sizeof(char*);
854: break;
855:
856: default:
857: fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
858: abort();
859: }
860: }
861:
862:
863: static const char*
864: __objc_skip_type (const char* type)
865: {
866: switch (*type) {
867: case _C_ID:
868: case _C_CLASS:
869: case _C_SEL:
870: case _C_CHR:
871: case _C_UCHR:
872: case _C_CHARPTR:
873: case _C_ATOM:
874: case _C_SHT:
875: case _C_USHT:
876: case _C_INT:
877: case _C_UINT:
878: case _C_LNG:
879: case _C_ULNG:
880: case _C_FLT:
881: case _C_DBL:
882: return ++type;
883: break;
884:
885: case _C_ARY_B:
886: while(isdigit(*++type));
887: type = __objc_skip_type(type);
888: if (*type == _C_ARY_E)
889: return ++type;
890: else
891: __objc_fatal("cannot parse typespec: %s", type);
892: break;
893:
894: default:
895: fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
896: abort();
897: }
898: }
899:
900: /*
901: ** USER LEVEL FUNCTIONS
902: */
903:
904: /*
905: ** Write one object, encoded in TYPE and pointed to by DATA to the
906: ** typed stream STREAM.
907: */
908:
909: int
910: objc_write_type(TypedStream* stream, const char* type, const void* data)
911: {
912: switch(*type) {
913: case _C_ID:
914: return objc_write_object (stream, *(id*)data);
915: break;
916:
917: case _C_CLASS:
918: return objc_write_class (stream, *(Class**)data);
919: break;
920:
921: case _C_SEL:
922: return objc_write_selector (stream, *(SEL*)data);
923: break;
924:
925: case _C_CHR:
926: return objc_write_char(stream, *(char*)data);
927: break;
928:
929: case _C_UCHR:
930: return objc_write_unsigned_char(stream, *(unsigned char*)data);
931: break;
932:
933: case _C_SHT:
934: return objc_write_short(stream, *(short*)data);
935: break;
936:
937: case _C_USHT:
938: return objc_write_unsigned_short(stream, *(unsigned short*)data);
939: break;
940:
941: case _C_INT:
942: case _C_LNG:
943: return objc_write_int(stream, *(int*)data);
944: break;
945:
946: case _C_UINT:
947: case _C_ULNG:
948: return objc_write_unsigned_int(stream, *(unsigned int*)data);
949: break;
950:
951: case _C_CHARPTR:
952: return objc_write_string (stream, (char*)data, strlen((char*)data));
953: break;
954:
955: case _C_ATOM:
956: return objc_write_string_atomic (stream, (char*)data, strlen((char*)data));
957: break;
958:
959: case _C_ARY_B:
960: {
961: int len = atoi(type+1);
962: while (isdigit(*++type));
963: return objc_write_array (stream, type, len, data);
964: }
965: break;
966:
967: default:
968: fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
969: abort();
970: }
971: }
972:
973: /*
974: ** Read one object, encoded in TYPE and pointed to by DATA to the
975: ** typed stream STREAM. DATA specifies the address of the types to
976: ** read. Expected type is checked against the type actually present
977: ** on the stream.
978: */
979:
980: int
981: objc_read_type(TypedStream* stream, const char* type, void* data)
982: {
983: char c;
984: switch(c = *type) {
985: case _C_ID:
986: return objc_read_object (stream, (id*)data);
987: break;
988:
989: case _C_CLASS:
990: return objc_read_class (stream, (Class**)data);
991: break;
992:
993: case _C_SEL:
994: return objc_read_selector (stream, (SEL*)data);
995: break;
996:
997: case _C_CHR:
998: return objc_read_char (stream, (char*)data);
999: break;
1000:
1001: case _C_UCHR:
1002: return objc_read_unsigned_char (stream, (unsigned char*)data);
1003: break;
1004:
1005: case _C_SHT:
1006: return objc_read_short (stream, (short*)data);
1007: break;
1008:
1009: case _C_USHT:
1010: return objc_read_unsigned_short (stream, (unsigned short*)data);
1011: break;
1012:
1013: case _C_INT:
1014: case _C_LNG:
1015: return objc_read_int (stream, (int*)data);
1016: break;
1017:
1018: case _C_UINT:
1019: case _C_ULNG:
1020: return objc_read_unsigned_int (stream, (unsigned int*)data);
1021: break;
1022:
1023: case _C_CHARPTR:
1024: case _C_ATOM:
1025: return objc_read_string (stream, (char**)data);
1026: break;
1027:
1028: case _C_ARY_B:
1029: {
1030: int len = atoi(type+1);
1031: while (isdigit(*++type));
1032: return objc_read_array (stream, type, len, data);
1033: }
1034: break;
1035:
1036: default:
1037: fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
1038: abort();
1039: }
1040: }
1041:
1042: /*
1043: ** Write the object specified by the template TYPE to STREAM. Last
1044: ** arguments specify addresses of values to be written. It might
1045: ** seem surprising to specify values by address, but this is extremely
1046: ** convenient for copy-paste with objc_read_types calls. A more
1047: ** down-to-the-earth cause for this passing of addresses is that values
1048: ** of arbitrary size is not well supported in ANSI C for functions with
1049: ** variable number of arguments.
1050: */
1051:
1052: int
1053: objc_write_types (TypedStream* stream, const char* type, ...)
1054: {
1055: va_list args;
1056: const char *c;
1057: int res = 0;
1058:
1059: va_start(args, type);
1060:
1061: for (c = type; *c; c = __objc_skip_type (c))
1062: {
1063: switch(*c) {
1064: case _C_ID:
1065: res = objc_write_object (stream, *va_arg (args, id*));
1066: break;
1067:
1068: case _C_CLASS:
1069: res = objc_write_class (stream, *va_arg(args, Class**));
1070: break;
1071:
1072: case _C_SEL:
1073: res = objc_write_selector (stream, *va_arg(args, SEL*));
1074: break;
1075:
1076: case _C_CHR:
1077: res = objc_write_char (stream, *va_arg (args, char*));
1078: break;
1079:
1080: case _C_UCHR:
1081: res = objc_write_unsigned_char (stream,
1082: *va_arg (args, unsigned char*));
1083: break;
1084:
1085: case _C_SHT:
1086: res = objc_write_short (stream, *va_arg(args, short*));
1087: break;
1088:
1089: case _C_USHT:
1090: res = objc_write_unsigned_short (stream,
1091: *va_arg(args, unsigned short*));
1092: break;
1093:
1094: case _C_INT:
1095: case _C_LNG:
1096: res = objc_write_int(stream, *va_arg(args, int*));
1097: break;
1098:
1099: case _C_UINT:
1100: case _C_ULNG:
1101: res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
1102: break;
1103:
1104: case _C_CHARPTR:
1105: {
1106: char* str = va_arg(args, char*);
1107: res = objc_write_string (stream, str, strlen(str));
1108: }
1109: break;
1110:
1111: case _C_ATOM:
1112: {
1113: char* str = va_arg(args, char*);
1114: res = objc_write_string_atomic (stream, str, strlen(str));
1115: }
1116: break;
1117:
1118: case _C_ARY_B:
1119: {
1120: int len = atoi(c+1);
1121: const char* t = c;
1122: while (isdigit(*++t));
1123: res = objc_write_array (stream, t, len, va_arg(args, void*));
1124: t = __objc_skip_type (t);
1125: if (*t != _C_ARY_E)
1126: __objc_fatal("expected `]', got: %s", t);
1127: }
1128: break;
1129:
1130: default:
1131: fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
1132: abort();
1133: }
1134: }
1135: va_end(args);
1136: return res;
1137: }
1138:
1139:
1140: /*
1141: ** Last arguments specify addresses of values to be read. Expected
1142: ** type is checked against the type actually present on the stream.
1143: */
1144:
1145: int
1146: objc_read_types(TypedStream* stream, const char* type, ...)
1147: {
1148: va_list args;
1149: const char *c;
1150: int res = 0;
1151:
1152: va_start(args, type);
1153:
1154: for (c = type; *c; c = __objc_skip_type(c))
1155: {
1156: switch(*c) {
1157: case _C_ID:
1158: res = objc_read_object(stream, va_arg(args, id*));
1159: break;
1160:
1161: case _C_CLASS:
1162: res = objc_read_class(stream, va_arg(args, Class**));
1163: break;
1164:
1165: case _C_SEL:
1166: res = objc_read_selector(stream, va_arg(args, SEL*));
1167: break;
1168:
1169: case _C_CHR:
1170: res = objc_read_char(stream, va_arg(args, char*));
1171: break;
1172:
1173: case _C_UCHR:
1174: res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
1175: break;
1176:
1177: case _C_SHT:
1178: res = objc_read_short(stream, va_arg(args, short*));
1179: break;
1180:
1181: case _C_USHT:
1182: res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
1183: break;
1184:
1185: case _C_INT:
1186: case _C_LNG:
1187: res = objc_read_int(stream, va_arg(args, int*));
1188: break;
1189:
1190: case _C_UINT:
1191: case _C_ULNG:
1192: res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
1193: break;
1194:
1195: case _C_CHARPTR:
1196: case _C_ATOM:
1197: {
1198: char** str = va_arg(args, char**);
1199: res = objc_read_string (stream, str);
1200: }
1201: break;
1202:
1203: case _C_ARY_B:
1204: {
1205: int len = atoi(c+1);
1206: const char* t = c;
1207: while (isdigit(*++t));
1208: res = objc_read_array (stream, t, len, va_arg(args, void*));
1209: t = __objc_skip_type (t);
1210: if (*t != _C_ARY_E)
1211: __objc_fatal("expected `]', got: %s", t);
1212: }
1213: break;
1214:
1215: default:
1216: fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
1217: abort();
1218: }
1219: }
1220: va_end(args);
1221: return res;
1222: }
1223:
1224: /*
1225: ** Write an array of COUNT elements of TYPE from the memory address DATA.
1226: ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1227: */
1228:
1229: int
1230: objc_write_array (TypedStream* stream, const char* type,
1231: int count, const void* data)
1232: {
1233: int off = objc_sizeof_type(type);
1234: const char* where = data;
1235:
1236: while (count-- > 0)
1237: {
1238: objc_write_type(stream, type, where);
1239: where += off;
1240: }
1241: return 1;
1242: }
1243:
1244: /*
1245: ** Read an array of COUNT elements of TYPE into the memory address
1246: ** DATA. The memory pointed to by data is supposed to be allocated
1247: ** by the callee. This is equivalent of
1248: ** objc_read_type (stream, "[N<type>]", data)
1249: */
1250:
1251: int
1252: objc_read_array (TypedStream* stream, const char* type,
1253: int count, void* data)
1254: {
1255: int off = objc_sizeof_type(type);
1256: char* where = (char*)data;
1257:
1258: while (count-- > 0)
1259: {
1260: objc_read_type(stream, type, where);
1261: where += off;
1262: }
1263: return 1;
1264: }
1265:
1266: static int
1267: __objc_fread(FILE* file, char* data, int len)
1268: {
1269: return fread(data, len, 1, file);
1270: }
1271:
1272: static int
1273: __objc_fwrite(FILE* file, char* data, int len)
1274: {
1275: return fwrite(data, len, 1, file);
1276: }
1277:
1278: static int
1279: __objc_feof(FILE* file)
1280: {
1281: return feof(file);
1282: }
1283:
1284: static int
1285: __objc_no_write(FILE* file, char* data, int len)
1286: {
1287: __objc_fatal ("TypedStream not open for writing");
1288: }
1289:
1290: static int
1291: __objc_no_read(FILE* file, char* data, int len)
1292: {
1293: __objc_fatal ("TypedStream not open for reading");
1294: }
1295:
1296: static int
1297: __objc_read_typed_stream_signature (TypedStream* stream)
1298: {
1299: char buffer[80];
1300: int pos = 0;
1301: do
1302: (*stream->read)(stream->physical, buffer+pos, 1);
1303: while (buffer[pos++] != '\0');
1304: sscanf (buffer, "GNU TypedStream %d", &stream->version);
1305: if (stream->version != OBJC_TYPED_STREAM_VERSION)
1306: __objc_fatal ("cannot handle TypedStream version %d", stream->version);
1307: return 1;
1308: }
1309:
1310: static int
1311: __objc_write_typed_stream_signature (TypedStream* stream)
1312: {
1313: char buffer[80];
1314: sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
1315: stream->version = OBJC_TYPED_STREAM_VERSION;
1316: (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
1317: return 1;
1318: }
1319:
1320: static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
1321: {
1322: hash_delete (stream->object_table);
1323: stream->object_table = hash_new(64,
1324: (hash_func_type)hash_ptr,
1325: (compare_func_type)compare_ptrs);
1326: }
1327:
1328: static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
1329: {
1330: node_ptr node;
1331: SEL awake_sel = sel_get_uid ("awake");
1332:
1333: /* resolve object forward references */
1334: for (node = hash_next (stream->object_refs, NULL); node;
1335: node = hash_next (stream->object_refs, node))
1336: {
1337: struct objc_list* reflist = node->value;
1338: const void* key = node->key;
1339: id object = hash_value_for_key (stream->object_table, key);
1340: while(reflist)
1341: {
1342: *((id*)reflist->head) = object;
1343: reflist = reflist->tail;
1344: }
1345: list_free (node->value);
1346: }
1347:
1348: /* empty object reference table */
1349: hash_delete (stream->object_refs);
1350: stream->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1351: (compare_func_type)compare_ptrs);
1352:
1353: /* call -awake for all objects read */
1354: if (awake_sel)
1355: {
1356: for (node = hash_next (stream->object_table, NULL); node;
1357: node = hash_next (stream->object_table, node))
1358: {
1359: id object = node->value;
1360: if (__objc_responds_to (object, awake_sel))
1361: (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
1362: }
1363: }
1364:
1365: /* empty object table */
1366: hash_delete (stream->object_table);
1367: stream->object_table = hash_new(64,
1368: (hash_func_type)hash_ptr,
1369: (compare_func_type)compare_ptrs);
1370: }
1371:
1372: /*
1373: ** Open the stream PHYSICAL in MODE
1374: */
1375:
1376: TypedStream*
1377: objc_open_typed_stream (FILE* physical, int mode)
1378: {
1379: int fflush(FILE*);
1380:
1381: TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
1382:
1383: s->mode = mode;
1384: s->physical = physical;
1385: s->stream_table = hash_new(64,
1386: (hash_func_type)hash_ptr,
1387: (compare_func_type)compare_ptrs);
1388: s->object_table = hash_new(64,
1389: (hash_func_type)hash_ptr,
1390: (compare_func_type)compare_ptrs);
1391: s->eof = (objc_typed_eof_func)__objc_feof;
1392: s->flush = (objc_typed_flush_func)fflush;
1393: s->writing_root_p = 0;
1394: if (mode == OBJC_READONLY)
1395: {
1396: s->class_table = hash_new(8, (hash_func_type)hash_string,
1397: (compare_func_type)compare_strings);
1398: s->object_refs = hash_new(8, (hash_func_type)hash_ptr,
1399: (compare_func_type)compare_ptrs);
1400: s->read = (objc_typed_read_func)__objc_fread;
1401: s->write = (objc_typed_write_func)__objc_no_write;
1402: __objc_read_typed_stream_signature (s);
1403: }
1404: else if (mode == OBJC_WRITEONLY)
1405: {
1406: s->class_table = 0;
1407: s->object_refs = 0;
1408: s->read = (objc_typed_read_func)__objc_no_read;
1409: s->write = (objc_typed_write_func)__objc_fwrite;
1410: __objc_write_typed_stream_signature (s);
1411: }
1412: else
1413: {
1414: objc_close_typed_stream (s);
1415: return NULL;
1416: }
1417: s->type = OBJC_FILE_STREAM;
1418: return s;
1419: }
1420:
1421: /*
1422: ** Open the file named by FILE_NAME in MODE
1423: */
1424:
1425: TypedStream*
1426: objc_open_typed_stream_for_file (const char* file_name, int mode)
1427: {
1428: FILE* file = NULL;
1429: TypedStream* s;
1430:
1431: if (mode == OBJC_READONLY)
1432: file = fopen (file_name, "r");
1433: else
1434: file = fopen (file_name, "w");
1435:
1436: if (file)
1437: {
1438: s = objc_open_typed_stream (file, mode);
1439: if (s)
1440: s->type |= OBJC_MANAGED_STREAM;
1441: return s;
1442: }
1443: else
1444: return NULL;
1445: }
1446:
1447: /*
1448: ** Close STREAM freeing the structure it self. If it was opened with
1449: ** objc_open_typed_stream_for_file, the file will also be closed.
1450: */
1451:
1452: void
1453: objc_close_typed_stream (TypedStream* stream)
1454: {
1455: if (stream->mode == OBJC_READONLY)
1456: {
1457: __objc_finish_read_root_object (stream); /* Just in case... */
1458: hash_delete (stream->class_table);
1459: hash_delete (stream->object_refs);
1460: }
1461:
1462: hash_delete (stream->stream_table);
1463: hash_delete (stream->object_table);
1464:
1465: if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1466: fclose ((FILE*)stream->physical);
1467:
1468: free (stream);
1469: }
1470:
1471: BOOL
1472: objc_end_of_typed_stream (TypedStream* stream)
1473: {
1474: return (*stream->eof)(stream->physical);
1475: }
1476:
1477: void
1478: objc_flush_typed_stream (TypedStream* stream)
1479: {
1480: (*stream->flush)(stream->physical);
1481: }
1482:
1483: int
1484: objc_get_stream_class_version (TypedStream* stream, Class* class)
1485: {
1486: if (stream->class_table)
1487: return (int) hash_value_for_key (stream->class_table, class->name);
1488: else
1489: return class_get_version (class);
1490: }
1491:
1492: #endif /* __alpha__ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.