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

1.1       root        1: /* GNU Objective C Runtime archiving
1.1.1.4 ! root        2:    Copyright (C) 1993, 1995 Free Software Foundation, Inc.
        !             3:    Contributed by Kresten Krab Thorup
1.1       root        4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is free software; you can redistribute it and/or modify it under the
1.1.1.4 ! root        8: terms of the GNU General Public License as published by the Free Software
        !             9: Foundation; either version 2, or (at your option) any later version.
1.1       root       10: 
                     11: GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
1.1.1.4 ! root       12: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
        !            13: FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
        !            14: details.
1.1       root       15: 
                     16: You should have received a copy of the GNU General Public License along with
1.1.1.4 ! root       17: GNU CC; see the file COPYING.  If not, write to the Free Software
        !            18: Foundation, 59 Temple Place - Suite 330,
        !            19: Boston, MA 02111-1307, USA.  */
1.1       root       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"
1.1.1.3   root       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))
1.1       root       39: 
                     40: #define __objc_fatal(format, args...) \
1.1.1.2   root       41:  { fprintf(stderr, "archiving: "); \
1.1       root       42:    fprintf(stderr, format, ## args); \
                     43:    fprintf(stderr, "\n"); abort(); }
                     44: 
                     45: /* Declare some functions... */
                     46: 
                     47: static int
1.1.1.4 ! root       48: objc_read_class (struct objc_typed_stream* stream, Class* class);
1.1       root       49: 
1.1.1.3   root       50: int objc_sizeof_type(const char* type);
1.1       root       51: 
                     52: static int
1.1.1.3   root       53: objc_write_use_common (struct objc_typed_stream* stream, unsigned long key);
1.1       root       54: 
                     55: static int
                     56: objc_write_register_common (struct objc_typed_stream* stream,
1.1.1.3   root       57:                            unsigned long key);
1.1       root       58: 
                     59: static int 
                     60: objc_write_class (struct objc_typed_stream* stream,
                     61:                         struct objc_class* class);
                     62: 
1.1.1.3   root       63: const char* objc_skip_type (const char* type);
1.1       root       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: {
1.1.1.3   root      117:   if ((val&_B_VALUE) == val)
                    118:     {
                    119:       buf[0] = val|_B_SINT;
                    120:       return 1;
                    121:     }
1.1       root      122:   else 
                    123:     {
1.1.1.3   root      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;
1.1       root      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: {
1.1.1.3   root      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;
1.1       root      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: {
1.1.1.3   root      173:   if ((val&_B_VALUE) == val)
1.1       root      174:     {
1.1.1.3   root      175:       buf[0] = val|_B_SINT;
                    176:       return 1;
1.1       root      177:     }
                    178:   else 
                    179:     {
1.1.1.3   root      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;
1.1       root      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: {
1.1.1.3   root      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: }
1.1       root      216: 
1.1.1.3   root      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: }
1.1       root      224: 
1.1.1.3   root      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:     }
1.1       root      233:   else 
                    234:     {
1.1.1.3   root      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;
1.1       root      251:     }
                    252: }
                    253: 
                    254: int
1.1.1.3   root      255: objc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value)
1.1       root      256: {
1.1.1.3   root      257:   unsigned char buf[sizeof(unsigned long)+1];
                    258:   int len = __objc_code_unsigned_long (buf, value);
1.1       root      259:   return (*stream->write)(stream->physical, buf, len);
                    260: }
                    261: 
1.1.1.3   root      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: 
1.1       root      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: {
1.1.1.3   root      304:   unsigned long key;
                    305:   if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string))))
1.1       root      306:     return objc_write_use_common (stream, key);
                    307:   else
                    308:     {
                    309:       int length;
1.1.1.3   root      310:       hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string);
1.1       root      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
1.1.1.3   root      318: objc_write_register_common (struct objc_typed_stream* stream, unsigned long key)
1.1       root      319: {
1.1.1.3   root      320:   unsigned char buf[sizeof (unsigned long)+2];
                    321:   int len = __objc_code_unsigned_long (buf+1, key);
1.1       root      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
1.1.1.3   root      336: objc_write_use_common (struct objc_typed_stream* stream, unsigned long key)
1.1       root      337: {
1.1.1.3   root      338:   unsigned char buf[sizeof (unsigned long)+2];
                    339:   int len = __objc_code_unsigned_long (buf+1, key);
1.1       root      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';
1.1.1.3   root      369:   SEL write_sel = sel_get_any_uid ("write:");
1.1       root      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: {
1.1.1.3   root      384:   unsigned long key;
                    385:   if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
1.1       root      386:     return objc_write_use_common (stream, key);
                    387: 
                    388:   __objc_write_extension (stream, _BX_OBJREF);
1.1.1.3   root      389:   return objc_write_unsigned_long (stream, PTR2LONG (object));
1.1       root      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: {
1.1.1.3   root      412:   unsigned long key;
                    413:   if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
1.1       root      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;
1.1.1.3   root      422:       hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object);
1.1       root      423:       if ((length = objc_write_register_common (stream, key)))
                    424:        return __objc_write_object (stream, object);
                    425:       return length;
                    426:     }
                    427: }
                    428: 
1.1.1.3   root      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: 
1.1       root      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));
1.1.1.4 ! root      441:   return objc_write_unsigned_long (stream, class->version);
1.1       root      442: }
                    443: 
                    444: 
                    445: static int 
                    446: objc_write_class (struct objc_typed_stream* stream,
                    447:                         struct objc_class* class)
                    448: {
1.1.1.3   root      449:   unsigned long key;
                    450:   if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class))))
1.1       root      451:     return objc_write_use_common (stream, key);
                    452:   else
                    453:     {
                    454:       int length;
1.1.1.3   root      455:       hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class);
1.1       root      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: {
1.1.1.4 ! root      466:   const char* sel_name;
1.1       root      467:   __objc_write_extension (stream, _BX_SEL);
1.1.1.4 ! root      468:   /* to handle NULL selectors */
        !           469:   if ((SEL)0 == selector)
        !           470:     return objc_write_string (stream, "", 0);
        !           471:   sel_name = sel_get_name (selector);
1.1       root      472:   return objc_write_string (stream, sel_name, strlen ((char*)sel_name));
                    473: }
                    474: 
                    475: int 
                    476: objc_write_selector (struct objc_typed_stream* stream, SEL selector)
                    477: {
1.1.1.4 ! root      478:   const char* sel_name;
1.1.1.3   root      479:   unsigned long key;
1.1.1.4 ! root      480: 
        !           481:   /* to handle NULL selectors */
        !           482:   if ((SEL)0 == selector)
        !           483:     return __objc_write_selector (stream, selector);
        !           484: 
        !           485:   sel_name = sel_get_name (selector);
1.1.1.3   root      486:   if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name))))
1.1       root      487:     return objc_write_use_common (stream, key);
                    488:   else
                    489:     {
                    490:       int length;
1.1.1.3   root      491:       hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
1.1       root      492:       if ((length = objc_write_register_common (stream, key)))
                    493:        return __objc_write_selector (stream, selector);
                    494:       return length;
                    495:     }
                    496: }
                    497: 
                    498: 
                    499: 
                    500: /*
                    501: ** Read operations 
                    502: */
                    503: 
                    504: __inline__ int
                    505: objc_read_char (struct objc_typed_stream* stream, char* val)
                    506: {
                    507:   unsigned char buf;
                    508:   int len;
                    509:   len = (*stream->read)(stream->physical, &buf, 1);
                    510:   if (len != 0)
                    511:     {
                    512:       if ((buf & _B_CODE) == _B_SINT)
                    513:        (*val) = (buf & _B_VALUE);
                    514: 
                    515:       else if ((buf & _B_NUMBER) == 1)
                    516:        {
                    517:          len = (*stream->read)(stream->physical, val, 1);
                    518:          if (buf&_B_SIGN)
                    519:            (*val) = -1*(*val);
                    520:        }
                    521: 
                    522:       else
                    523:        __objc_fatal("expected 8bit signed int, got %dbit int",
                    524:                     (int)(buf&_B_NUMBER)*8);
                    525:     }
                    526:   return len;
                    527: }
                    528: 
                    529: 
                    530: __inline__ int
                    531: objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val)
                    532: {
                    533:   unsigned char buf;
                    534:   int len;
                    535:   if ((len = (*stream->read)(stream->physical, &buf, 1)))
                    536:     {
                    537:       if ((buf & _B_CODE) == _B_SINT)
                    538:        (*val) = (buf & _B_VALUE);
                    539: 
                    540:       else if ((buf & _B_NUMBER) == 1)
                    541:        len = (*stream->read)(stream->physical, val, 1);
                    542: 
                    543:       else
                    544:        __objc_fatal("expected 8bit unsigned int, got %dbit int",
                    545:                     (int)(buf&_B_NUMBER)*8);
                    546:     }
                    547:   return len;
                    548: }
                    549: 
                    550: __inline__ int
                    551: objc_read_short (struct objc_typed_stream* stream, short* value)
                    552: {
                    553:   unsigned char buf[sizeof(short)+1];
                    554:   int len;
                    555:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    556:     {
                    557:       if ((buf[0] & _B_CODE) == _B_SINT)
                    558:        (*value) = (buf[0] & _B_VALUE);
                    559: 
                    560:       else
                    561:        {
                    562:          int pos = 1;
                    563:          int nbytes = buf[0] & _B_NUMBER;
                    564:          if (nbytes > sizeof (short))
                    565:            __objc_fatal("expected short, got bigger (%dbits)", nbytes*8);
                    566:          len = (*stream->read)(stream->physical, buf+1, nbytes);
                    567:          (*value) = 0;
                    568:          while (pos <= nbytes)
                    569:            (*value) = ((*value)*0x100) + buf[pos++];
                    570:          if (buf[0] & _B_SIGN)
                    571:            (*value) = -(*value);
                    572:        }
                    573:     }
                    574:   return len;
                    575: }
                    576: 
                    577: __inline__ int
                    578: objc_read_unsigned_short (struct objc_typed_stream* stream,
                    579:                          unsigned short* value)
                    580: {
                    581:   unsigned char buf[sizeof(unsigned short)+1];
                    582:   int len;
                    583:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    584:     {
                    585:       if ((buf[0] & _B_CODE) == _B_SINT)
                    586:        (*value) = (buf[0] & _B_VALUE);
                    587: 
                    588:       else
                    589:        {
                    590:          int pos = 1;
                    591:          int nbytes = buf[0] & _B_NUMBER;
                    592:          if (nbytes > sizeof (short))
                    593:            __objc_fatal("expected short, got int or bigger");
                    594:          len = (*stream->read)(stream->physical, buf+1, nbytes);
                    595:          (*value) = 0;
                    596:          while (pos <= nbytes)
                    597:            (*value) = ((*value)*0x100) + buf[pos++];
                    598:        }
                    599:     }
                    600:   return len;
                    601: }
                    602: 
                    603: 
                    604: __inline__ int
                    605: objc_read_int (struct objc_typed_stream* stream, int* value)
                    606: {
                    607:   unsigned char buf[sizeof(int)+1];
                    608:   int len;
                    609:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    610:     {
                    611:       if ((buf[0] & _B_CODE) == _B_SINT)
                    612:        (*value) = (buf[0] & _B_VALUE);
                    613: 
                    614:       else
                    615:        {
                    616:          int pos = 1;
                    617:          int nbytes = buf[0] & _B_NUMBER;
                    618:          if (nbytes > sizeof (int))
                    619:            __objc_fatal("expected int, got bigger");
                    620:          len = (*stream->read)(stream->physical, buf+1, nbytes);
                    621:          (*value) = 0;
                    622:          while (pos <= nbytes)
                    623:            (*value) = ((*value)*0x100) + buf[pos++];
                    624:          if (buf[0] & _B_SIGN)
                    625:            (*value) = -(*value);
                    626:        }
                    627:     }
                    628:   return len;
                    629: }
                    630: 
                    631: __inline__ int
1.1.1.3   root      632: objc_read_long (struct objc_typed_stream* stream, long* value)
                    633: {
                    634:   unsigned char buf[sizeof(long)+1];
                    635:   int len;
                    636:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    637:     {
                    638:       if ((buf[0] & _B_CODE) == _B_SINT)
                    639:        (*value) = (buf[0] & _B_VALUE);
                    640: 
                    641:       else
                    642:        {
                    643:          int pos = 1;
                    644:          int nbytes = buf[0] & _B_NUMBER;
                    645:          if (nbytes > sizeof (long))
                    646:            __objc_fatal("expected long, got bigger");
                    647:          len = (*stream->read)(stream->physical, buf+1, nbytes);
                    648:          (*value) = 0;
                    649:          while (pos <= nbytes)
                    650:            (*value) = ((*value)*0x100) + buf[pos++];
                    651:          if (buf[0] & _B_SIGN)
                    652:            (*value) = -(*value);
                    653:        }
                    654:     }
                    655:   return len;
                    656: }
                    657: 
                    658: __inline__ int
1.1       root      659: __objc_read_nbyte_uint (struct objc_typed_stream* stream,
                    660:                       unsigned int nbytes, unsigned int* val)
                    661: {
                    662:   int len, pos = 0;
                    663:   unsigned char buf[sizeof(unsigned int)+1];
                    664: 
                    665:   if (nbytes > sizeof (int))
                    666:     __objc_fatal("expected int, got bigger");
                    667: 
                    668:   len = (*stream->read)(stream->physical, buf, nbytes);
                    669:   (*val) = 0;
                    670:   while (pos < nbytes)
                    671:     (*val) = ((*val)*0x100) + buf[pos++];
                    672:   return len;
                    673: }
                    674:   
                    675: 
                    676: __inline__ int
                    677: objc_read_unsigned_int (struct objc_typed_stream* stream,
                    678:                        unsigned int* value)
                    679: {
                    680:   unsigned char buf[sizeof(unsigned int)+1];
                    681:   int len;
                    682:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    683:     {
                    684:       if ((buf[0] & _B_CODE) == _B_SINT)
                    685:        (*value) = (buf[0] & _B_VALUE);
                    686: 
                    687:       else
                    688:        len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), value);
                    689: 
                    690:     }
                    691:   return len;
                    692: }
                    693: 
1.1.1.3   root      694: int
                    695: __objc_read_nbyte_ulong (struct objc_typed_stream* stream,
                    696:                       unsigned int nbytes, unsigned long* val)
                    697: {
                    698:   int len, pos = 0;
                    699:   unsigned char buf[sizeof(unsigned long)+1];
                    700: 
                    701:   if (nbytes > sizeof (long))
                    702:     __objc_fatal("expected long, got bigger");
                    703: 
                    704:   len = (*stream->read)(stream->physical, buf, nbytes);
                    705:   (*val) = 0;
                    706:   while (pos < nbytes)
                    707:     (*val) = ((*val)*0x100) + buf[pos++];
                    708:   return len;
                    709: }
                    710:   
                    711: 
                    712: __inline__ int
                    713: objc_read_unsigned_long (struct objc_typed_stream* stream,
                    714:                        unsigned long* value)
                    715: {
                    716:   unsigned char buf[sizeof(unsigned long)+1];
                    717:   int len;
                    718:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    719:     {
                    720:       if ((buf[0] & _B_CODE) == _B_SINT)
                    721:        (*value) = (buf[0] & _B_VALUE);
                    722: 
                    723:       else
                    724:        len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value);
                    725: 
                    726:     }
                    727:   return len;
                    728: }
                    729: 
1.1       root      730: __inline__ int
                    731: objc_read_string (struct objc_typed_stream* stream,
                    732:                  char** string)
                    733: {
                    734:   unsigned char buf[sizeof(unsigned int)+1];
                    735:   int len;
                    736:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    737:     {
1.1.1.3   root      738:       unsigned long key = 0;
1.1       root      739: 
                    740:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
                    741:        {
1.1.1.3   root      742:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1       root      743:          len = (*stream->read)(stream->physical, buf, 1);
                    744:        }
                    745: 
                    746:       switch (buf[0]&_B_CODE) {
                    747:       case _B_SSTR:
                    748:        {
                    749:          int length = buf[0]&_B_VALUE;
                    750:          (*string) = (char*)__objc_xmalloc(length+1);
                    751:          if (key)
1.1.1.3   root      752:            hash_add (&stream->stream_table, LONG2PTR(key), *string);
1.1       root      753:          len = (*stream->read)(stream->physical, *string, length);
                    754:          (*string)[length] = '\0';
                    755:        }
                    756:        break;
                    757: 
                    758:       case _B_UCOMM:
                    759:        {
1.1.1.2   root      760:          char *tmp;
1.1.1.3   root      761:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
                    762:          tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key));
                    763:          *string = __objc_xmalloc (strlen(tmp) + 1);
1.1.1.2   root      764:          strcpy (*string, tmp);
1.1       root      765:        }
                    766:        break;
                    767: 
                    768:       case _B_NSTR:
                    769:        {
                    770:          unsigned int nbytes = buf[0]&_B_VALUE;
                    771:          len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
                    772:          if (len) {
1.1.1.2   root      773:            (*string) = (char*)__objc_xmalloc(nbytes+1);
1.1       root      774:            if (key)
1.1.1.3   root      775:              hash_add (&stream->stream_table, LONG2PTR(key), *string);
1.1.1.2   root      776:            len = (*stream->read)(stream->physical, *string, nbytes);
1.1       root      777:            (*string)[nbytes] = '\0';
                    778:          }
                    779:        }
                    780:        break;
                    781:        
                    782:       default:
                    783:        __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE));
                    784:       }
                    785:     }
                    786: 
                    787:   return len;
                    788: }
                    789: 
                    790: 
                    791: int
                    792: objc_read_object (struct objc_typed_stream* stream, id* object)
                    793: {
                    794:   unsigned char buf[sizeof (unsigned int)];
                    795:   int len;
                    796:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    797:     {
1.1.1.3   root      798:       SEL read_sel = sel_get_any_uid ("read:");
                    799:       unsigned long key = 0;
1.1       root      800: 
                    801:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register common */
                    802:        {
1.1.1.3   root      803:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1       root      804:          len = (*stream->read)(stream->physical, buf, 1);
                    805:        }
                    806: 
                    807:       if (buf[0] == (_B_EXT | _BX_OBJECT))
                    808:        {
1.1.1.4 ! root      809:          Class class;
1.1       root      810: 
                    811:          /* get class */
                    812:          len = objc_read_class (stream, &class);
                    813: 
                    814:          /* create instance */
                    815:          (*object) = class_create_instance(class);
                    816: 
                    817:          /* register? */
                    818:          if (key)
1.1.1.3   root      819:            hash_add (&stream->object_table, LONG2PTR(key), *object);
1.1       root      820: 
                    821:          /* send -read: */
                    822:          if (__objc_responds_to (*object, read_sel))
                    823:            (*get_imp(class, read_sel))(*object, read_sel, stream);
                    824: 
                    825:          /* check null-byte */
                    826:          len = (*stream->read)(stream->physical, buf, 1);
                    827:          if (buf[0] != '\0')
                    828:            __objc_fatal("expected null-byte, got opcode %c", buf[0]);
                    829:        }
                    830: 
                    831:       else if ((buf[0]&_B_CODE) == _B_UCOMM)
                    832:        {
                    833:          if (key)
                    834:            __objc_fatal("cannot register use upcode...");
1.1.1.3   root      835:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
                    836:          (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
1.1       root      837:        }
                    838: 
                    839:       else if (buf[0] == (_B_EXT | _BX_OBJREF))        /* a forward reference */
                    840:        {
                    841:          struct objc_list* other;
1.1.1.3   root      842:          len = objc_read_unsigned_long (stream, &key);
                    843:          other = (struct objc_list*)hash_value_for_key (stream->object_refs, LONG2PTR(key));
                    844:          hash_add (&stream->object_refs, LONG2PTR(key), (void*)list_cons(object, other));
1.1       root      845:        }
                    846: 
                    847:       else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
                    848:        {
                    849:          if (key)
                    850:            __objc_fatal("cannot register root object...");
                    851:          len = objc_read_object (stream, object);
                    852:          __objc_finish_read_root_object (stream);
                    853:        }
                    854: 
                    855:       else
                    856:        __objc_fatal("expected object, got opcode %c", buf[0]);
                    857:     }
                    858:   return len;
                    859: }
                    860: 
                    861: static int
1.1.1.4 ! root      862: objc_read_class (struct objc_typed_stream* stream, Class* class)
1.1       root      863: {
                    864:   unsigned char buf[sizeof (unsigned int)];
                    865:   int len;
                    866:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    867:     {
1.1.1.3   root      868:       unsigned long key = 0;
1.1       root      869: 
                    870:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
                    871:        {
1.1.1.3   root      872:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1       root      873:          len = (*stream->read)(stream->physical, buf, 1);
                    874:        }
                    875: 
                    876:       if (buf[0] == (_B_EXT | _BX_CLASS))
                    877:        {
                    878:          char* class_name;
1.1.1.3   root      879:          unsigned long version;
1.1       root      880: 
                    881:          /* get class */
                    882:          len = objc_read_string (stream, &class_name);
                    883:          (*class) = objc_get_class(class_name);
                    884:          free (class_name);
                    885: 
                    886:          /* register */
                    887:          if (key)
1.1.1.3   root      888:            hash_add (&stream->stream_table, LONG2PTR(key), *class);
1.1       root      889: 
1.1.1.3   root      890:          objc_read_unsigned_long(stream, &version);
1.1       root      891:          hash_add (&stream->class_table, (*class)->name, (void*)version);
                    892:        }
                    893: 
                    894:       else if ((buf[0]&_B_CODE) == _B_UCOMM)
                    895:        {
                    896:          if (key)
                    897:            __objc_fatal("cannot register use upcode...");
1.1.1.3   root      898:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
                    899:          (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
1.1       root      900:          if (!*class)
1.1.1.3   root      901:            __objc_fatal("cannot find class for key %lu", key);
1.1       root      902:        }
                    903: 
                    904:       else
                    905:        __objc_fatal("expected class, got opcode %c", buf[0]);
                    906:     }
                    907:   return len;
                    908: }
                    909: 
                    910: int
                    911: objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
                    912: {
                    913:   unsigned char buf[sizeof (unsigned int)];
                    914:   int len;
                    915:   if ((len = (*stream->read)(stream->physical, buf, 1)))
                    916:     {
1.1.1.3   root      917:       unsigned long key = 0;
1.1       root      918: 
                    919:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
                    920:        {
1.1.1.3   root      921:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1       root      922:          len = (*stream->read)(stream->physical, buf, 1);
                    923:        }
                    924: 
                    925:       if (buf[0] == (_B_EXT|_BX_SEL)) /* selector! */
                    926:        {
                    927:          char* selector_name;
                    928: 
                    929:          /* get selector */
                    930:          len = objc_read_string (stream, &selector_name);
1.1.1.4 ! root      931:          /* To handle NULL selectors */
        !           932:          if (0 == strlen(selector_name))
        !           933:            {
        !           934:              (*selector) = (SEL)0;
        !           935:              return 0;
        !           936:            }
        !           937:          else 
        !           938:            (*selector) = sel_get_any_uid(selector_name);
1.1       root      939:          free (selector_name);
                    940: 
                    941:          /* register */
                    942:          if (key)
1.1.1.3   root      943:            hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
1.1       root      944:        }
                    945: 
                    946:       else if ((buf[0]&_B_CODE) == _B_UCOMM)
                    947:        {
                    948:          if (key)
                    949:            __objc_fatal("cannot register use upcode...");
1.1.1.3   root      950:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
                    951:          (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
1.1       root      952:        }
                    953: 
                    954:       else
                    955:        __objc_fatal("expected selector, got opcode %c", buf[0]);
                    956:     }
                    957:   return len;
                    958: }
                    959: 
                    960: /*
                    961: ** USER LEVEL FUNCTIONS
                    962: */
                    963: 
                    964: /*
                    965: ** Write one object, encoded in TYPE and pointed to by DATA to the
                    966: ** typed stream STREAM.  
                    967: */
                    968: 
                    969: int
                    970: objc_write_type(TypedStream* stream, const char* type, const void* data)
                    971: {
                    972:   switch(*type) {
                    973:   case _C_ID:
                    974:     return objc_write_object (stream, *(id*)data);
                    975:     break;
                    976: 
                    977:   case _C_CLASS:
1.1.1.4 ! root      978:     return objc_write_class (stream, *(Class*)data);
1.1       root      979:     break;
                    980: 
                    981:   case _C_SEL:
                    982:     return objc_write_selector (stream, *(SEL*)data);
                    983:     break;
                    984: 
                    985:   case _C_CHR:
                    986:     return objc_write_char(stream, *(char*)data);
                    987:     break;
                    988:     
                    989:   case _C_UCHR:
                    990:     return objc_write_unsigned_char(stream, *(unsigned char*)data);
                    991:     break;
                    992: 
                    993:   case _C_SHT:
                    994:     return objc_write_short(stream, *(short*)data);
                    995:     break;
                    996: 
                    997:   case _C_USHT:
                    998:     return objc_write_unsigned_short(stream, *(unsigned short*)data);
                    999:     break;
                   1000: 
                   1001:   case _C_INT:
                   1002:     return objc_write_int(stream, *(int*)data);
                   1003:     break;
                   1004: 
                   1005:   case _C_UINT:
                   1006:     return objc_write_unsigned_int(stream, *(unsigned int*)data);
                   1007:     break;
                   1008: 
1.1.1.3   root     1009:   case _C_LNG:
                   1010:     return objc_write_long(stream, *(long*)data);
                   1011:     break;
                   1012: 
                   1013:   case _C_ULNG:
                   1014:     return objc_write_unsigned_long(stream, *(unsigned long*)data);
                   1015:     break;
                   1016: 
1.1       root     1017:   case _C_CHARPTR:
1.1.1.2   root     1018:     return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
1.1       root     1019:     break;
                   1020: 
                   1021:   case _C_ATOM:
1.1.1.2   root     1022:     return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data));
1.1       root     1023:     break;
                   1024: 
                   1025:   case _C_ARY_B:
                   1026:     {
                   1027:       int len = atoi(type+1);
                   1028:       while (isdigit(*++type));
                   1029:       return objc_write_array (stream, type, len, data);
                   1030:     }
                   1031:     break; 
                   1032: 
1.1.1.3   root     1033:   case _C_STRUCT_B:
                   1034:     {
                   1035:       int acc_size = 0;
                   1036:       int align;
                   1037:       while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
                   1038:       while (*type != _C_STRUCT_E);
                   1039:        {
                   1040:          align = objc_alignof_type (type);       /* padd to alignment */
                   1041:          acc_size += ROUND (acc_size, align);
                   1042:          objc_write_type (stream, type, ((char*)data)+acc_size);
                   1043:          acc_size += objc_sizeof_type (type);   /* add component size */
                   1044:          type = objc_skip_typespec (type);      /* skip component */
                   1045:        }
                   1046:       return 1;
                   1047:     }
                   1048: 
1.1       root     1049:   default:
                   1050:     fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
                   1051:     abort();
                   1052:   }
                   1053: }
                   1054: 
                   1055: /*
                   1056: ** Read one object, encoded in TYPE and pointed to by DATA to the
                   1057: ** typed stream STREAM.  DATA specifies the address of the types to
                   1058: ** read.  Expected type is checked against the type actually present
                   1059: ** on the stream. 
                   1060: */
                   1061: 
                   1062: int
                   1063: objc_read_type(TypedStream* stream, const char* type, void* data)
                   1064: {
                   1065:   char c;
                   1066:   switch(c = *type) {
                   1067:   case _C_ID:
                   1068:     return objc_read_object (stream, (id*)data);
                   1069:     break;
                   1070: 
                   1071:   case _C_CLASS:
1.1.1.4 ! root     1072:     return objc_read_class (stream, (Class*)data);
1.1       root     1073:     break;
                   1074: 
                   1075:   case _C_SEL:
                   1076:     return objc_read_selector (stream, (SEL*)data);
                   1077:     break;
                   1078: 
                   1079:   case _C_CHR:
                   1080:     return objc_read_char (stream, (char*)data);
                   1081:     break;
                   1082:     
                   1083:   case _C_UCHR:
                   1084:     return objc_read_unsigned_char (stream, (unsigned char*)data);
                   1085:     break;
                   1086: 
                   1087:   case _C_SHT:
                   1088:     return objc_read_short (stream, (short*)data);
                   1089:     break;
                   1090: 
                   1091:   case _C_USHT:
                   1092:     return objc_read_unsigned_short (stream, (unsigned short*)data);
                   1093:     break;
                   1094: 
                   1095:   case _C_INT:
                   1096:     return objc_read_int (stream, (int*)data);
                   1097:     break;
                   1098: 
                   1099:   case _C_UINT:
                   1100:     return objc_read_unsigned_int (stream, (unsigned int*)data);
                   1101:     break;
                   1102: 
1.1.1.3   root     1103:   case _C_LNG:
                   1104:     return objc_read_long (stream, (long*)data);
                   1105:     break;
                   1106: 
                   1107:   case _C_ULNG:
                   1108:     return objc_read_unsigned_long (stream, (unsigned long*)data);
                   1109:     break;
                   1110: 
1.1       root     1111:   case _C_CHARPTR:
                   1112:   case _C_ATOM:
                   1113:     return objc_read_string (stream, (char**)data);
                   1114:     break;
                   1115: 
                   1116:   case _C_ARY_B:
                   1117:     {
                   1118:       int len = atoi(type+1);
                   1119:       while (isdigit(*++type));
                   1120:       return objc_read_array (stream, type, len, data);
                   1121:     }
                   1122:     break; 
                   1123: 
1.1.1.3   root     1124:   case _C_STRUCT_B:
                   1125:     {
                   1126:       int acc_size = 0;
                   1127:       int align;
                   1128:       while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
                   1129:       while (*type != _C_STRUCT_E);
                   1130:        {
                   1131:          align = objc_alignof_type (type);       /* padd to alignment */
                   1132:          acc_size += ROUND (acc_size, align);
                   1133:          objc_read_type (stream, type, ((char*)data)+acc_size);
                   1134:          acc_size += objc_sizeof_type (type);   /* add component size */
                   1135:          type = objc_skip_typespec (type);      /* skip component */
                   1136:        }
                   1137:       return 1;
                   1138:     }
                   1139: 
1.1       root     1140:   default:
1.1.1.2   root     1141:     fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
1.1       root     1142:     abort();
                   1143:   }
                   1144: }
                   1145: 
                   1146: /*
                   1147: ** Write the object specified by the template TYPE to STREAM.  Last
                   1148: ** arguments specify addresses of values to be written.  It might 
                   1149: ** seem surprising to specify values by address, but this is extremely
                   1150: ** convenient for copy-paste with objc_read_types calls.  A more
                   1151: ** down-to-the-earth cause for this passing of addresses is that values
                   1152: ** of arbitrary size is not well supported in ANSI C for functions with
                   1153: ** variable number of arguments.
                   1154: */
                   1155: 
                   1156: int 
                   1157: objc_write_types (TypedStream* stream, const char* type, ...)
                   1158: {
                   1159:   va_list args;
                   1160:   const char *c;
                   1161:   int res = 0;
                   1162: 
                   1163:   va_start(args, type);
                   1164: 
1.1.1.3   root     1165:   for (c = type; *c; c = objc_skip_typespec (c))
1.1       root     1166:     {
                   1167:       switch(*c) {
                   1168:       case _C_ID:
                   1169:        res = objc_write_object (stream, *va_arg (args, id*));
                   1170:        break;
                   1171: 
                   1172:       case _C_CLASS:
1.1.1.4 ! root     1173:        res = objc_write_class (stream, *va_arg(args, Class*));
1.1       root     1174:        break;
                   1175: 
                   1176:       case _C_SEL:
                   1177:        res = objc_write_selector (stream, *va_arg(args, SEL*));
                   1178:        break;
                   1179:        
                   1180:       case _C_CHR:
                   1181:        res = objc_write_char (stream, *va_arg (args, char*));
                   1182:        break;
                   1183:        
                   1184:       case _C_UCHR:
                   1185:        res = objc_write_unsigned_char (stream,
                   1186:                                        *va_arg (args, unsigned char*));
                   1187:        break;
                   1188:        
                   1189:       case _C_SHT:
                   1190:        res = objc_write_short (stream, *va_arg(args, short*));
                   1191:        break;
                   1192: 
                   1193:       case _C_USHT:
                   1194:        res = objc_write_unsigned_short (stream,
                   1195:                                         *va_arg(args, unsigned short*));
                   1196:        break;
                   1197: 
                   1198:       case _C_INT:
                   1199:        res = objc_write_int(stream, *va_arg(args, int*));
                   1200:        break;
                   1201:        
                   1202:       case _C_UINT:
                   1203:        res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
                   1204:        break;
                   1205: 
1.1.1.3   root     1206:       case _C_LNG:
                   1207:        res = objc_write_long(stream, *va_arg(args, long*));
                   1208:        break;
                   1209:        
                   1210:       case _C_ULNG:
                   1211:        res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*));
                   1212:        break;
                   1213: 
1.1       root     1214:       case _C_CHARPTR:
                   1215:        {
1.1.1.2   root     1216:          char** str = va_arg(args, char**);
                   1217:          res = objc_write_string (stream, *str, strlen(*str));
1.1       root     1218:        }
                   1219:        break;
                   1220: 
                   1221:       case _C_ATOM:
                   1222:        {
1.1.1.2   root     1223:          char** str = va_arg(args, char**);
                   1224:          res = objc_write_string_atomic (stream, *str, strlen(*str));
1.1       root     1225:        }
                   1226:        break;
                   1227: 
                   1228:       case _C_ARY_B:
                   1229:        {
                   1230:          int len = atoi(c+1);
                   1231:          const char* t = c;
                   1232:          while (isdigit(*++t));
                   1233:          res = objc_write_array (stream, t, len, va_arg(args, void*));
1.1.1.3   root     1234:          t = objc_skip_typespec (t);
1.1       root     1235:          if (*t != _C_ARY_E)
                   1236:            __objc_fatal("expected `]', got: %s", t);
                   1237:        }
                   1238:        break; 
                   1239:        
                   1240:       default:
1.1.1.2   root     1241:        fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type);
1.1       root     1242:        abort();
                   1243:       }
                   1244:     }
                   1245:   va_end(args);
                   1246:   return res;
                   1247: }
                   1248: 
                   1249: 
                   1250: /* 
                   1251: ** Last arguments specify addresses of values to be read.  Expected
                   1252: ** type is checked against the type actually present on the stream. 
                   1253: */
                   1254: 
                   1255: int 
                   1256: objc_read_types(TypedStream* stream, const char* type, ...)
                   1257: {
                   1258:   va_list args;
                   1259:   const char *c;
                   1260:   int res = 0;
                   1261: 
                   1262:   va_start(args, type);
                   1263: 
1.1.1.3   root     1264:   for (c = type; *c; c = objc_skip_typespec(c))
1.1       root     1265:     {
                   1266:       switch(*c) {
                   1267:       case _C_ID:
                   1268:        res = objc_read_object(stream, va_arg(args, id*));
                   1269:        break;
                   1270: 
                   1271:       case _C_CLASS:
1.1.1.4 ! root     1272:        res = objc_read_class(stream, va_arg(args, Class*));
1.1       root     1273:        break;
                   1274: 
                   1275:       case _C_SEL:
                   1276:        res = objc_read_selector(stream, va_arg(args, SEL*));
                   1277:        break;
                   1278:        
                   1279:       case _C_CHR:
                   1280:        res = objc_read_char(stream, va_arg(args, char*));
                   1281:        break;
                   1282:        
                   1283:       case _C_UCHR:
                   1284:        res = objc_read_unsigned_char(stream, va_arg(args, unsigned char*));
                   1285:        break;
                   1286:        
                   1287:       case _C_SHT:
                   1288:        res = objc_read_short(stream, va_arg(args, short*));
                   1289:        break;
                   1290: 
                   1291:       case _C_USHT:
                   1292:        res = objc_read_unsigned_short(stream, va_arg(args, unsigned short*));
                   1293:        break;
                   1294: 
                   1295:       case _C_INT:
                   1296:        res = objc_read_int(stream, va_arg(args, int*));
                   1297:        break;
                   1298:        
                   1299:       case _C_UINT:
                   1300:        res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
                   1301:        break;
                   1302: 
1.1.1.3   root     1303:       case _C_LNG:
                   1304:        res = objc_read_long(stream, va_arg(args, long*));
                   1305:        break;
                   1306:        
                   1307:       case _C_ULNG:
                   1308:        res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*));
                   1309:        break;
                   1310: 
1.1       root     1311:       case _C_CHARPTR:
                   1312:       case _C_ATOM:
                   1313:        {
                   1314:          char** str = va_arg(args, char**);
                   1315:          res = objc_read_string (stream, str);
                   1316:        }
                   1317:        break;
                   1318: 
                   1319:       case _C_ARY_B:
                   1320:        {
                   1321:          int len = atoi(c+1);
                   1322:          const char* t = c;
                   1323:          while (isdigit(*++t));
                   1324:          res = objc_read_array (stream, t, len, va_arg(args, void*));
1.1.1.3   root     1325:          t = objc_skip_typespec (t);
1.1       root     1326:          if (*t != _C_ARY_E)
                   1327:            __objc_fatal("expected `]', got: %s", t);
                   1328:        }
                   1329:        break; 
                   1330:        
                   1331:       default:
1.1.1.2   root     1332:        fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
1.1       root     1333:        abort();
                   1334:       }
                   1335:     }
                   1336:   va_end(args);
                   1337:   return res;
                   1338: }
                   1339: 
                   1340: /*
                   1341: ** Write an array of COUNT elements of TYPE from the memory address DATA.
                   1342: ** This is equivalent of objc_write_type (stream, "[N<type>]", data)
                   1343: */
                   1344: 
                   1345: int
                   1346: objc_write_array (TypedStream* stream, const char* type,
                   1347:                  int count, const void* data)
                   1348: {
                   1349:   int off = objc_sizeof_type(type);
                   1350:   const char* where = data;
                   1351: 
                   1352:   while (count-- > 0)
                   1353:     {
                   1354:       objc_write_type(stream, type, where);
                   1355:       where += off;
                   1356:     }
                   1357:   return 1;
                   1358: }
                   1359: 
                   1360: /*
                   1361: ** Read an array of COUNT elements of TYPE into the memory address
                   1362: ** DATA.  The memory pointed to by data is supposed to be allocated
                   1363: ** by the callee.  This is equivalent of 
                   1364: **   objc_read_type (stream, "[N<type>]", data)
                   1365: */
                   1366: 
                   1367: int
                   1368: objc_read_array (TypedStream* stream, const char* type,
                   1369:                 int count, void* data)
                   1370: {
                   1371:   int off = objc_sizeof_type(type);
                   1372:   char* where = (char*)data;
                   1373: 
                   1374:   while (count-- > 0)
                   1375:     {
                   1376:       objc_read_type(stream, type, where);
                   1377:       where += off;
                   1378:     }
                   1379:   return 1;
                   1380: }
                   1381: 
1.1.1.3   root     1382: static void
                   1383: __objc_free (void* p)
                   1384: {
                   1385:   free (p);
                   1386: }
                   1387: 
1.1       root     1388: static int 
                   1389: __objc_fread(FILE* file, char* data, int len)
                   1390: {
                   1391:   return fread(data, len, 1, file);
                   1392: }
                   1393: 
                   1394: static int 
                   1395: __objc_fwrite(FILE* file, char* data, int len)
                   1396: {
                   1397:   return fwrite(data, len, 1, file);
                   1398: }
                   1399: 
                   1400: static int
                   1401: __objc_feof(FILE* file)
                   1402: {
                   1403:   return feof(file);
                   1404: }
                   1405: 
                   1406: static int 
                   1407: __objc_no_write(FILE* file, char* data, int len)
                   1408: {
                   1409:   __objc_fatal ("TypedStream not open for writing");
                   1410: }
                   1411: 
                   1412: static int 
                   1413: __objc_no_read(FILE* file, char* data, int len)
                   1414: {
                   1415:   __objc_fatal ("TypedStream not open for reading");
                   1416: }
                   1417: 
                   1418: static int
                   1419: __objc_read_typed_stream_signature (TypedStream* stream)
                   1420: {
                   1421:   char buffer[80];
                   1422:   int pos = 0;
                   1423:   do
                   1424:     (*stream->read)(stream->physical, buffer+pos, 1);
                   1425:   while (buffer[pos++] != '\0');
                   1426:   sscanf (buffer, "GNU TypedStream %d", &stream->version);
                   1427:   if (stream->version != OBJC_TYPED_STREAM_VERSION)
                   1428:     __objc_fatal ("cannot handle TypedStream version %d", stream->version);
                   1429:   return 1;
                   1430: }
                   1431: 
                   1432: static int
                   1433: __objc_write_typed_stream_signature (TypedStream* stream)
                   1434: {
                   1435:   char buffer[80];
                   1436:   sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
                   1437:   stream->version = OBJC_TYPED_STREAM_VERSION;
                   1438:   (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
                   1439:   return 1;
                   1440: }
                   1441: 
                   1442: static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
                   1443: {
                   1444:   hash_delete (stream->object_table);
                   1445:   stream->object_table = hash_new(64,
                   1446:                                  (hash_func_type)hash_ptr,
                   1447:                                  (compare_func_type)compare_ptrs);
                   1448: }
                   1449: 
                   1450: static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
                   1451: {
                   1452:   node_ptr node;
1.1.1.3   root     1453:   struct objc_list* free_list;
                   1454:   SEL awake_sel = sel_get_any_uid ("awake");
1.1       root     1455: 
                   1456:   /* resolve object forward references */
1.1.1.3   root     1457:   free_list = list_cons(NULL, NULL);
1.1       root     1458:   for (node = hash_next (stream->object_refs, NULL); node;
                   1459:        node = hash_next (stream->object_refs, node))
                   1460:     {
                   1461:       struct objc_list* reflist = node->value;
                   1462:       const void* key = node->key;
                   1463:       id object = hash_value_for_key (stream->object_table, key);
                   1464:       while(reflist)
                   1465:        {
                   1466:          *((id*)reflist->head) = object;
1.1.1.3   root     1467:           if (list_find(&free_list, reflist) == NULL)
                   1468:            free_list = list_cons (reflist, free_list);
1.1       root     1469:          reflist = reflist->tail;
                   1470:        }
                   1471:     }
1.1.1.3   root     1472:   list_mapcar (free_list, __objc_free);
                   1473:   list_free (free_list);
1.1       root     1474: 
                   1475:   /* empty object reference table */
                   1476:   hash_delete (stream->object_refs);
                   1477:   stream->object_refs = hash_new(8, (hash_func_type)hash_ptr,
                   1478:                                 (compare_func_type)compare_ptrs);
                   1479:   
                   1480:   /* call -awake for all objects read  */
                   1481:   if (awake_sel)
                   1482:     {
                   1483:       for (node = hash_next (stream->object_table, NULL); node;
                   1484:           node = hash_next (stream->object_table, node))
                   1485:        {
                   1486:          id object = node->value;
                   1487:          if (__objc_responds_to (object, awake_sel))
                   1488:            (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
                   1489:        }
                   1490:     }
                   1491: 
                   1492:   /* empty object table */
                   1493:   hash_delete (stream->object_table);
                   1494:   stream->object_table = hash_new(64,
                   1495:                                  (hash_func_type)hash_ptr,
                   1496:                                  (compare_func_type)compare_ptrs);
                   1497: }
                   1498: 
                   1499: /*
                   1500: ** Open the stream PHYSICAL in MODE
                   1501: */
                   1502: 
                   1503: TypedStream* 
                   1504: objc_open_typed_stream (FILE* physical, int mode)
                   1505: {
                   1506:   TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
                   1507: 
                   1508:   s->mode = mode;
                   1509:   s->physical = physical;
                   1510:   s->stream_table = hash_new(64,
                   1511:                             (hash_func_type)hash_ptr,
                   1512:                             (compare_func_type)compare_ptrs);
                   1513:   s->object_table = hash_new(64,
                   1514:                             (hash_func_type)hash_ptr,
                   1515:                             (compare_func_type)compare_ptrs);
                   1516:   s->eof = (objc_typed_eof_func)__objc_feof;
                   1517:   s->flush = (objc_typed_flush_func)fflush;
                   1518:   s->writing_root_p = 0;
                   1519:   if (mode == OBJC_READONLY)
                   1520:     {
                   1521:       s->class_table = hash_new(8, (hash_func_type)hash_string,
                   1522:                                (compare_func_type)compare_strings);
                   1523:       s->object_refs = hash_new(8, (hash_func_type)hash_ptr,
                   1524:                                (compare_func_type)compare_ptrs);
                   1525:       s->read = (objc_typed_read_func)__objc_fread;
                   1526:       s->write = (objc_typed_write_func)__objc_no_write;
                   1527:       __objc_read_typed_stream_signature (s);
                   1528:     }
                   1529:   else if (mode == OBJC_WRITEONLY)
                   1530:     {
                   1531:       s->class_table = 0;
                   1532:       s->object_refs = 0;
                   1533:       s->read = (objc_typed_read_func)__objc_no_read;
                   1534:       s->write = (objc_typed_write_func)__objc_fwrite;
                   1535:       __objc_write_typed_stream_signature (s);
                   1536:     }      
                   1537:   else
                   1538:     {
                   1539:       objc_close_typed_stream (s);
                   1540:       return NULL;
                   1541:     }
                   1542:   s->type = OBJC_FILE_STREAM;
                   1543:   return s;
                   1544: }
                   1545: 
                   1546: /*
                   1547: ** Open the file named by FILE_NAME in MODE
                   1548: */
                   1549: 
                   1550: TypedStream*
                   1551: objc_open_typed_stream_for_file (const char* file_name, int mode)
                   1552: {
                   1553:   FILE* file = NULL;
                   1554:   TypedStream* s;
                   1555: 
                   1556:   if (mode == OBJC_READONLY)
                   1557:     file = fopen (file_name, "r");
                   1558:   else
                   1559:     file = fopen (file_name, "w");
                   1560: 
                   1561:   if (file)
                   1562:     {
                   1563:       s = objc_open_typed_stream (file, mode);
                   1564:       if (s)
                   1565:        s->type |= OBJC_MANAGED_STREAM;
                   1566:       return s;
                   1567:     }
                   1568:   else
                   1569:     return NULL;
                   1570: }
                   1571: 
                   1572: /*
                   1573: ** Close STREAM freeing the structure it self.  If it was opened with 
                   1574: ** objc_open_typed_stream_for_file, the file will also be closed.
                   1575: */
                   1576: 
                   1577: void
                   1578: objc_close_typed_stream (TypedStream* stream)
                   1579: {
                   1580:   if (stream->mode == OBJC_READONLY)
                   1581:     {
                   1582:       __objc_finish_read_root_object (stream); /* Just in case... */
                   1583:       hash_delete (stream->class_table);
                   1584:       hash_delete (stream->object_refs);
                   1585:     }
                   1586: 
                   1587:   hash_delete (stream->stream_table);
                   1588:   hash_delete (stream->object_table);
                   1589: 
                   1590:   if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
                   1591:     fclose ((FILE*)stream->physical);
                   1592: 
                   1593:   free (stream);
                   1594: }
                   1595: 
                   1596: BOOL
                   1597: objc_end_of_typed_stream (TypedStream* stream)
                   1598: {
                   1599:   return (*stream->eof)(stream->physical);
                   1600: }
                   1601: 
                   1602: void
                   1603: objc_flush_typed_stream (TypedStream* stream)
                   1604: {
                   1605:   (*stream->flush)(stream->physical);
                   1606: }
                   1607: 
1.1.1.3   root     1608: long
1.1.1.4 ! root     1609: objc_get_stream_class_version (TypedStream* stream, Class class)
1.1       root     1610: {
                   1611:   if (stream->class_table)
1.1.1.3   root     1612:     return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
1.1       root     1613:   else
                   1614:     return class_get_version (class);
                   1615: }
                   1616: 

unix.superglobalmegacorp.com

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