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

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

unix.superglobalmegacorp.com

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