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