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