Annotation of GNUtools/cc/objc/archive.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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