* config/ia64/ia64.md (cstorebi4): Fix thinko.
[gcc.git] / libobjc / archive.c
1 /* GNU Objective C Runtime archiving
2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009 Free Software Foundation, Inc.
3 Contributed by Kresten Krab Thorup
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 3, or (at your option) any later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
24
25 #include "tconfig.h"
26 #include "objc/runtime.h"
27 #include "objc/typedstream.h"
28 #include "objc/encoding.h"
29 #include <stdlib.h>
30
31 extern int fflush (FILE *);
32
33 #define ROUND(V, A) \
34 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
35 __a * ((__v + __a - 1)/__a); })
36
37 #define PTR2LONG(P) (((char *) (P))-(char *) 0)
38 #define LONG2PTR(L) (((char *) 0) + (L))
39
40 /* Declare some functions... */
41
42 static int
43 objc_read_class (struct objc_typed_stream *stream, Class *class);
44
45 int objc_sizeof_type (const char *type);
46
47 static int
48 objc_write_use_common (struct objc_typed_stream *stream, unsigned long key);
49
50 static int
51 objc_write_register_common (struct objc_typed_stream *stream,
52 unsigned long key);
53
54 static int
55 objc_write_class (struct objc_typed_stream *stream,
56 struct objc_class *class);
57
58 const char *objc_skip_type (const char *type);
59
60 static void __objc_finish_write_root_object (struct objc_typed_stream *);
61 static void __objc_finish_read_root_object (struct objc_typed_stream *);
62
63 static inline int
64 __objc_code_unsigned_char (unsigned char *buf, unsigned char val)
65 {
66 if ((val&_B_VALUE) == val)
67 {
68 buf[0] = val|_B_SINT;
69 return 1;
70 }
71 else
72 {
73 buf[0] = _B_NINT|0x01;
74 buf[1] = val;
75 return 2;
76 }
77 }
78
79 int
80 objc_write_unsigned_char (struct objc_typed_stream *stream,
81 unsigned char value)
82 {
83 unsigned char buf[sizeof (unsigned char) + 1];
84 int len = __objc_code_unsigned_char (buf, value);
85 return (*stream->write) (stream->physical, (char*)buf, len);
86 }
87
88 static inline int
89 __objc_code_char (unsigned char *buf, signed char val)
90 {
91 if (val >= 0)
92 return __objc_code_unsigned_char (buf, val);
93 else
94 {
95 buf[0] = _B_NINT|_B_SIGN|0x01;
96 buf[1] = -val;
97 return 2;
98 }
99 }
100
101 int
102 objc_write_char (struct objc_typed_stream *stream, signed char value)
103 {
104 unsigned char buf[sizeof (char) + 1];
105 int len = __objc_code_char (buf, value);
106 return (*stream->write) (stream->physical, (char*)buf, len);
107 }
108
109 static inline int
110 __objc_code_unsigned_short (unsigned char *buf, unsigned short val)
111 {
112 if ((val&_B_VALUE) == val)
113 {
114 buf[0] = val|_B_SINT;
115 return 1;
116 }
117 else
118 {
119 int c, b;
120
121 buf[0] = _B_NINT;
122
123 for (c = sizeof (short); c != 0; c -= 1)
124 if (((val >> (8*(c - 1)))%0x100) != 0)
125 break;
126
127 buf[0] |= c;
128
129 for (b = 1; c != 0; c--, b++)
130 {
131 buf[b] = (val >> (8*(c - 1)))%0x100;
132 }
133
134 return b;
135 }
136 }
137
138 int
139 objc_write_unsigned_short (struct objc_typed_stream *stream,
140 unsigned short value)
141 {
142 unsigned char buf[sizeof (unsigned short) + 1];
143 int len = __objc_code_unsigned_short (buf, value);
144 return (*stream->write) (stream->physical, (char*)buf, len);
145 }
146
147 static inline int
148 __objc_code_short (unsigned char *buf, short val)
149 {
150 int sign = (val < 0);
151 int size = __objc_code_unsigned_short (buf, sign ? -val : val);
152 if (sign)
153 buf[0] |= _B_SIGN;
154 return size;
155 }
156
157 int
158 objc_write_short (struct objc_typed_stream *stream, short value)
159 {
160 unsigned char buf[sizeof (short) + 1];
161 int len = __objc_code_short (buf, value);
162 return (*stream->write) (stream->physical, (char*)buf, len);
163 }
164
165
166 static inline int
167 __objc_code_unsigned_int (unsigned char *buf, unsigned int val)
168 {
169 if ((val&_B_VALUE) == val)
170 {
171 buf[0] = val|_B_SINT;
172 return 1;
173 }
174 else
175 {
176 int c, b;
177
178 buf[0] = _B_NINT;
179
180 for (c = sizeof (int); c != 0; c -= 1)
181 if (((val >> (8*(c - 1)))%0x100) != 0)
182 break;
183
184 buf[0] |= c;
185
186 for (b = 1; c != 0; c--, b++)
187 {
188 buf[b] = (val >> (8*(c-1)))%0x100;
189 }
190
191 return b;
192 }
193 }
194
195 int
196 objc_write_unsigned_int (struct objc_typed_stream *stream, unsigned int value)
197 {
198 unsigned char buf[sizeof (unsigned int) + 1];
199 int len = __objc_code_unsigned_int (buf, value);
200 return (*stream->write) (stream->physical, (char*)buf, len);
201 }
202
203 static inline int
204 __objc_code_int (unsigned char *buf, int val)
205 {
206 int sign = (val < 0);
207 int size = __objc_code_unsigned_int (buf, sign ? -val : val);
208 if (sign)
209 buf[0] |= _B_SIGN;
210 return size;
211 }
212
213 int
214 objc_write_int (struct objc_typed_stream *stream, int value)
215 {
216 unsigned char buf[sizeof (int) + 1];
217 int len = __objc_code_int (buf, value);
218 return (*stream->write) (stream->physical, (char*)buf, len);
219 }
220
221 static inline int
222 __objc_code_unsigned_long (unsigned char *buf, unsigned long val)
223 {
224 if ((val&_B_VALUE) == val)
225 {
226 buf[0] = val|_B_SINT;
227 return 1;
228 }
229 else
230 {
231 int c, b;
232
233 buf[0] = _B_NINT;
234
235 for (c = sizeof (long); c != 0; c -= 1)
236 if (((val >> (8*(c - 1)))%0x100) != 0)
237 break;
238
239 buf[0] |= c;
240
241 for (b = 1; c != 0; c--, b++)
242 {
243 buf[b] = (val >> (8*(c - 1)))%0x100;
244 }
245
246 return b;
247 }
248 }
249
250 int
251 objc_write_unsigned_long (struct objc_typed_stream *stream,
252 unsigned long value)
253 {
254 unsigned char buf[sizeof (unsigned long) + 1];
255 int len = __objc_code_unsigned_long (buf, value);
256 return (*stream->write) (stream->physical, (char*)buf, len);
257 }
258
259 static inline int
260 __objc_code_long (unsigned char *buf, long val)
261 {
262 int sign = (val < 0);
263 int size = __objc_code_unsigned_long (buf, sign ? -val : val);
264 if (sign)
265 buf[0] |= _B_SIGN;
266 return size;
267 }
268
269 int
270 objc_write_long (struct objc_typed_stream *stream, long value)
271 {
272 unsigned char buf[sizeof (long) + 1];
273 int len = __objc_code_long (buf, value);
274 return (*stream->write) (stream->physical, (char*)buf, len);
275 }
276
277
278 int
279 objc_write_string (struct objc_typed_stream *stream,
280 const unsigned char *string, unsigned int nbytes)
281 {
282 unsigned char buf[sizeof (unsigned int) + 1];
283 int len = __objc_code_unsigned_int (buf, nbytes);
284
285 if ((buf[0]&_B_CODE) == _B_SINT)
286 buf[0] = (buf[0]&_B_VALUE)|_B_SSTR;
287
288 else /* _B_NINT */
289 buf[0] = (buf[0]&_B_VALUE)|_B_NSTR;
290
291 if ((*stream->write) (stream->physical, (char*)buf, len) != 0)
292 return (*stream->write) (stream->physical, (char*)string, nbytes);
293 else
294 return 0;
295 }
296
297 int
298 objc_write_string_atomic (struct objc_typed_stream *stream,
299 unsigned char *string, unsigned int nbytes)
300 {
301 unsigned long key;
302 if ((key = PTR2LONG(objc_hash_value_for_key (stream->stream_table, string))))
303 return objc_write_use_common (stream, key);
304 else
305 {
306 int length;
307 objc_hash_add (&stream->stream_table,
308 LONG2PTR(key=PTR2LONG(string)), string);
309 if ((length = objc_write_register_common (stream, key)))
310 return objc_write_string (stream, string, nbytes);
311 return length;
312 }
313 }
314
315 static int
316 objc_write_register_common (struct objc_typed_stream *stream,
317 unsigned long key)
318 {
319 unsigned char buf[sizeof (unsigned long)+2];
320 int len = __objc_code_unsigned_long (buf + 1, key);
321 if (len == 1)
322 {
323 buf[0] = _B_RCOMM|0x01;
324 buf[1] &= _B_VALUE;
325 return (*stream->write) (stream->physical, (char*)buf, len + 1);
326 }
327 else
328 {
329 buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM;
330 return (*stream->write) (stream->physical, (char*)buf + 1, len);
331 }
332 }
333
334 static int
335 objc_write_use_common (struct objc_typed_stream *stream, unsigned long key)
336 {
337 unsigned char buf[sizeof (unsigned long)+2];
338 int len = __objc_code_unsigned_long (buf + 1, key);
339 if (len == 1)
340 {
341 buf[0] = _B_UCOMM|0x01;
342 buf[1] &= _B_VALUE;
343 return (*stream->write) (stream->physical, (char*)buf, 2);
344 }
345 else
346 {
347 buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM;
348 return (*stream->write) (stream->physical, (char*)buf + 1, len);
349 }
350 }
351
352 static inline int
353 __objc_write_extension (struct objc_typed_stream *stream, unsigned char code)
354 {
355 if (code <= _B_VALUE)
356 {
357 unsigned char buf = code|_B_EXT;
358 return (*stream->write) (stream->physical, (char*)&buf, 1);
359 }
360 else
361 {
362 objc_error (nil, OBJC_ERR_BAD_OPCODE,
363 "__objc_write_extension: bad opcode %c\n", code);
364 return -1;
365 }
366 }
367
368 inline int
369 __objc_write_object (struct objc_typed_stream *stream, id object)
370 {
371 unsigned char buf = '\0';
372 SEL write_sel = sel_get_any_uid ("write:");
373 if (object)
374 {
375 __objc_write_extension (stream, _BX_OBJECT);
376 objc_write_class (stream, object->class_pointer);
377 (*objc_msg_lookup (object, write_sel)) (object, write_sel, stream);
378 return (*stream->write) (stream->physical, (char*)&buf, 1);
379 }
380 else
381 return objc_write_use_common (stream, 0);
382 }
383
384 int
385 objc_write_object_reference (struct objc_typed_stream *stream, id object)
386 {
387 unsigned long key;
388 if ((key = PTR2LONG(objc_hash_value_for_key (stream->object_table, object))))
389 return objc_write_use_common (stream, key);
390
391 __objc_write_extension (stream, _BX_OBJREF);
392 return objc_write_unsigned_long (stream, PTR2LONG (object));
393 }
394
395 int
396 objc_write_root_object (struct objc_typed_stream *stream, id object)
397 {
398 int len = 0;
399 if (stream->writing_root_p)
400 objc_error (nil, OBJC_ERR_RECURSE_ROOT,
401 "objc_write_root_object called recursively");
402 else
403 {
404 stream->writing_root_p = 1;
405 __objc_write_extension (stream, _BX_OBJROOT);
406 if ((len = objc_write_object (stream, object)))
407 __objc_finish_write_root_object (stream);
408 stream->writing_root_p = 0;
409 }
410 return len;
411 }
412
413 int
414 objc_write_object (struct objc_typed_stream *stream, id object)
415 {
416 unsigned long key;
417 if ((key = PTR2LONG(objc_hash_value_for_key (stream->object_table, object))))
418 return objc_write_use_common (stream, key);
419
420 else if (object == nil)
421 return objc_write_use_common (stream, 0);
422
423 else
424 {
425 int length;
426 objc_hash_add (&stream->object_table,
427 LONG2PTR(key=PTR2LONG(object)), object);
428 if ((length = objc_write_register_common (stream, key)))
429 return __objc_write_object (stream, object);
430 return length;
431 }
432 }
433
434 inline int
435 __objc_write_class (struct objc_typed_stream *stream, struct objc_class *class)
436 {
437 __objc_write_extension (stream, _BX_CLASS);
438 objc_write_string_atomic (stream, (unsigned char *) class->name,
439 strlen ((char *) class->name));
440 return objc_write_unsigned_long (stream, class->version);
441 }
442
443
444 static int
445 objc_write_class (struct objc_typed_stream *stream,
446 struct objc_class *class)
447 {
448 unsigned long key;
449 if ((key = PTR2LONG(objc_hash_value_for_key (stream->stream_table, class))))
450 return objc_write_use_common (stream, key);
451 else
452 {
453 int length;
454 objc_hash_add (&stream->stream_table,
455 LONG2PTR(key = PTR2LONG(class)), class);
456 if ((length = objc_write_register_common (stream, key)))
457 return __objc_write_class (stream, class);
458 return length;
459 }
460 }
461
462
463 inline int
464 __objc_write_selector (struct objc_typed_stream *stream, SEL selector)
465 {
466 const char *sel_name;
467 __objc_write_extension (stream, _BX_SEL);
468 /* to handle NULL selectors */
469 if ((SEL)0 == selector)
470 return objc_write_string (stream, (unsigned char*)"", 0);
471 sel_name = sel_get_name (selector);
472 return objc_write_string (stream, (unsigned char*)sel_name, strlen ((char*)sel_name));
473 }
474
475 int
476 objc_write_selector (struct objc_typed_stream *stream, SEL selector)
477 {
478 const char *sel_name;
479 unsigned long key;
480
481 /* to handle NULL selectors */
482 if ((SEL)0 == selector)
483 return __objc_write_selector (stream, selector);
484
485 sel_name = sel_get_name (selector);
486 if ((key = PTR2LONG(objc_hash_value_for_key (stream->stream_table,
487 sel_name))))
488 return objc_write_use_common (stream, key);
489 else
490 {
491 int length;
492 objc_hash_add (&stream->stream_table,
493 LONG2PTR(key = PTR2LONG(sel_name)), (char *) sel_name);
494 if ((length = objc_write_register_common (stream, key)))
495 return __objc_write_selector (stream, selector);
496 return length;
497 }
498 }
499
500
501
502 /*
503 ** Read operations
504 */
505
506 inline int
507 objc_read_char (struct objc_typed_stream *stream, char *val)
508 {
509 unsigned char buf;
510 int len;
511 len = (*stream->read) (stream->physical, (char*)&buf, 1);
512 if (len != 0)
513 {
514 if ((buf & _B_CODE) == _B_SINT)
515 (*val) = (buf & _B_VALUE);
516
517 else if ((buf & _B_NUMBER) == 1)
518 {
519 len = (*stream->read) (stream->physical, val, 1);
520 if (buf&_B_SIGN)
521 (*val) = -1 * (*val);
522 }
523
524 else
525 objc_error (nil, OBJC_ERR_BAD_DATA,
526 "expected 8bit signed int, got %dbit int",
527 (int) (buf&_B_NUMBER)*8);
528 }
529 return len;
530 }
531
532
533 inline int
534 objc_read_unsigned_char (struct objc_typed_stream *stream, unsigned char *val)
535 {
536 unsigned char buf;
537 int len;
538 if ((len = (*stream->read) (stream->physical, (char*)&buf, 1)))
539 {
540 if ((buf & _B_CODE) == _B_SINT)
541 (*val) = (buf & _B_VALUE);
542
543 else if ((buf & _B_NUMBER) == 1)
544 len = (*stream->read) (stream->physical, (char*)val, 1);
545
546 else
547 objc_error (nil, OBJC_ERR_BAD_DATA,
548 "expected 8bit unsigned int, got %dbit int",
549 (int) (buf&_B_NUMBER)*8);
550 }
551 return len;
552 }
553
554 inline int
555 objc_read_short (struct objc_typed_stream *stream, short *value)
556 {
557 unsigned char buf[sizeof (short) + 1];
558 int len;
559 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
560 {
561 if ((buf[0] & _B_CODE) == _B_SINT)
562 (*value) = (buf[0] & _B_VALUE);
563
564 else
565 {
566 int pos = 1;
567 int nbytes = buf[0] & _B_NUMBER;
568 if (nbytes > (int) sizeof (short))
569 objc_error (nil, OBJC_ERR_BAD_DATA,
570 "expected short, got bigger (%dbits)", nbytes*8);
571 len = (*stream->read) (stream->physical, (char*)buf + 1, nbytes);
572 (*value) = 0;
573 while (pos <= nbytes)
574 (*value) = ((*value)*0x100) + buf[pos++];
575 if (buf[0] & _B_SIGN)
576 (*value) = -(*value);
577 }
578 }
579 return len;
580 }
581
582 inline int
583 objc_read_unsigned_short (struct objc_typed_stream *stream,
584 unsigned short *value)
585 {
586 unsigned char buf[sizeof (unsigned short) + 1];
587 int len;
588 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
589 {
590 if ((buf[0] & _B_CODE) == _B_SINT)
591 (*value) = (buf[0] & _B_VALUE);
592
593 else
594 {
595 int pos = 1;
596 int nbytes = buf[0] & _B_NUMBER;
597 if (nbytes > (int) sizeof (short))
598 objc_error (nil, OBJC_ERR_BAD_DATA,
599 "expected short, got int or bigger");
600 len = (*stream->read) (stream->physical, (char*)buf + 1, nbytes);
601 (*value) = 0;
602 while (pos <= nbytes)
603 (*value) = ((*value)*0x100) + buf[pos++];
604 }
605 }
606 return len;
607 }
608
609
610 inline int
611 objc_read_int (struct objc_typed_stream *stream, int *value)
612 {
613 unsigned char buf[sizeof (int) + 1];
614 int len;
615 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
616 {
617 if ((buf[0] & _B_CODE) == _B_SINT)
618 (*value) = (buf[0] & _B_VALUE);
619
620 else
621 {
622 int pos = 1;
623 int nbytes = buf[0] & _B_NUMBER;
624 if (nbytes > (int) sizeof (int))
625 objc_error (nil, OBJC_ERR_BAD_DATA, "expected int, got bigger");
626 len = (*stream->read) (stream->physical, (char*)buf + 1, nbytes);
627 (*value) = 0;
628 while (pos <= nbytes)
629 (*value) = ((*value)*0x100) + buf[pos++];
630 if (buf[0] & _B_SIGN)
631 (*value) = -(*value);
632 }
633 }
634 return len;
635 }
636
637 inline int
638 objc_read_long (struct objc_typed_stream *stream, long *value)
639 {
640 unsigned char buf[sizeof (long) + 1];
641 int len;
642 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
643 {
644 if ((buf[0] & _B_CODE) == _B_SINT)
645 (*value) = (buf[0] & _B_VALUE);
646
647 else
648 {
649 int pos = 1;
650 int nbytes = buf[0] & _B_NUMBER;
651 if (nbytes > (int) sizeof (long))
652 objc_error (nil, OBJC_ERR_BAD_DATA, "expected long, got bigger");
653 len = (*stream->read) (stream->physical, (char*)buf + 1, nbytes);
654 (*value) = 0;
655 while (pos <= nbytes)
656 (*value) = ((*value)*0x100) + buf[pos++];
657 if (buf[0] & _B_SIGN)
658 (*value) = -(*value);
659 }
660 }
661 return len;
662 }
663
664 inline int
665 __objc_read_nbyte_uint (struct objc_typed_stream *stream,
666 unsigned int nbytes, unsigned int *val)
667 {
668 int len;
669 unsigned int pos = 0;
670 unsigned char buf[sizeof (unsigned int) + 1];
671
672 if (nbytes > sizeof (int))
673 objc_error (nil, OBJC_ERR_BAD_DATA, "expected int, got bigger");
674
675 len = (*stream->read) (stream->physical, (char*)buf, nbytes);
676 (*val) = 0;
677 while (pos < nbytes)
678 (*val) = ((*val)*0x100) + buf[pos++];
679 return len;
680 }
681
682
683 inline int
684 objc_read_unsigned_int (struct objc_typed_stream *stream,
685 unsigned int *value)
686 {
687 unsigned char buf[sizeof (unsigned int) + 1];
688 int len;
689 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
690 {
691 if ((buf[0] & _B_CODE) == _B_SINT)
692 (*value) = (buf[0] & _B_VALUE);
693
694 else
695 len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value);
696
697 }
698 return len;
699 }
700
701 int
702 __objc_read_nbyte_ulong (struct objc_typed_stream *stream,
703 unsigned int nbytes, unsigned long *val)
704 {
705 int len;
706 unsigned int pos = 0;
707 unsigned char buf[sizeof (unsigned long) + 1];
708
709 if (nbytes > sizeof (long))
710 objc_error (nil, OBJC_ERR_BAD_DATA, "expected long, got bigger");
711
712 len = (*stream->read) (stream->physical, (char*)buf, nbytes);
713 (*val) = 0;
714 while (pos < nbytes)
715 (*val) = ((*val)*0x100) + buf[pos++];
716 return len;
717 }
718
719
720 inline int
721 objc_read_unsigned_long (struct objc_typed_stream *stream,
722 unsigned long *value)
723 {
724 unsigned char buf[sizeof (unsigned long) + 1];
725 int len;
726 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
727 {
728 if ((buf[0] & _B_CODE) == _B_SINT)
729 (*value) = (buf[0] & _B_VALUE);
730
731 else
732 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value);
733
734 }
735 return len;
736 }
737
738 inline int
739 objc_read_string (struct objc_typed_stream *stream,
740 char **string)
741 {
742 unsigned char buf[sizeof (unsigned int) + 1];
743 int len;
744 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
745 {
746 unsigned long key = 0;
747
748 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
749 {
750 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), &key);
751 len = (*stream->read) (stream->physical, (char*)buf, 1);
752 }
753
754 switch (buf[0]&_B_CODE) {
755 case _B_SSTR:
756 {
757 int length = buf[0]&_B_VALUE;
758 (*string) = (char*)objc_malloc (length + 1);
759 if (key)
760 objc_hash_add (&stream->stream_table, LONG2PTR(key), *string);
761 len = (*stream->read) (stream->physical, *string, length);
762 (*string)[length] = '\0';
763 }
764 break;
765
766 case _B_UCOMM:
767 {
768 char *tmp;
769 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), &key);
770 tmp = objc_hash_value_for_key (stream->stream_table, LONG2PTR (key));
771 *string = objc_malloc (strlen (tmp) + 1);
772 strcpy (*string, tmp);
773 }
774 break;
775
776 case _B_NSTR:
777 {
778 unsigned int nbytes = buf[0]&_B_VALUE;
779 len = __objc_read_nbyte_uint (stream, nbytes, &nbytes);
780 if (len) {
781 (*string) = (char*)objc_malloc (nbytes + 1);
782 if (key)
783 objc_hash_add (&stream->stream_table, LONG2PTR(key), *string);
784 len = (*stream->read) (stream->physical, *string, nbytes);
785 (*string)[nbytes] = '\0';
786 }
787 }
788 break;
789
790 default:
791 objc_error (nil, OBJC_ERR_BAD_DATA,
792 "expected string, got opcode %c\n", (buf[0]&_B_CODE));
793 }
794 }
795
796 return len;
797 }
798
799
800 int
801 objc_read_object (struct objc_typed_stream *stream, id *object)
802 {
803 unsigned char buf[sizeof (unsigned int)];
804 int len;
805 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
806 {
807 SEL read_sel = sel_get_any_uid ("read:");
808 unsigned long key = 0;
809
810 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
811 {
812 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), &key);
813 len = (*stream->read) (stream->physical, (char*)buf, 1);
814 }
815
816 if (buf[0] == (_B_EXT | _BX_OBJECT))
817 {
818 Class class;
819
820 /* get class */
821 len = objc_read_class (stream, &class);
822
823 /* create instance */
824 (*object) = class_create_instance (class);
825
826 /* register? */
827 if (key)
828 objc_hash_add (&stream->object_table, LONG2PTR(key), *object);
829
830 /* send -read: */
831 if (__objc_responds_to (*object, read_sel))
832 (*get_imp (class, read_sel)) (*object, read_sel, stream);
833
834 /* check null-byte */
835 len = (*stream->read) (stream->physical, (char*)buf, 1);
836 if (buf[0] != '\0')
837 objc_error (nil, OBJC_ERR_BAD_DATA,
838 "expected null-byte, got opcode %c", buf[0]);
839 }
840
841 else if ((buf[0]&_B_CODE) == _B_UCOMM)
842 {
843 if (key)
844 objc_error (nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
845 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), &key);
846 (*object) = objc_hash_value_for_key (stream->object_table,
847 LONG2PTR(key));
848 }
849
850 else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
851 {
852 struct objc_list *other;
853 len = objc_read_unsigned_long (stream, &key);
854 other
855 = (struct objc_list *) objc_hash_value_for_key (stream->object_refs,
856 LONG2PTR(key));
857 objc_hash_add (&stream->object_refs, LONG2PTR(key),
858 (void *)list_cons (object, other));
859 }
860
861 else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
862 {
863 if (key)
864 objc_error (nil, OBJC_ERR_BAD_KEY,
865 "cannot register root object...");
866 len = objc_read_object (stream, object);
867 __objc_finish_read_root_object (stream);
868 }
869
870 else
871 objc_error (nil, OBJC_ERR_BAD_DATA,
872 "expected object, got opcode %c", buf[0]);
873 }
874 return len;
875 }
876
877 static int
878 objc_read_class (struct objc_typed_stream *stream, Class *class)
879 {
880 unsigned char buf[sizeof (unsigned int)];
881 int len;
882 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
883 {
884 unsigned long key = 0;
885
886 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
887 {
888 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), &key);
889 len = (*stream->read) (stream->physical, (char*)buf, 1);
890 }
891
892 if (buf[0] == (_B_EXT | _BX_CLASS))
893 {
894 char temp[1] = "";
895 char *class_name = temp;
896 unsigned long version;
897
898 /* get class */
899 len = objc_read_string (stream, &class_name);
900 (*class) = objc_get_class (class_name);
901 objc_free (class_name);
902
903 /* register */
904 if (key)
905 objc_hash_add (&stream->stream_table, LONG2PTR(key), *class);
906
907 objc_read_unsigned_long (stream, &version);
908 objc_hash_add (&stream->class_table,
909 (*class)->name, (void *) ((size_t) version));
910 }
911
912 else if ((buf[0]&_B_CODE) == _B_UCOMM)
913 {
914 if (key)
915 objc_error (nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
916 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), &key);
917 *class = objc_hash_value_for_key (stream->stream_table,
918 LONG2PTR(key));
919 if (! *class)
920 objc_error (nil, OBJC_ERR_BAD_CLASS,
921 "cannot find class for key %lu", key);
922 }
923
924 else
925 objc_error (nil, OBJC_ERR_BAD_DATA,
926 "expected class, got opcode %c", buf[0]);
927 }
928 return len;
929 }
930
931 int
932 objc_read_selector (struct objc_typed_stream *stream, SEL* selector)
933 {
934 unsigned char buf[sizeof (unsigned int)];
935 int len;
936 if ((len = (*stream->read) (stream->physical, (char*)buf, 1)))
937 {
938 unsigned long key = 0;
939
940 if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
941 {
942 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), &key);
943 len = (*stream->read) (stream->physical, (char*)buf, 1);
944 }
945
946 if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
947 {
948 char temp[1] = "";
949 char *selector_name = temp;
950
951 /* get selector */
952 len = objc_read_string (stream, &selector_name);
953 /* To handle NULL selectors */
954 if (0 == strlen (selector_name))
955 {
956 (*selector) = (SEL)0;
957 return 0;
958 }
959 else
960 (*selector) = sel_get_any_uid (selector_name);
961 objc_free (selector_name);
962
963 /* register */
964 if (key)
965 objc_hash_add (&stream->stream_table,
966 LONG2PTR(key), (void *) *selector);
967 }
968
969 else if ((buf[0]&_B_CODE) == _B_UCOMM)
970 {
971 if (key)
972 objc_error (nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
973 len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), &key);
974 (*selector) = objc_hash_value_for_key (stream->stream_table,
975 LONG2PTR(key));
976 }
977
978 else
979 objc_error (nil, OBJC_ERR_BAD_DATA,
980 "expected selector, got opcode %c", buf[0]);
981 }
982 return len;
983 }
984
985 /*
986 ** USER LEVEL FUNCTIONS
987 */
988
989 /*
990 ** Write one object, encoded in TYPE and pointed to by DATA to the
991 ** typed stream STREAM.
992 */
993
994 int
995 objc_write_type (TypedStream *stream, const char *type, const void *data)
996 {
997 switch (*type) {
998 case _C_ID:
999 return objc_write_object (stream, *(id *) data);
1000 break;
1001
1002 case _C_CLASS:
1003 return objc_write_class (stream, *(Class *) data);
1004 break;
1005
1006 case _C_SEL:
1007 return objc_write_selector (stream, *(SEL *) data);
1008 break;
1009
1010 case _C_CHR:
1011 return objc_write_char (stream, *(signed char *) data);
1012 break;
1013
1014 case _C_UCHR:
1015 return objc_write_unsigned_char (stream, *(unsigned char *) data);
1016 break;
1017
1018 case _C_SHT:
1019 return objc_write_short (stream, *(short *) data);
1020 break;
1021
1022 case _C_USHT:
1023 return objc_write_unsigned_short (stream, *(unsigned short *) data);
1024 break;
1025
1026 case _C_INT:
1027 return objc_write_int (stream, *(int *) data);
1028 break;
1029
1030 case _C_UINT:
1031 return objc_write_unsigned_int (stream, *(unsigned int *) data);
1032 break;
1033
1034 case _C_LNG:
1035 return objc_write_long (stream, *(long *) data);
1036 break;
1037
1038 case _C_ULNG:
1039 return objc_write_unsigned_long (stream, *(unsigned long *) data);
1040 break;
1041
1042 case _C_CHARPTR:
1043 return objc_write_string (stream,
1044 *(unsigned char **) data, strlen (*(char **) data));
1045 break;
1046
1047 case _C_ATOM:
1048 return objc_write_string_atomic (stream, *(unsigned char **) data,
1049 strlen (*(char **) data));
1050 break;
1051
1052 case _C_ARY_B:
1053 {
1054 int len = atoi (type + 1);
1055 while (isdigit ((unsigned char) *++type))
1056 ;
1057 return objc_write_array (stream, type, len, data);
1058 }
1059 break;
1060
1061 case _C_STRUCT_B:
1062 {
1063 int acc_size = 0;
1064 int align;
1065 while (*type != _C_STRUCT_E && *type++ != '=')
1066 ; /* skip "<name>=" */
1067 while (*type != _C_STRUCT_E)
1068 {
1069 align = objc_alignof_type (type); /* padd to alignment */
1070 acc_size = ROUND (acc_size, align);
1071 objc_write_type (stream, type, ((char *) data) + acc_size);
1072 acc_size += objc_sizeof_type (type); /* add component size */
1073 type = objc_skip_typespec (type); /* skip component */
1074 }
1075 return 1;
1076 }
1077
1078 default:
1079 {
1080 objc_error (nil, OBJC_ERR_BAD_TYPE,
1081 "objc_write_type: cannot parse typespec: %s\n", type);
1082 return 0;
1083 }
1084 }
1085 }
1086
1087 /*
1088 ** Read one object, encoded in TYPE and pointed to by DATA to the
1089 ** typed stream STREAM. DATA specifies the address of the types to
1090 ** read. Expected type is checked against the type actually present
1091 ** on the stream.
1092 */
1093
1094 int
1095 objc_read_type(TypedStream *stream, const char *type, void *data)
1096 {
1097 char c;
1098 switch (c = *type) {
1099 case _C_ID:
1100 return objc_read_object (stream, (id*)data);
1101 break;
1102
1103 case _C_CLASS:
1104 return objc_read_class (stream, (Class*)data);
1105 break;
1106
1107 case _C_SEL:
1108 return objc_read_selector (stream, (SEL*)data);
1109 break;
1110
1111 case _C_CHR:
1112 return objc_read_char (stream, (char*)data);
1113 break;
1114
1115 case _C_UCHR:
1116 return objc_read_unsigned_char (stream, (unsigned char*)data);
1117 break;
1118
1119 case _C_SHT:
1120 return objc_read_short (stream, (short*)data);
1121 break;
1122
1123 case _C_USHT:
1124 return objc_read_unsigned_short (stream, (unsigned short*)data);
1125 break;
1126
1127 case _C_INT:
1128 return objc_read_int (stream, (int*)data);
1129 break;
1130
1131 case _C_UINT:
1132 return objc_read_unsigned_int (stream, (unsigned int*)data);
1133 break;
1134
1135 case _C_LNG:
1136 return objc_read_long (stream, (long*)data);
1137 break;
1138
1139 case _C_ULNG:
1140 return objc_read_unsigned_long (stream, (unsigned long*)data);
1141 break;
1142
1143 case _C_CHARPTR:
1144 case _C_ATOM:
1145 return objc_read_string (stream, (char**)data);
1146 break;
1147
1148 case _C_ARY_B:
1149 {
1150 int len = atoi (type + 1);
1151 while (isdigit ((unsigned char) *++type))
1152 ;
1153 return objc_read_array (stream, type, len, data);
1154 }
1155 break;
1156
1157 case _C_STRUCT_B:
1158 {
1159 int acc_size = 0;
1160 int align;
1161 while (*type != _C_STRUCT_E && *type++ != '=')
1162 ; /* skip "<name>=" */
1163 while (*type != _C_STRUCT_E)
1164 {
1165 align = objc_alignof_type (type); /* padd to alignment */
1166 acc_size = ROUND (acc_size, align);
1167 objc_read_type (stream, type, ((char*)data)+acc_size);
1168 acc_size += objc_sizeof_type (type); /* add component size */
1169 type = objc_skip_typespec (type); /* skip component */
1170 }
1171 return 1;
1172 }
1173
1174 default:
1175 {
1176 objc_error (nil, OBJC_ERR_BAD_TYPE,
1177 "objc_read_type: cannot parse typespec: %s\n", type);
1178 return 0;
1179 }
1180 }
1181 }
1182
1183 /*
1184 ** Write the object specified by the template TYPE to STREAM. Last
1185 ** arguments specify addresses of values to be written. It might
1186 ** seem surprising to specify values by address, but this is extremely
1187 ** convenient for copy-paste with objc_read_types calls. A more
1188 ** down-to-the-earth cause for this passing of addresses is that values
1189 ** of arbitrary size is not well supported in ANSI C for functions with
1190 ** variable number of arguments.
1191 */
1192
1193 int
1194 objc_write_types (TypedStream *stream, const char *type, ...)
1195 {
1196 va_list args;
1197 const char *c;
1198 int res = 0;
1199
1200 va_start(args, type);
1201
1202 for (c = type; *c; c = objc_skip_typespec (c))
1203 {
1204 switch (*c) {
1205 case _C_ID:
1206 res = objc_write_object (stream, *va_arg (args, id*));
1207 break;
1208
1209 case _C_CLASS:
1210 res = objc_write_class (stream, *va_arg (args, Class*));
1211 break;
1212
1213 case _C_SEL:
1214 res = objc_write_selector (stream, *va_arg (args, SEL*));
1215 break;
1216
1217 case _C_CHR:
1218 res = objc_write_char (stream, *va_arg (args, char*));
1219 break;
1220
1221 case _C_UCHR:
1222 res = objc_write_unsigned_char (stream,
1223 *va_arg (args, unsigned char*));
1224 break;
1225
1226 case _C_SHT:
1227 res = objc_write_short (stream, *va_arg (args, short*));
1228 break;
1229
1230 case _C_USHT:
1231 res = objc_write_unsigned_short (stream,
1232 *va_arg (args, unsigned short*));
1233 break;
1234
1235 case _C_INT:
1236 res = objc_write_int(stream, *va_arg (args, int*));
1237 break;
1238
1239 case _C_UINT:
1240 res = objc_write_unsigned_int(stream, *va_arg (args, unsigned int*));
1241 break;
1242
1243 case _C_LNG:
1244 res = objc_write_long(stream, *va_arg (args, long*));
1245 break;
1246
1247 case _C_ULNG:
1248 res = objc_write_unsigned_long(stream, *va_arg (args, unsigned long*));
1249 break;
1250
1251 case _C_CHARPTR:
1252 {
1253 unsigned char **str = va_arg (args, unsigned char **);
1254 res = objc_write_string (stream, *str, strlen ((char*)*str));
1255 }
1256 break;
1257
1258 case _C_ATOM:
1259 {
1260 unsigned char **str = va_arg (args, unsigned char **);
1261 res = objc_write_string_atomic (stream, *str, strlen ((char*)*str));
1262 }
1263 break;
1264
1265 case _C_ARY_B:
1266 {
1267 int len = atoi (c + 1);
1268 const char *t = c;
1269 while (isdigit ((unsigned char) *++t))
1270 ;
1271 res = objc_write_array (stream, t, len, va_arg (args, void *));
1272 t = objc_skip_typespec (t);
1273 if (*t != _C_ARY_E)
1274 objc_error (nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
1275 }
1276 break;
1277
1278 default:
1279 objc_error (nil, OBJC_ERR_BAD_TYPE,
1280 "objc_write_types: cannot parse typespec: %s\n", type);
1281 }
1282 }
1283 va_end(args);
1284 return res;
1285 }
1286
1287
1288 /*
1289 ** Last arguments specify addresses of values to be read. Expected
1290 ** type is checked against the type actually present on the stream.
1291 */
1292
1293 int
1294 objc_read_types(TypedStream *stream, const char *type, ...)
1295 {
1296 va_list args;
1297 const char *c;
1298 int res = 0;
1299
1300 va_start (args, type);
1301
1302 for (c = type; *c; c = objc_skip_typespec(c))
1303 {
1304 switch (*c) {
1305 case _C_ID:
1306 res = objc_read_object(stream, va_arg (args, id*));
1307 break;
1308
1309 case _C_CLASS:
1310 res = objc_read_class(stream, va_arg (args, Class*));
1311 break;
1312
1313 case _C_SEL:
1314 res = objc_read_selector(stream, va_arg (args, SEL*));
1315 break;
1316
1317 case _C_CHR:
1318 res = objc_read_char(stream, va_arg (args, char*));
1319 break;
1320
1321 case _C_UCHR:
1322 res = objc_read_unsigned_char(stream, va_arg (args, unsigned char*));
1323 break;
1324
1325 case _C_SHT:
1326 res = objc_read_short(stream, va_arg (args, short*));
1327 break;
1328
1329 case _C_USHT:
1330 res = objc_read_unsigned_short(stream, va_arg (args, unsigned short*));
1331 break;
1332
1333 case _C_INT:
1334 res = objc_read_int(stream, va_arg (args, int*));
1335 break;
1336
1337 case _C_UINT:
1338 res = objc_read_unsigned_int(stream, va_arg (args, unsigned int*));
1339 break;
1340
1341 case _C_LNG:
1342 res = objc_read_long(stream, va_arg (args, long*));
1343 break;
1344
1345 case _C_ULNG:
1346 res = objc_read_unsigned_long(stream, va_arg (args, unsigned long*));
1347 break;
1348
1349 case _C_CHARPTR:
1350 case _C_ATOM:
1351 {
1352 char **str = va_arg (args, char **);
1353 res = objc_read_string (stream, str);
1354 }
1355 break;
1356
1357 case _C_ARY_B:
1358 {
1359 int len = atoi (c + 1);
1360 const char *t = c;
1361 while (isdigit ((unsigned char) *++t))
1362 ;
1363 res = objc_read_array (stream, t, len, va_arg (args, void *));
1364 t = objc_skip_typespec (t);
1365 if (*t != _C_ARY_E)
1366 objc_error (nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
1367 }
1368 break;
1369
1370 default:
1371 objc_error (nil, OBJC_ERR_BAD_TYPE,
1372 "objc_read_types: cannot parse typespec: %s\n", type);
1373 }
1374 }
1375 va_end (args);
1376 return res;
1377 }
1378
1379 /*
1380 ** Write an array of COUNT elements of TYPE from the memory address DATA.
1381 ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
1382 */
1383
1384 int
1385 objc_write_array (TypedStream *stream, const char *type,
1386 int count, const void *data)
1387 {
1388 int off = objc_sizeof_type(type);
1389 const char *where = data;
1390
1391 while (count-- > 0)
1392 {
1393 objc_write_type(stream, type, where);
1394 where += off;
1395 }
1396 return 1;
1397 }
1398
1399 /*
1400 ** Read an array of COUNT elements of TYPE into the memory address
1401 ** DATA. The memory pointed to by data is supposed to be allocated
1402 ** by the callee. This is equivalent of
1403 ** objc_read_type (stream, "[N<type>]", data)
1404 */
1405
1406 int
1407 objc_read_array (TypedStream *stream, const char *type,
1408 int count, void *data)
1409 {
1410 int off = objc_sizeof_type(type);
1411 char *where = (char*)data;
1412
1413 while (count-- > 0)
1414 {
1415 objc_read_type(stream, type, where);
1416 where += off;
1417 }
1418 return 1;
1419 }
1420
1421 static int
1422 __objc_fread (FILE *file, char *data, int len)
1423 {
1424 return fread(data, len, 1, file);
1425 }
1426
1427 static int
1428 __objc_fwrite (FILE *file, char *data, int len)
1429 {
1430 return fwrite(data, len, 1, file);
1431 }
1432
1433 static int
1434 __objc_feof (FILE *file)
1435 {
1436 return feof(file);
1437 }
1438
1439 static int
1440 __objc_no_write (FILE *file __attribute__ ((__unused__)),
1441 const char *data __attribute__ ((__unused__)),
1442 int len __attribute__ ((__unused__)))
1443 {
1444 objc_error (nil, OBJC_ERR_NO_WRITE, "TypedStream not open for writing");
1445 return 0;
1446 }
1447
1448 static int
1449 __objc_no_read (FILE *file __attribute__ ((__unused__)),
1450 const char *data __attribute__ ((__unused__)),
1451 int len __attribute__ ((__unused__)))
1452 {
1453 objc_error (nil, OBJC_ERR_NO_READ, "TypedStream not open for reading");
1454 return 0;
1455 }
1456
1457 static int
1458 __objc_read_typed_stream_signature (TypedStream *stream)
1459 {
1460 char buffer[80];
1461 int pos = 0;
1462 do
1463 (*stream->read) (stream->physical, buffer+pos, 1);
1464 while (buffer[pos++] != '\0')
1465 ;
1466 sscanf (buffer, "GNU TypedStream %d", &stream->version);
1467 if (stream->version != OBJC_TYPED_STREAM_VERSION)
1468 objc_error (nil, OBJC_ERR_STREAM_VERSION,
1469 "cannot handle TypedStream version %d", stream->version);
1470 return 1;
1471 }
1472
1473 static int
1474 __objc_write_typed_stream_signature (TypedStream *stream)
1475 {
1476 char buffer[80];
1477 sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
1478 stream->version = OBJC_TYPED_STREAM_VERSION;
1479 (*stream->write) (stream->physical, buffer, strlen (buffer) + 1);
1480 return 1;
1481 }
1482
1483 static void __objc_finish_write_root_object(struct objc_typed_stream *stream)
1484 {
1485 objc_hash_delete (stream->object_table);
1486 stream->object_table = objc_hash_new (64,
1487 (hash_func_type) objc_hash_ptr,
1488 (compare_func_type) objc_compare_ptrs);
1489 }
1490
1491 static void __objc_finish_read_root_object(struct objc_typed_stream *stream)
1492 {
1493 node_ptr node;
1494 SEL awake_sel = sel_get_any_uid ("awake");
1495 cache_ptr free_list = objc_hash_new (64,
1496 (hash_func_type) objc_hash_ptr,
1497 (compare_func_type) objc_compare_ptrs);
1498
1499 /* resolve object forward references */
1500 for (node = objc_hash_next (stream->object_refs, NULL); node;
1501 node = objc_hash_next (stream->object_refs, node))
1502 {
1503 struct objc_list *reflist = node->value;
1504 const void *key = node->key;
1505 id object = objc_hash_value_for_key (stream->object_table, key);
1506 while (reflist)
1507 {
1508 *((id*) reflist->head) = object;
1509 if (objc_hash_value_for_key (free_list,reflist) == NULL)
1510 objc_hash_add (&free_list,reflist,reflist);
1511
1512 reflist = reflist->tail;
1513 }
1514 }
1515
1516 /* apply __objc_free to all objects stored in free_list */
1517 for (node = objc_hash_next (free_list, NULL); node;
1518 node = objc_hash_next (free_list, node))
1519 objc_free ((void *) node->key);
1520
1521 objc_hash_delete (free_list);
1522
1523 /* empty object reference table */
1524 objc_hash_delete (stream->object_refs);
1525 stream->object_refs = objc_hash_new (8, (hash_func_type) objc_hash_ptr,
1526 (compare_func_type) objc_compare_ptrs);
1527
1528 /* call -awake for all objects read */
1529 if (awake_sel)
1530 {
1531 for (node = objc_hash_next (stream->object_table, NULL); node;
1532 node = objc_hash_next (stream->object_table, node))
1533 {
1534 id object = node->value;
1535 if (__objc_responds_to (object, awake_sel))
1536 (*objc_msg_lookup (object, awake_sel)) (object, awake_sel);
1537 }
1538 }
1539
1540 /* empty object table */
1541 objc_hash_delete (stream->object_table);
1542 stream->object_table = objc_hash_new(64,
1543 (hash_func_type)objc_hash_ptr,
1544 (compare_func_type)objc_compare_ptrs);
1545 }
1546
1547 /*
1548 ** Open the stream PHYSICAL in MODE
1549 */
1550
1551 TypedStream *
1552 objc_open_typed_stream (FILE *physical, int mode)
1553 {
1554 TypedStream *s = (TypedStream *) objc_malloc (sizeof (TypedStream));
1555
1556 s->mode = mode;
1557 s->physical = physical;
1558 s->stream_table = objc_hash_new (64,
1559 (hash_func_type) objc_hash_ptr,
1560 (compare_func_type) objc_compare_ptrs);
1561 s->object_table = objc_hash_new (64,
1562 (hash_func_type) objc_hash_ptr,
1563 (compare_func_type) objc_compare_ptrs);
1564 s->eof = (objc_typed_eof_func) __objc_feof;
1565 s->flush = (objc_typed_flush_func) fflush;
1566 s->writing_root_p = 0;
1567 if (mode == OBJC_READONLY)
1568 {
1569 s->class_table
1570 = objc_hash_new (8, (hash_func_type) objc_hash_string,
1571 (compare_func_type) objc_compare_strings);
1572 s->object_refs = objc_hash_new (8, (hash_func_type) objc_hash_ptr,
1573 (compare_func_type) objc_compare_ptrs);
1574 s->read = (objc_typed_read_func) __objc_fread;
1575 s->write = (objc_typed_write_func) __objc_no_write;
1576 __objc_read_typed_stream_signature (s);
1577 }
1578 else if (mode == OBJC_WRITEONLY)
1579 {
1580 s->class_table = 0;
1581 s->object_refs = 0;
1582 s->read = (objc_typed_read_func) __objc_no_read;
1583 s->write = (objc_typed_write_func) __objc_fwrite;
1584 __objc_write_typed_stream_signature (s);
1585 }
1586 else
1587 {
1588 objc_close_typed_stream (s);
1589 return NULL;
1590 }
1591 s->type = OBJC_FILE_STREAM;
1592 return s;
1593 }
1594
1595 /*
1596 ** Open the file named by FILE_NAME in MODE
1597 */
1598
1599 TypedStream*
1600 objc_open_typed_stream_for_file (const char *file_name, int mode)
1601 {
1602 FILE *file = NULL;
1603 TypedStream *s;
1604
1605 if (mode == OBJC_READONLY)
1606 file = fopen (file_name, "r");
1607 else
1608 file = fopen (file_name, "w");
1609
1610 if (file)
1611 {
1612 s = objc_open_typed_stream (file, mode);
1613 if (s)
1614 s->type |= OBJC_MANAGED_STREAM;
1615 return s;
1616 }
1617 else
1618 return NULL;
1619 }
1620
1621 /*
1622 ** Close STREAM freeing the structure it self. If it was opened with
1623 ** objc_open_typed_stream_for_file, the file will also be closed.
1624 */
1625
1626 void
1627 objc_close_typed_stream (TypedStream *stream)
1628 {
1629 if (stream->mode == OBJC_READONLY)
1630 {
1631 __objc_finish_read_root_object (stream); /* Just in case... */
1632 objc_hash_delete (stream->class_table);
1633 objc_hash_delete (stream->object_refs);
1634 }
1635
1636 objc_hash_delete (stream->stream_table);
1637 objc_hash_delete (stream->object_table);
1638
1639 if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
1640 fclose ((FILE *)stream->physical);
1641
1642 objc_free(stream);
1643 }
1644
1645 BOOL
1646 objc_end_of_typed_stream (TypedStream *stream)
1647 {
1648 return (*stream->eof) (stream->physical);
1649 }
1650
1651 void
1652 objc_flush_typed_stream (TypedStream *stream)
1653 {
1654 (*stream->flush) (stream->physical);
1655 }
1656
1657 long
1658 objc_get_stream_class_version (TypedStream *stream, Class class)
1659 {
1660 if (stream->class_table)
1661 return PTR2LONG(objc_hash_value_for_key (stream->class_table,
1662 class->name));
1663 else
1664 return class_get_version (class);
1665 }
1666