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

1.1       root        1: /* GNU Objective C Runtime archiving
                      2:    Copyright (C) 1993 Free Software Foundation, Inc.
                      3: 
                      4: Author: Kresten Krab Thorup
                      5: 
                      6: This file is part of GNU CC.
                      7: 
                      8: GNU CC is free software; you can redistribute it and/or modify it under the
                      9:    terms of the GNU General Public License as published by the Free Software
                     10:    Foundation; either version 2, or (at your option) any later version.
                     11: 
                     12: GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
                     13:    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
                     14:    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
                     15:    details.
                     16: 
                     17: You should have received a copy of the GNU General Public License along with
                     18:    GNU CC; see the file COPYING.  If not, write to the Free Software
                     19:    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     20: 
                     21: /* As a special exception, if you link this library with files compiled with
                     22:    GCC to produce an executable, this does not cause the resulting executable
                     23:    to be covered by the GNU General Public License. This exception does not
                     24:    however invalidate any other reasons why the executable file might be
                     25:    covered by the GNU General Public License.  */
                     26: 
                     27: #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
                     48: objc_read_class (struct objc_typed_stream* stream, Class** class);
                     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.3 ! root      441:   return objc_write_unsigned_long (stream, CLS_GETNUMBER(class));
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: {
                    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);
1.1.1.3 ! root      475:   unsigned long key;
        !           476:   if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name))))
1.1       root      477:     return objc_write_use_common (stream, key);
                    478:   else
                    479:     {
                    480:       int length;
1.1.1.3 ! root      481:       hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
1.1       root      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
1.1.1.3 ! root      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
1.1       root      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: 
1.1.1.3 ! root      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: 
1.1       root      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:     {
1.1.1.3 ! root      728:       unsigned long key = 0;
1.1       root      729: 
                    730:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
                    731:        {
1.1.1.3 ! root      732:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1       root      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)
1.1.1.3 ! root      742:            hash_add (&stream->stream_table, LONG2PTR(key), *string);
1.1       root      743:          len = (*stream->read)(stream->physical, *string, length);
                    744:          (*string)[length] = '\0';
                    745:        }
                    746:        break;
                    747: 
                    748:       case _B_UCOMM:
                    749:        {
1.1.1.2   root      750:          char *tmp;
1.1.1.3 ! root      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);
1.1.1.2   root      754:          strcpy (*string, tmp);
1.1       root      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) {
1.1.1.2   root      763:            (*string) = (char*)__objc_xmalloc(nbytes+1);
1.1       root      764:            if (key)
1.1.1.3 ! root      765:              hash_add (&stream->stream_table, LONG2PTR(key), *string);
1.1.1.2   root      766:            len = (*stream->read)(stream->physical, *string, nbytes);
1.1       root      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:     {
1.1.1.3 ! root      788:       SEL read_sel = sel_get_any_uid ("read:");
        !           789:       unsigned long key = 0;
1.1       root      790: 
                    791:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register common */
                    792:        {
1.1.1.3 ! root      793:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1       root      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)
1.1.1.3 ! root      809:            hash_add (&stream->object_table, LONG2PTR(key), *object);
1.1       root      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...");
1.1.1.3 ! root      825:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
        !           826:          (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
1.1       root      827:        }
                    828: 
                    829:       else if (buf[0] == (_B_EXT | _BX_OBJREF))        /* a forward reference */
                    830:        {
                    831:          struct objc_list* other;
1.1.1.3 ! root      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));
1.1       root      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:     {
1.1.1.3 ! root      858:       unsigned long key = 0;
1.1       root      859: 
                    860:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
                    861:        {
1.1.1.3 ! root      862:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1       root      863:          len = (*stream->read)(stream->physical, buf, 1);
                    864:        }
                    865: 
                    866:       if (buf[0] == (_B_EXT | _BX_CLASS))
                    867:        {
                    868:          char* class_name;
1.1.1.3 ! root      869:          unsigned long version;
1.1       root      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)
1.1.1.3 ! root      878:            hash_add (&stream->stream_table, LONG2PTR(key), *class);
1.1       root      879: 
1.1.1.3 ! root      880:          objc_read_unsigned_long(stream, &version);
1.1       root      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...");
1.1.1.3 ! root      888:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
        !           889:          (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
1.1       root      890:          if (!*class)
1.1.1.3 ! root      891:            __objc_fatal("cannot find class for key %lu", key);
1.1       root      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:     {
1.1.1.3 ! root      907:       unsigned long key = 0;
1.1       root      908: 
                    909:       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
                    910:        {
1.1.1.3 ! root      911:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
1.1       root      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);
1.1.1.3 ! root      921:          (*selector) = sel_get_any_uid(selector_name);
1.1       root      922:          free (selector_name);
                    923: 
                    924:          /* register */
                    925:          if (key)
1.1.1.3 ! root      926:            hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
1.1       root      927:        }
                    928: 
                    929:       else if ((buf[0]&_B_CODE) == _B_UCOMM)
                    930:        {
                    931:          if (key)
                    932:            __objc_fatal("cannot register use upcode...");
1.1.1.3 ! root      933:          len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
        !           934:          (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
1.1       root      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: 
1.1.1.3 ! root      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: 
1.1       root     1000:   case _C_CHARPTR:
1.1.1.2   root     1001:     return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
1.1       root     1002:     break;
                   1003: 
                   1004:   case _C_ATOM:
1.1.1.2   root     1005:     return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data));
1.1       root     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: 
1.1.1.3 ! root     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: 
1.1       root     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: 
1.1.1.3 ! root     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: 
1.1       root     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: 
1.1.1.3 ! root     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: 
1.1       root     1123:   default:
1.1.1.2   root     1124:     fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
1.1       root     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: 
1.1.1.3 ! root     1148:   for (c = type; *c; c = objc_skip_typespec (c))
1.1       root     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: 
1.1.1.3 ! root     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: 
1.1       root     1197:       case _C_CHARPTR:
                   1198:        {
1.1.1.2   root     1199:          char** str = va_arg(args, char**);
                   1200:          res = objc_write_string (stream, *str, strlen(*str));
1.1       root     1201:        }
                   1202:        break;
                   1203: 
                   1204:       case _C_ATOM:
                   1205:        {
1.1.1.2   root     1206:          char** str = va_arg(args, char**);
                   1207:          res = objc_write_string_atomic (stream, *str, strlen(*str));
1.1       root     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*));
1.1.1.3 ! root     1217:          t = objc_skip_typespec (t);
1.1       root     1218:          if (*t != _C_ARY_E)
                   1219:            __objc_fatal("expected `]', got: %s", t);
                   1220:        }
                   1221:        break; 
                   1222:        
                   1223:       default:
1.1.1.2   root     1224:        fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type);
1.1       root     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: 
1.1.1.3 ! root     1247:   for (c = type; *c; c = objc_skip_typespec(c))
1.1       root     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: 
1.1.1.3 ! root     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: 
1.1       root     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*));
1.1.1.3 ! root     1308:          t = objc_skip_typespec (t);
1.1       root     1309:          if (*t != _C_ARY_E)
                   1310:            __objc_fatal("expected `]', got: %s", t);
                   1311:        }
                   1312:        break; 
                   1313:        
                   1314:       default:
1.1.1.2   root     1315:        fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
1.1       root     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: 
1.1.1.3 ! root     1365: static void
        !          1366: __objc_free (void* p)
        !          1367: {
        !          1368:   free (p);
        !          1369: }
        !          1370: 
1.1       root     1371: static int 
                   1372: __objc_fread(FILE* file, char* data, int len)
                   1373: {
                   1374:   return fread(data, len, 1, file);
                   1375: }
                   1376: 
                   1377: static int 
                   1378: __objc_fwrite(FILE* file, char* data, int len)
                   1379: {
                   1380:   return fwrite(data, len, 1, file);
                   1381: }
                   1382: 
                   1383: static int
                   1384: __objc_feof(FILE* file)
                   1385: {
                   1386:   return feof(file);
                   1387: }
                   1388: 
                   1389: static int 
                   1390: __objc_no_write(FILE* file, char* data, int len)
                   1391: {
                   1392:   __objc_fatal ("TypedStream not open for writing");
                   1393: }
                   1394: 
                   1395: static int 
                   1396: __objc_no_read(FILE* file, char* data, int len)
                   1397: {
                   1398:   __objc_fatal ("TypedStream not open for reading");
                   1399: }
                   1400: 
                   1401: static int
                   1402: __objc_read_typed_stream_signature (TypedStream* stream)
                   1403: {
                   1404:   char buffer[80];
                   1405:   int pos = 0;
                   1406:   do
                   1407:     (*stream->read)(stream->physical, buffer+pos, 1);
                   1408:   while (buffer[pos++] != '\0');
                   1409:   sscanf (buffer, "GNU TypedStream %d", &stream->version);
                   1410:   if (stream->version != OBJC_TYPED_STREAM_VERSION)
                   1411:     __objc_fatal ("cannot handle TypedStream version %d", stream->version);
                   1412:   return 1;
                   1413: }
                   1414: 
                   1415: static int
                   1416: __objc_write_typed_stream_signature (TypedStream* stream)
                   1417: {
                   1418:   char buffer[80];
                   1419:   sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
                   1420:   stream->version = OBJC_TYPED_STREAM_VERSION;
                   1421:   (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
                   1422:   return 1;
                   1423: }
                   1424: 
                   1425: static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
                   1426: {
                   1427:   hash_delete (stream->object_table);
                   1428:   stream->object_table = hash_new(64,
                   1429:                                  (hash_func_type)hash_ptr,
                   1430:                                  (compare_func_type)compare_ptrs);
                   1431: }
                   1432: 
                   1433: static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
                   1434: {
                   1435:   node_ptr node;
1.1.1.3 ! root     1436:   struct objc_list* free_list;
        !          1437:   SEL awake_sel = sel_get_any_uid ("awake");
1.1       root     1438: 
                   1439:   /* resolve object forward references */
1.1.1.3 ! root     1440:   free_list = list_cons(NULL, NULL);
1.1       root     1441:   for (node = hash_next (stream->object_refs, NULL); node;
                   1442:        node = hash_next (stream->object_refs, node))
                   1443:     {
                   1444:       struct objc_list* reflist = node->value;
                   1445:       const void* key = node->key;
                   1446:       id object = hash_value_for_key (stream->object_table, key);
                   1447:       while(reflist)
                   1448:        {
                   1449:          *((id*)reflist->head) = object;
1.1.1.3 ! root     1450:           if (list_find(&free_list, reflist) == NULL)
        !          1451:            free_list = list_cons (reflist, free_list);
1.1       root     1452:          reflist = reflist->tail;
                   1453:        }
                   1454:     }
1.1.1.3 ! root     1455:   list_mapcar (free_list, __objc_free);
        !          1456:   list_free (free_list);
1.1       root     1457: 
                   1458:   /* empty object reference table */
                   1459:   hash_delete (stream->object_refs);
                   1460:   stream->object_refs = hash_new(8, (hash_func_type)hash_ptr,
                   1461:                                 (compare_func_type)compare_ptrs);
                   1462:   
                   1463:   /* call -awake for all objects read  */
                   1464:   if (awake_sel)
                   1465:     {
                   1466:       for (node = hash_next (stream->object_table, NULL); node;
                   1467:           node = hash_next (stream->object_table, node))
                   1468:        {
                   1469:          id object = node->value;
                   1470:          if (__objc_responds_to (object, awake_sel))
                   1471:            (*objc_msg_lookup(object, awake_sel))(object, awake_sel);
                   1472:        }
                   1473:     }
                   1474: 
                   1475:   /* empty object table */
                   1476:   hash_delete (stream->object_table);
                   1477:   stream->object_table = hash_new(64,
                   1478:                                  (hash_func_type)hash_ptr,
                   1479:                                  (compare_func_type)compare_ptrs);
                   1480: }
                   1481: 
                   1482: /*
                   1483: ** Open the stream PHYSICAL in MODE
                   1484: */
                   1485: 
                   1486: TypedStream* 
                   1487: objc_open_typed_stream (FILE* physical, int mode)
                   1488: {
                   1489:   TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
                   1490: 
                   1491:   s->mode = mode;
                   1492:   s->physical = physical;
                   1493:   s->stream_table = hash_new(64,
                   1494:                             (hash_func_type)hash_ptr,
                   1495:                             (compare_func_type)compare_ptrs);
                   1496:   s->object_table = hash_new(64,
                   1497:                             (hash_func_type)hash_ptr,
                   1498:                             (compare_func_type)compare_ptrs);
                   1499:   s->eof = (objc_typed_eof_func)__objc_feof;
                   1500:   s->flush = (objc_typed_flush_func)fflush;
                   1501:   s->writing_root_p = 0;
                   1502:   if (mode == OBJC_READONLY)
                   1503:     {
                   1504:       s->class_table = hash_new(8, (hash_func_type)hash_string,
                   1505:                                (compare_func_type)compare_strings);
                   1506:       s->object_refs = hash_new(8, (hash_func_type)hash_ptr,
                   1507:                                (compare_func_type)compare_ptrs);
                   1508:       s->read = (objc_typed_read_func)__objc_fread;
                   1509:       s->write = (objc_typed_write_func)__objc_no_write;
                   1510:       __objc_read_typed_stream_signature (s);
                   1511:     }
                   1512:   else if (mode == OBJC_WRITEONLY)
                   1513:     {
                   1514:       s->class_table = 0;
                   1515:       s->object_refs = 0;
                   1516:       s->read = (objc_typed_read_func)__objc_no_read;
                   1517:       s->write = (objc_typed_write_func)__objc_fwrite;
                   1518:       __objc_write_typed_stream_signature (s);
                   1519:     }      
                   1520:   else
                   1521:     {
                   1522:       objc_close_typed_stream (s);
                   1523:       return NULL;
                   1524:     }
                   1525:   s->type = OBJC_FILE_STREAM;
                   1526:   return s;
                   1527: }
                   1528: 
                   1529: /*
                   1530: ** Open the file named by FILE_NAME in MODE
                   1531: */
                   1532: 
                   1533: TypedStream*
                   1534: objc_open_typed_stream_for_file (const char* file_name, int mode)
                   1535: {
                   1536:   FILE* file = NULL;
                   1537:   TypedStream* s;
                   1538: 
                   1539:   if (mode == OBJC_READONLY)
                   1540:     file = fopen (file_name, "r");
                   1541:   else
                   1542:     file = fopen (file_name, "w");
                   1543: 
                   1544:   if (file)
                   1545:     {
                   1546:       s = objc_open_typed_stream (file, mode);
                   1547:       if (s)
                   1548:        s->type |= OBJC_MANAGED_STREAM;
                   1549:       return s;
                   1550:     }
                   1551:   else
                   1552:     return NULL;
                   1553: }
                   1554: 
                   1555: /*
                   1556: ** Close STREAM freeing the structure it self.  If it was opened with 
                   1557: ** objc_open_typed_stream_for_file, the file will also be closed.
                   1558: */
                   1559: 
                   1560: void
                   1561: objc_close_typed_stream (TypedStream* stream)
                   1562: {
                   1563:   if (stream->mode == OBJC_READONLY)
                   1564:     {
                   1565:       __objc_finish_read_root_object (stream); /* Just in case... */
                   1566:       hash_delete (stream->class_table);
                   1567:       hash_delete (stream->object_refs);
                   1568:     }
                   1569: 
                   1570:   hash_delete (stream->stream_table);
                   1571:   hash_delete (stream->object_table);
                   1572: 
                   1573:   if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
                   1574:     fclose ((FILE*)stream->physical);
                   1575: 
                   1576:   free (stream);
                   1577: }
                   1578: 
                   1579: BOOL
                   1580: objc_end_of_typed_stream (TypedStream* stream)
                   1581: {
                   1582:   return (*stream->eof)(stream->physical);
                   1583: }
                   1584: 
                   1585: void
                   1586: objc_flush_typed_stream (TypedStream* stream)
                   1587: {
                   1588:   (*stream->flush)(stream->physical);
                   1589: }
                   1590: 
1.1.1.3 ! root     1591: long
1.1       root     1592: objc_get_stream_class_version (TypedStream* stream, Class* class)
                   1593: {
                   1594:   if (stream->class_table)
1.1.1.3 ! root     1595:     return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
1.1       root     1596:   else
                   1597:     return class_get_version (class);
                   1598: }
                   1599: 

unix.superglobalmegacorp.com

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