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

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...) \
1.1.1.2 ! root       37:  { fprintf(stderr, "archiving: "); \
1.1       root       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:        {
1.1.1.2 ! root      620:          char *tmp;
        !           621:          len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), &key);
        !           622:          tmp = hash_value_for_key (stream->stream_table, (void*)key);
        !           623:          *string = __objc_xmalloc (strlen (tmp) + 1);
        !           624:          strcpy (*string, tmp);
1.1       root      625:        }
                    626:        break;
                    627: 
                    628:       case _B_NSTR:
                    629:        {
                    630:          unsigned int nbytes = buf[0]&_B_VALUE;
                    631:          len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
                    632:          if (len) {
1.1.1.2 ! root      633:            (*string) = (char*)__objc_xmalloc(nbytes+1);
1.1       root      634:            if (key)
                    635:              hash_add (&stream->stream_table, (void*)key, *string);
1.1.1.2 ! root      636:            len = (*stream->read)(stream->physical, *string, nbytes);
1.1       root      637:            (*string)[nbytes] = '\0';
                    638:          }
                    639:        }
                    640:        break;
                    641:        
                    642:       default:
                    643:        __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE));
                    644:       }
                    645:     }
                    646: 
                    647:   return len;
                    648: }
                    649: 
                    650: 
                    651: int
                    652: objc_read_object (struct objc_typed_stream* stream, id* object)
                    653: {
                    654:   unsigned char buf[sizeof (unsigned int)];
                    655:   int len;
                    656:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    657:     {
                    658:       SEL read_sel = sel_get_uid ("read:");
                    659:       unsigned int key = 0;
                    660: 
                    661:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register common */
                    662:        {
                    663:          len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
                    664:          len = (*stream->read)(stream->physical, buf, 1);
                    665:        }
                    666: 
                    667:       if (buf[0] == (_B_EXT | _BX_OBJECT))
                    668:        {
                    669:          Class* class;
                    670: 
                    671:          /* get class */
                    672:          len = objc_read_class (stream, &class);
                    673: 
                    674:          /* create instance */
                    675:          (*object) = class_create_instance(class);
                    676: 
                    677:          /* register? */
                    678:          if (key)
                    679:            hash_add (&stream->object_table, (void*)key, *object);
                    680: 
                    681:          /* send -read: */
                    682:          if (__objc_responds_to (*object, read_sel))
                    683:            (*get_imp(class, read_sel))(*object, read_sel, stream);
                    684: 
                    685:          /* check null-byte */
                    686:          len = (*stream->read)(stream->physical, buf, 1);
                    687:          if (buf[0] != '\0')
                    688:            __objc_fatal("expected null-byte, got opcode %c", buf[0]);
                    689:        }
                    690: 
                    691:       else if ((buf[0]&_B_CODE) == _B_UCOMM)
                    692:        {
                    693:          if (key)
                    694:            __objc_fatal("cannot register use upcode...");
                    695:          len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
                    696:          (*object) = hash_value_for_key (stream->object_table, (void*)key);
                    697:        }
                    698: 
                    699:       else if (buf[0] == (_B_EXT | _BX_OBJREF))        /* a forward reference */
                    700:        {
                    701:          struct objc_list* other;
                    702:          len = objc_read_unsigned_int (stream, &key);
                    703:          other = (struct objc_list*)hash_value_for_key (stream->object_refs, (void*)key);
                    704:          hash_add (&stream->object_refs, (void*)key, (void*)list_cons(object, other));
                    705:        }
                    706: 
                    707:       else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
                    708:        {
                    709:          if (key)
                    710:            __objc_fatal("cannot register root object...");
                    711:          len = objc_read_object (stream, object);
                    712:          __objc_finish_read_root_object (stream);
                    713:        }
                    714: 
                    715:       else
                    716:        __objc_fatal("expected object, got opcode %c", buf[0]);
                    717:     }
                    718:   return len;
                    719: }
                    720: 
                    721: static int
                    722: objc_read_class (struct objc_typed_stream* stream, Class** class)
                    723: {
                    724:   unsigned char buf[sizeof (unsigned int)];
                    725:   int len;
                    726:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    727:     {
                    728:       unsigned int key = 0;
                    729: 
                    730:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
                    731:        {
                    732:          len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
                    733:          len = (*stream->read)(stream->physical, buf, 1);
                    734:        }
                    735: 
                    736:       if (buf[0] == (_B_EXT | _BX_CLASS))
                    737:        {
                    738:          char* class_name;
                    739:          int version;
                    740: 
                    741:          /* get class */
                    742:          len = objc_read_string (stream, &class_name);
                    743:          (*class) = objc_get_class(class_name);
                    744:          free (class_name);
                    745: 
                    746:          /* register */
                    747:          if (key)
                    748:            hash_add (&stream->stream_table, (void*)key, *class);
                    749: 
                    750:          objc_read_unsigned_int(stream, &version);
                    751:          hash_add (&stream->class_table, (*class)->name, (void*)version);
                    752:        }
                    753: 
                    754:       else if ((buf[0]&_B_CODE) == _B_UCOMM)
                    755:        {
                    756:          if (key)
                    757:            __objc_fatal("cannot register use upcode...");
                    758:          len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
                    759:          (*class) = hash_value_for_key (stream->stream_table, (void*)key);
                    760:          if (!*class)
                    761:            __objc_fatal("cannot find class for key %x", key);
                    762:        }
                    763: 
                    764:       else
                    765:        __objc_fatal("expected class, got opcode %c", buf[0]);
                    766:     }
                    767:   return len;
                    768: }
                    769: 
                    770: int
                    771: objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
                    772: {
                    773:   unsigned char buf[sizeof (unsigned int)];
                    774:   int len;
                    775:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    776:     {
                    777:       unsigned int key = 0;
                    778: 
                    779:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
                    780:        {
                    781:          len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
                    782:          len = (*stream->read)(stream->physical, buf, 1);
                    783:        }
                    784: 
                    785:       if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
                    786:        {
                    787:          char* selector_name;
                    788: 
                    789:          /* get selector */
                    790:          len = objc_read_string (stream, &selector_name);
                    791:          (*selector) = sel_get_uid(selector_name);
                    792:          free (selector_name);
                    793: 
                    794:          /* register */
                    795:          if (key)
                    796:            hash_add (&stream->stream_table, (void*)key, *selector);
                    797:        }
                    798: 
                    799:       else if ((buf[0]&_B_CODE) == _B_UCOMM)
                    800:        {
                    801:          if (key)
                    802:            __objc_fatal("cannot register use upcode...");
                    803:          len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
                    804:          (*selector) = hash_value_for_key (stream->stream_table, (void*)key);
                    805:        }
                    806: 
                    807:       else
                    808:        __objc_fatal("expected selector, got opcode %c", buf[0]);
                    809:     }
                    810:   return len;
                    811: }
                    812: 
                    813: static int
                    814: objc_sizeof_type(const char* type)
                    815: {
                    816:   switch(*type) {
                    817:   case _C_ID: return sizeof(id);
                    818:     break;
                    819: 
                    820:   case _C_CLASS:
                    821:     return sizeof(Class*);
                    822:     break;
                    823: 
                    824:   case _C_SEL:
                    825:     return sizeof(SEL);
                    826:     break;
                    827: 
                    828:   case _C_CHR:
                    829:     return sizeof(char);
                    830:     break;
                    831:     
                    832:   case _C_UCHR:
                    833:     return sizeof(unsigned char);
                    834:     break;
                    835: 
                    836:   case _C_SHT:
                    837:     return sizeof(short);
                    838:     break;
                    839: 
                    840:   case _C_USHT:
                    841:     return sizeof(unsigned short);
                    842:     break;
                    843: 
                    844:   case _C_INT:
                    845:   case _C_LNG:
                    846:     return sizeof(int);
                    847:     break;
                    848: 
                    849:   case _C_UINT:
                    850:   case _C_ULNG:
                    851:     return sizeof(unsigned int);
                    852:     break;
                    853: 
                    854:   case _C_ATOM:
                    855:   case _C_CHARPTR:
                    856:     return sizeof(char*);
                    857:     break;
                    858: 
                    859:   default:
1.1.1.2 ! root      860:     fprintf(stderr, "objc_sizeof_type: cannot parse typespec: %s\n", type);
1.1       root      861:     abort();
                    862:   }
                    863: }
                    864: 
                    865: 
                    866: static const char*
                    867: __objc_skip_type (const char* type)
                    868: {
                    869:   switch (*type) {
                    870:   case _C_ID:
                    871:   case _C_CLASS:
                    872:   case _C_SEL:
                    873:   case _C_CHR:
                    874:   case _C_UCHR:
                    875:   case _C_CHARPTR:
                    876:   case _C_ATOM:
                    877:   case _C_SHT:
                    878:   case _C_USHT:
                    879:   case _C_INT:
                    880:   case _C_UINT:
                    881:   case _C_LNG:
                    882:   case _C_ULNG:
                    883:   case _C_FLT:
                    884:   case _C_DBL:
                    885:     return ++type;
                    886:     break;
                    887: 
                    888:   case _C_ARY_B:
                    889:     while(isdigit(*++type));
                    890:     type = __objc_skip_type(type);
                    891:     if (*type == _C_ARY_E)
                    892:       return ++type;
                    893:     else
                    894:       __objc_fatal("cannot parse typespec: %s", type);
                    895:     break;
                    896: 
                    897:   default:
1.1.1.2 ! root      898:     fprintf(stderr, "__objc_skip_type: cannot parse typespec: %s\n", type);
1.1       root      899:     abort();
                    900:   }
                    901: }
                    902: 
                    903: /*
                    904: ** USER LEVEL FUNCTIONS
                    905: */
                    906: 
                    907: /*
                    908: ** Write one object, encoded in TYPE and pointed to by DATA to the
                    909: ** typed stream STREAM.  
                    910: */
                    911: 
                    912: int
                    913: objc_write_type(TypedStream* stream, const char* type, const void* data)
                    914: {
                    915:   switch(*type) {
                    916:   case _C_ID:
                    917:     return objc_write_object (stream, *(id*)data);
                    918:     break;
                    919: 
                    920:   case _C_CLASS:
                    921:     return objc_write_class (stream, *(Class**)data);
                    922:     break;
                    923: 
                    924:   case _C_SEL:
                    925:     return objc_write_selector (stream, *(SEL*)data);
                    926:     break;
                    927: 
                    928:   case _C_CHR:
                    929:     return objc_write_char(stream, *(char*)data);
                    930:     break;
                    931:     
                    932:   case _C_UCHR:
                    933:     return objc_write_unsigned_char(stream, *(unsigned char*)data);
                    934:     break;
                    935: 
                    936:   case _C_SHT:
                    937:     return objc_write_short(stream, *(short*)data);
                    938:     break;
                    939: 
                    940:   case _C_USHT:
                    941:     return objc_write_unsigned_short(stream, *(unsigned short*)data);
                    942:     break;
                    943: 
                    944:   case _C_INT:
                    945:   case _C_LNG:
                    946:     return objc_write_int(stream, *(int*)data);
                    947:     break;
                    948: 
                    949:   case _C_UINT:
                    950:   case _C_ULNG:
                    951:     return objc_write_unsigned_int(stream, *(unsigned int*)data);
                    952:     break;
                    953: 
                    954:   case _C_CHARPTR:
1.1.1.2 ! root      955:     return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
1.1       root      956:     break;
                    957: 
                    958:   case _C_ATOM:
1.1.1.2 ! root      959:     return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data));
1.1       root      960:     break;
                    961: 
                    962:   case _C_ARY_B:
                    963:     {
                    964:       int len = atoi(type+1);
                    965:       while (isdigit(*++type));
                    966:       return objc_write_array (stream, type, len, data);
                    967:     }
                    968:     break; 
                    969: 
                    970:   default:
                    971:     fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
                    972:     abort();
                    973:   }
                    974: }
                    975: 
                    976: /*
                    977: ** Read one object, encoded in TYPE and pointed to by DATA to the
                    978: ** typed stream STREAM.  DATA specifies the address of the types to
                    979: ** read.  Expected type is checked against the type actually present
                    980: ** on the stream. 
                    981: */
                    982: 
                    983: int
                    984: objc_read_type(TypedStream* stream, const char* type, void* data)
                    985: {
                    986:   char c;
                    987:   switch(c = *type) {
                    988:   case _C_ID:
                    989:     return objc_read_object (stream, (id*)data);
                    990:     break;
                    991: 
                    992:   case _C_CLASS:
                    993:     return objc_read_class (stream, (Class**)data);
                    994:     break;
                    995: 
                    996:   case _C_SEL:
                    997:     return objc_read_selector (stream, (SEL*)data);
                    998:     break;
                    999: 
                   1000:   case _C_CHR:
                   1001:     return objc_read_char (stream, (char*)data);
                   1002:     break;
                   1003:     
                   1004:   case _C_UCHR:
                   1005:     return objc_read_unsigned_char (stream, (unsigned char*)data);
                   1006:     break;
                   1007: 
                   1008:   case _C_SHT:
                   1009:     return objc_read_short (stream, (short*)data);
                   1010:     break;
                   1011: 
                   1012:   case _C_USHT:
                   1013:     return objc_read_unsigned_short (stream, (unsigned short*)data);
                   1014:     break;
                   1015: 
                   1016:   case _C_INT:
                   1017:   case _C_LNG:
                   1018:     return objc_read_int (stream, (int*)data);
                   1019:     break;
                   1020: 
                   1021:   case _C_UINT:
                   1022:   case _C_ULNG:
                   1023:     return objc_read_unsigned_int (stream, (unsigned int*)data);
                   1024:     break;
                   1025: 
                   1026:   case _C_CHARPTR:
                   1027:   case _C_ATOM:
                   1028:     return objc_read_string (stream, (char**)data);
                   1029:     break;
                   1030: 
                   1031:   case _C_ARY_B:
                   1032:     {
                   1033:       int len = atoi(type+1);
                   1034:       while (isdigit(*++type));
                   1035:       return objc_read_array (stream, type, len, data);
                   1036:     }
                   1037:     break; 
                   1038: 
                   1039:   default:
1.1.1.2 ! root     1040:     fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
1.1       root     1041:     abort();
                   1042:   }
                   1043: }
                   1044: 
                   1045: /*
                   1046: ** Write the object specified by the template TYPE to STREAM.  Last
                   1047: ** arguments specify addresses of values to be written.  It might 
                   1048: ** seem surprising to specify values by address, but this is extremely
                   1049: ** convenient for copy-paste with objc_read_types calls.  A more
                   1050: ** down-to-the-earth cause for this passing of addresses is that values
                   1051: ** of arbitrary size is not well supported in ANSI C for functions with
                   1052: ** variable number of arguments.
                   1053: */
                   1054: 
                   1055: int 
                   1056: objc_write_types (TypedStream* stream, const char* type, ...)
                   1057: {
                   1058:   va_list args;
                   1059:   const char *c;
                   1060:   int res = 0;
                   1061: 
                   1062:   va_start(args, type);
                   1063: 
                   1064:   for (c = type; *c; c = __objc_skip_type (c))
                   1065:     {
                   1066:       switch(*c) {
                   1067:       case _C_ID:
                   1068:        res = objc_write_object (stream, *va_arg (args, id*));
                   1069:        break;
                   1070: 
                   1071:       case _C_CLASS:
                   1072:        res = objc_write_class (stream, *va_arg(args, Class**));
                   1073:        break;
                   1074: 
                   1075:       case _C_SEL:
                   1076:        res = objc_write_selector (stream, *va_arg(args, SEL*));
                   1077:        break;
                   1078:        
                   1079:       case _C_CHR:
                   1080:        res = objc_write_char (stream, *va_arg (args, char*));
                   1081:        break;
                   1082:        
                   1083:       case _C_UCHR:
                   1084:        res = objc_write_unsigned_char (stream,
                   1085:                                        *va_arg (args, unsigned char*));
                   1086:        break;
                   1087:        
                   1088:       case _C_SHT:
                   1089:        res = objc_write_short (stream, *va_arg(args, short*));
                   1090:        break;
                   1091: 
                   1092:       case _C_USHT:
                   1093:        res = objc_write_unsigned_short (stream,
                   1094:                                         *va_arg(args, unsigned short*));
                   1095:        break;
                   1096: 
                   1097:       case _C_INT:
                   1098:       case _C_LNG:
                   1099:        res = objc_write_int(stream, *va_arg(args, int*));
                   1100:        break;
                   1101:        
                   1102:       case _C_UINT:
                   1103:       case _C_ULNG:
                   1104:        res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
                   1105:        break;
                   1106: 
                   1107:       case _C_CHARPTR:
                   1108:        {
1.1.1.2 ! root     1109:          char** str = va_arg(args, char**);
        !          1110:          res = objc_write_string (stream, *str, strlen(*str));
1.1       root     1111:        }
                   1112:        break;
                   1113: 
                   1114:       case _C_ATOM:
                   1115:        {
1.1.1.2 ! root     1116:          char** str = va_arg(args, char**);
        !          1117:          res = objc_write_string_atomic (stream, *str, strlen(*str));
1.1       root     1118:        }
                   1119:        break;
                   1120: 
                   1121:       case _C_ARY_B:
                   1122:        {
                   1123:          int len = atoi(c+1);
                   1124:          const char* t = c;
                   1125:          while (isdigit(*++t));
                   1126:          res = objc_write_array (stream, t, len, va_arg(args, void*));
                   1127:          t = __objc_skip_type (t);
                   1128:          if (*t != _C_ARY_E)
                   1129:            __objc_fatal("expected `]', got: %s", t);
                   1130:        }
                   1131:        break; 
                   1132:        
                   1133:       default:
1.1.1.2 ! root     1134:        fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type);
1.1       root     1135:        abort();
                   1136:       }
                   1137:     }
                   1138:   va_end(args);
                   1139:   return res;
                   1140: }
                   1141: 
                   1142: 
                   1143: /* 
                   1144: ** Last arguments specify addresses of values to be read.  Expected
                   1145: ** type is checked against the type actually present on the stream. 
                   1146: */
                   1147: 
                   1148: int 
                   1149: objc_read_types(TypedStream* stream, const char* type, ...)
                   1150: {
                   1151:   va_list args;
                   1152:   const char *c;
                   1153:   int res = 0;
                   1154: 
                   1155:   va_start(args, type);
                   1156: 
                   1157:   for (c = type; *c; c = __objc_skip_type(c))
                   1158:     {
                   1159:       switch(*c) {
                   1160:       case _C_ID:
                   1161:        res = objc_read_object(stream, va_arg(args, id*));
                   1162:        break;
                   1163: 
                   1164:       case _C_CLASS:
                   1165:        res = objc_read_class(stream, va_arg(args, Class**));
                   1166:        break;
                   1167: 
                   1168:       case _C_SEL:
                   1169:        res = objc_read_selector(stream, va_arg(args, SEL*));
                   1170:        break;
                   1171:        
                   1172:       case _C_CHR:
                   1173:        res = objc_read_char(stream, va_arg(args, char*));
                   1174:        break;
                   1175:        
                   1176:       case _C_UCHR:
                   1177:        res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
                   1178:        break;
                   1179:        
                   1180:       case _C_SHT:
                   1181:        res = objc_read_short(stream, va_arg(args, short*));
                   1182:        break;
                   1183: 
                   1184:       case _C_USHT:
                   1185:        res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
                   1186:        break;
                   1187: 
                   1188:       case _C_INT:
                   1189:       case _C_LNG:
                   1190:        res = objc_read_int(stream, va_arg(args, int*));
                   1191:        break;
                   1192:        
                   1193:       case _C_UINT:
                   1194:       case _C_ULNG:
                   1195:        res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
                   1196:        break;
                   1197: 
                   1198:       case _C_CHARPTR:
                   1199:       case _C_ATOM:
                   1200:        {
                   1201:          char** str = va_arg(args, char**);
                   1202:          res = objc_read_string (stream, str);
                   1203:        }
                   1204:        break;
                   1205: 
                   1206:       case _C_ARY_B:
                   1207:        {
                   1208:          int len = atoi(c+1);
                   1209:          const char* t = c;
                   1210:          while (isdigit(*++t));
                   1211:          res = objc_read_array (stream, t, len, va_arg(args, void*));
                   1212:          t = __objc_skip_type (t);
                   1213:          if (*t != _C_ARY_E)
                   1214:            __objc_fatal("expected `]', got: %s", t);
                   1215:        }
                   1216:        break; 
                   1217:        
                   1218:       default:
1.1.1.2 ! root     1219:        fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
1.1       root     1220:        abort();
                   1221:       }
                   1222:     }
                   1223:   va_end(args);
                   1224:   return res;
                   1225: }
                   1226: 
                   1227: /*
                   1228: ** Write an array of COUNT elements of TYPE from the memory address DATA.
                   1229: ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
                   1230: */
                   1231: 
                   1232: int
                   1233: objc_write_array (TypedStream* stream, const char* type,
                   1234:                  int count, const void* data)
                   1235: {
                   1236:   int off = objc_sizeof_type(type);
                   1237:   const char* where = data;
                   1238: 
                   1239:   while (count-- > 0)
                   1240:     {
                   1241:       objc_write_type(stream, type, where);
                   1242:       where += off;
                   1243:     }
                   1244:   return 1;
                   1245: }
                   1246: 
                   1247: /*
                   1248: ** Read an array of COUNT elements of TYPE into the memory address
                   1249: ** DATA.  The memory pointed to by data is supposed to be allocated
                   1250: ** by the callee.  This is equivalent of 
                   1251: **   objc_read_type (stream, "[N<type>]", data)
                   1252: */
                   1253: 
                   1254: int
                   1255: objc_read_array (TypedStream* stream, const char* type,
                   1256:                 int count, void* data)
                   1257: {
                   1258:   int off = objc_sizeof_type(type);
                   1259:   char* where = (char*)data;
                   1260: 
                   1261:   while (count-- > 0)
                   1262:     {
                   1263:       objc_read_type(stream, type, where);
                   1264:       where += off;
                   1265:     }
                   1266:   return 1;
                   1267: }
                   1268: 
                   1269: static int 
                   1270: __objc_fread(FILE* file, char* data, int len)
                   1271: {
                   1272:   return fread(data, len, 1, file);
                   1273: }
                   1274: 
                   1275: static int 
                   1276: __objc_fwrite(FILE* file, char* data, int len)
                   1277: {
                   1278:   return fwrite(data, len, 1, file);
                   1279: }
                   1280: 
                   1281: static int
                   1282: __objc_feof(FILE* file)
                   1283: {
                   1284:   return feof(file);
                   1285: }
                   1286: 
                   1287: static int 
                   1288: __objc_no_write(FILE* file, char* data, int len)
                   1289: {
                   1290:   __objc_fatal ("TypedStream not open for writing");
                   1291: }
                   1292: 
                   1293: static int 
                   1294: __objc_no_read(FILE* file, char* data, int len)
                   1295: {
                   1296:   __objc_fatal ("TypedStream not open for reading");
                   1297: }
                   1298: 
                   1299: static int
                   1300: __objc_read_typed_stream_signature (TypedStream* stream)
                   1301: {
                   1302:   char buffer[80];
                   1303:   int pos = 0;
                   1304:   do
                   1305:     (*stream->read)(stream->physical, buffer+pos, 1);
                   1306:   while (buffer[pos++] != '\0');
                   1307:   sscanf (buffer, "GNU TypedStream %d", &stream->version);
                   1308:   if (stream->version != OBJC_TYPED_STREAM_VERSION)
                   1309:     __objc_fatal ("cannot handle TypedStream version %d", stream->version);
                   1310:   return 1;
                   1311: }
                   1312: 
                   1313: static int
                   1314: __objc_write_typed_stream_signature (TypedStream* stream)
                   1315: {
                   1316:   char buffer[80];
                   1317:   sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
                   1318:   stream->version = OBJC_TYPED_STREAM_VERSION;
                   1319:   (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
                   1320:   return 1;
                   1321: }
                   1322: 
                   1323: static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
                   1324: {
                   1325:   hash_delete (stream->object_table);
                   1326:   stream->object_table = hash_new(64,
                   1327:                                  (hash_func_type)hash_ptr,
                   1328:                                  (compare_func_type)compare_ptrs);
                   1329: }
                   1330: 
                   1331: static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
                   1332: {
                   1333:   node_ptr node;
                   1334:   SEL awake_sel = sel_get_uid ("awake");
                   1335: 
                   1336:   /* resolve object forward references */
                   1337:   for (node = hash_next (stream->object_refs, NULL); node;
                   1338:        node = hash_next (stream->object_refs, node))
                   1339:     {
                   1340:       struct objc_list* reflist = node->value;
                   1341:       const void* key = node->key;
                   1342:       id object = hash_value_for_key (stream->object_table, key);
                   1343:       while(reflist)
                   1344:        {
                   1345:          *((id*)reflist->head) = object;
                   1346:          reflist = reflist->tail;
                   1347:        }
                   1348:       list_free (node->value);
                   1349:     }
                   1350: 
                   1351:   /* empty object reference table */
                   1352:   hash_delete (stream->object_refs);
                   1353:   stream->object_refs = hash_new(8, (hash_func_type)hash_ptr,
                   1354:                                 (compare_func_type)compare_ptrs);
                   1355:   
                   1356:   /* call -awake for all objects read  */
                   1357:   if (awake_sel)
                   1358:     {
                   1359:       for (node = hash_next (stream->object_table, NULL); node;
                   1360:           node = hash_next (stream->object_table, node))
                   1361:        {
                   1362:          id object = node->value;
                   1363:          if (__objc_responds_to (object, awake_sel))
                   1364:            (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
                   1365:        }
                   1366:     }
                   1367: 
                   1368:   /* empty object table */
                   1369:   hash_delete (stream->object_table);
                   1370:   stream->object_table = hash_new(64,
                   1371:                                  (hash_func_type)hash_ptr,
                   1372:                                  (compare_func_type)compare_ptrs);
                   1373: }
                   1374: 
                   1375: /*
                   1376: ** Open the stream PHYSICAL in MODE
                   1377: */
                   1378: 
                   1379: TypedStream* 
                   1380: objc_open_typed_stream (FILE* physical, int mode)
                   1381: {
                   1382:   int fflush(FILE*);
                   1383: 
                   1384:   TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
                   1385: 
                   1386:   s->mode = mode;
                   1387:   s->physical = physical;
                   1388:   s->stream_table = hash_new(64,
                   1389:                             (hash_func_type)hash_ptr,
                   1390:                             (compare_func_type)compare_ptrs);
                   1391:   s->object_table = hash_new(64,
                   1392:                             (hash_func_type)hash_ptr,
                   1393:                             (compare_func_type)compare_ptrs);
                   1394:   s->eof = (objc_typed_eof_func)__objc_feof;
                   1395:   s->flush = (objc_typed_flush_func)fflush;
                   1396:   s->writing_root_p = 0;
                   1397:   if (mode == OBJC_READONLY)
                   1398:     {
                   1399:       s->class_table = hash_new(8, (hash_func_type)hash_string,
                   1400:                                (compare_func_type)compare_strings);
                   1401:       s->object_refs = hash_new(8, (hash_func_type)hash_ptr,
                   1402:                                (compare_func_type)compare_ptrs);
                   1403:       s->read = (objc_typed_read_func)__objc_fread;
                   1404:       s->write = (objc_typed_write_func)__objc_no_write;
                   1405:       __objc_read_typed_stream_signature (s);
                   1406:     }
                   1407:   else if (mode == OBJC_WRITEONLY)
                   1408:     {
                   1409:       s->class_table = 0;
                   1410:       s->object_refs = 0;
                   1411:       s->read = (objc_typed_read_func)__objc_no_read;
                   1412:       s->write = (objc_typed_write_func)__objc_fwrite;
                   1413:       __objc_write_typed_stream_signature (s);
                   1414:     }      
                   1415:   else
                   1416:     {
                   1417:       objc_close_typed_stream (s);
                   1418:       return NULL;
                   1419:     }
                   1420:   s->type = OBJC_FILE_STREAM;
                   1421:   return s;
                   1422: }
                   1423: 
                   1424: /*
                   1425: ** Open the file named by FILE_NAME in MODE
                   1426: */
                   1427: 
                   1428: TypedStream*
                   1429: objc_open_typed_stream_for_file (const char* file_name, int mode)
                   1430: {
                   1431:   FILE* file = NULL;
                   1432:   TypedStream* s;
                   1433: 
                   1434:   if (mode == OBJC_READONLY)
                   1435:     file = fopen (file_name, "r");
                   1436:   else
                   1437:     file = fopen (file_name, "w");
                   1438: 
                   1439:   if (file)
                   1440:     {
                   1441:       s = objc_open_typed_stream (file, mode);
                   1442:       if (s)
                   1443:        s->type |= OBJC_MANAGED_STREAM;
                   1444:       return s;
                   1445:     }
                   1446:   else
                   1447:     return NULL;
                   1448: }
                   1449: 
                   1450: /*
                   1451: ** Close STREAM freeing the structure it self.  If it was opened with 
                   1452: ** objc_open_typed_stream_for_file, the file will also be closed.
                   1453: */
                   1454: 
                   1455: void
                   1456: objc_close_typed_stream (TypedStream* stream)
                   1457: {
                   1458:   if (stream->mode == OBJC_READONLY)
                   1459:     {
                   1460:       __objc_finish_read_root_object (stream); /* Just in case... */
                   1461:       hash_delete (stream->class_table);
                   1462:       hash_delete (stream->object_refs);
                   1463:     }
                   1464: 
                   1465:   hash_delete (stream->stream_table);
                   1466:   hash_delete (stream->object_table);
                   1467: 
                   1468:   if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
                   1469:     fclose ((FILE*)stream->physical);
                   1470: 
                   1471:   free (stream);
                   1472: }
                   1473: 
                   1474: BOOL
                   1475: objc_end_of_typed_stream (TypedStream* stream)
                   1476: {
                   1477:   return (*stream->eof)(stream->physical);
                   1478: }
                   1479: 
                   1480: void
                   1481: objc_flush_typed_stream (TypedStream* stream)
                   1482: {
                   1483:   (*stream->flush)(stream->physical);
                   1484: }
                   1485: 
                   1486: int 
                   1487: objc_get_stream_class_version (TypedStream* stream, Class* class)
                   1488: {
                   1489:   if (stream->class_table)
                   1490:     return (int) hash_value_for_key (stream->class_table, class->name);
                   1491:   else
                   1492:     return class_get_version (class);
                   1493: }
                   1494: 
                   1495: #endif /* __alpha__ */

unix.superglobalmegacorp.com

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