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