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