]>
Commit | Line | Data |
---|---|---|
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 | 5 | This file is part of GCC. |
88e17b57 | 6 | |
6c82ad25 | 7 | GCC is free software; you can redistribute it and/or modify it under the |
88e17b57 | 8 | terms of the GNU General Public License as published by the Free Software |
748086b7 | 9 | Foundation; either version 3, or (at your option) any later version. |
88e17b57 | 10 | |
6c82ad25 | 11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
88e17b57 BE |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
13 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
14 | details. | |
15 | ||
748086b7 JJ |
16 | Under Section 7 of GPL version 3, you are granted additional |
17 | permissions described in the GCC Runtime Library Exception, version | |
18 | 3.1, as published by the Free Software Foundation. | |
88e17b57 | 19 | |
748086b7 JJ |
20 | You should have received a copy of the GNU General Public License and |
21 | a copy of the GCC Runtime Library Exception along with this program; | |
22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | <http://www.gnu.org/licenses/>. */ | |
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 | 38 | extern 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 | ||
49 | static int | |
40165636 | 50 | objc_read_class (struct objc_typed_stream *stream, Class *class); |
88e17b57 | 51 | |
40165636 | 52 | int objc_sizeof_type (const char *type); |
88e17b57 BE |
53 | |
54 | static int | |
40165636 | 55 | objc_write_use_common (struct objc_typed_stream *stream, unsigned long key); |
88e17b57 BE |
56 | |
57 | static int | |
40165636 | 58 | objc_write_register_common (struct objc_typed_stream *stream, |
88e17b57 BE |
59 | unsigned long key); |
60 | ||
61 | static int | |
40165636 RB |
62 | objc_write_class (struct objc_typed_stream *stream, |
63 | struct objc_class *class); | |
88e17b57 | 64 | |
40165636 | 65 | const char *objc_skip_type (const char *type); |
88e17b57 | 66 | |
40165636 RB |
67 | static void __objc_finish_write_root_object (struct objc_typed_stream *); |
68 | static void __objc_finish_read_root_object (struct objc_typed_stream *); | |
88e17b57 | 69 | |
435317e2 | 70 | static 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 | ||
86 | int | |
40165636 | 87 | objc_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 | 95 | static 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 | ||
108 | int | |
40165636 | 109 | objc_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 | 116 | static 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 | ||
145 | int | |
40165636 | 146 | objc_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 | 154 | static 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 | ||
164 | int | |
40165636 | 165 | objc_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 | 173 | static 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 | ||
202 | int | |
40165636 | 203 | objc_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 | 210 | static 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 | ||
220 | int | |
40165636 | 221 | objc_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 | 228 | static 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 | ||
257 | int | |
40165636 | 258 | objc_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 | 266 | static 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 | ||
276 | int | |
40165636 | 277 | objc_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 | ||
285 | int | |
40165636 RB |
286 | objc_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 | ||
304 | int | |
40165636 RB |
305 | objc_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 | ||
322 | static int | |
40165636 | 323 | objc_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 | ||
341 | static int | |
40165636 | 342 | objc_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 | 359 | static 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 | 374 | int |
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 | ||
390 | int | |
40165636 | 391 | objc_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 | ||
401 | int | |
40165636 | 402 | objc_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 | ||
418 | int | |
40165636 | 419 | objc_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 | 439 | 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 | ||
449 | static int | |
40165636 RB |
450 | objc_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 | 468 | 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 | ||
480 | int | |
40165636 | 481 | objc_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 | 511 | int |
40165636 | 512 | objc_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 | 537 | int |
40165636 | 538 | objc_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 | 557 | int |
40165636 | 558 | objc_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 | 584 | int |
40165636 RB |
585 | objc_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 | 611 | int |
40165636 | 612 | objc_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 | 638 | int |
40165636 | 639 | objc_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 | 665 | int |
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 | 684 | int |
40165636 RB |
685 | objc_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 | ||
702 | int | |
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 | 721 | int |
40165636 RB |
722 | objc_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 | 739 | int |
40165636 RB |
740 | objc_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 | ||
800 | int | |
40165636 | 801 | objc_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 | ||
874 | static int | |
40165636 | 875 | objc_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 | ||
926 | int | |
40165636 | 927 | objc_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 | ||
988 | int | |
40165636 | 989 | objc_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 | ||
1087 | int | |
40165636 | 1088 | objc_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 | ||
1185 | int | |
40165636 | 1186 | objc_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 | ||
1284 | int | |
40165636 | 1285 | objc_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 | ||
1374 | int | |
40165636 RB |
1375 | objc_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 | ||
1396 | int | |
40165636 RB |
1397 | objc_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 | ||
1411 | static int | |
40165636 | 1412 | __objc_fread (FILE *file, char *data, int len) |
88e17b57 BE |
1413 | { |
1414 | return fread(data, len, 1, file); | |
1415 | } | |
1416 | ||
1417 | static int | |
40165636 | 1418 | __objc_fwrite (FILE *file, char *data, int len) |
88e17b57 BE |
1419 | { |
1420 | return fwrite(data, len, 1, file); | |
1421 | } | |
1422 | ||
1423 | static int | |
40165636 | 1424 | __objc_feof (FILE *file) |
88e17b57 BE |
1425 | { |
1426 | return feof(file); | |
1427 | } | |
1428 | ||
1429 | static 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 | ||
1438 | static 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 | ||
1447 | static 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 | ||
1462 | static 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 | 1472 | static 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 | 1480 | static 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 |
1540 | TypedStream * |
1541 | objc_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 | ||
1588 | TypedStream* | |
40165636 | 1589 | objc_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 | ||
1615 | void | |
40165636 | 1616 | objc_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 | ||
1634 | BOOL | |
40165636 | 1635 | objc_end_of_typed_stream (TypedStream *stream) |
88e17b57 | 1636 | { |
40165636 | 1637 | return (*stream->eof) (stream->physical); |
88e17b57 BE |
1638 | } |
1639 | ||
1640 | void | |
40165636 | 1641 | objc_flush_typed_stream (TypedStream *stream) |
88e17b57 | 1642 | { |
40165636 | 1643 | (*stream->flush) (stream->physical); |
88e17b57 BE |
1644 | } |
1645 | ||
1646 | long | |
40165636 | 1647 | objc_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 |