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