OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libobjc/] [archive.c] - Blame information for rev 22

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.