Annotation of gcc/objc/archive.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.