?? archive.c
字號:
/* GNU Objective C Runtime archiving Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. Contributed by Kresten Krab ThorupThis file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modify it under theterms of the GNU General Public License as published by the Free SoftwareFoundation; either version 2, or (at your option) any later version.GNU CC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU General Public License for moredetails.You should have received a copy of the GNU General Public License along withGNU CC; see the file COPYING. If not, write to the Free SoftwareFoundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. *//* As a special exception, if you link this library with files compiled with GCC to produce an executable, this does not cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. */#include "config.h"#include "runtime.h"#include "typedstream.h"#include "encoding.h"#ifdef HAVE_STDLIB_H#include <stdlib.h>#endifextern int fflush(FILE*);#define ROUND(V, A) \ ({ typeof(V) __v=(V); typeof(A) __a=(A); \ __a*((__v+__a-1)/__a); })#define PTR2LONG(P) (((char*)(P))-(char*)0)#define LONG2PTR(L) (((char*)0)+(L))/* Declare some functions... */static intobjc_read_class (struct objc_typed_stream* stream, Class* class);int objc_sizeof_type(const char* type);static intobjc_write_use_common (struct objc_typed_stream* stream, unsigned long key);static intobjc_write_register_common (struct objc_typed_stream* stream, unsigned long key);static int objc_write_class (struct objc_typed_stream* stream, struct objc_class* class);const char* objc_skip_type (const char* type);static void __objc_finish_write_root_object(struct objc_typed_stream*);static void __objc_finish_read_root_object(struct objc_typed_stream*);static __inline__ int__objc_code_unsigned_char (unsigned char* buf, unsigned char val){ if ((val&_B_VALUE) == val) { buf[0] = val|_B_SINT; return 1; } else { buf[0] = _B_NINT|0x01; buf[1] = val; return 2; }}intobjc_write_unsigned_char (struct objc_typed_stream* stream, unsigned char value){ unsigned char buf[sizeof (unsigned char)+1]; int len = __objc_code_unsigned_char (buf, value); return (*stream->write)(stream->physical, buf, len);}static __inline__ int__objc_code_char (unsigned char* buf, char val){ if (val >= 0) return __objc_code_unsigned_char (buf, val); else { buf[0] = _B_NINT|_B_SIGN|0x01; buf[1] = -val; return 2; }}intobjc_write_char (struct objc_typed_stream* stream, char value){ unsigned char buf[sizeof (char)+1]; int len = __objc_code_char (buf, value); return (*stream->write)(stream->physical, buf, len);}static __inline__ int__objc_code_unsigned_short (unsigned char* buf, unsigned short val){ if ((val&_B_VALUE) == val) { buf[0] = val|_B_SINT; return 1; } else { int c, b; buf[0] = _B_NINT; for (c= sizeof(short); c != 0; c -= 1) if (((val>>(8*(c-1)))%0x100) != 0) break; buf[0] |= c; for (b = 1; c != 0; c--, b++) { buf[b] = (val >> (8*(c-1)))%0x100; } return b; }}intobjc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short value){ unsigned char buf[sizeof (unsigned short)+1]; int len = __objc_code_unsigned_short (buf, value); return (*stream->write)(stream->physical, buf, len);} static __inline__ int__objc_code_short (unsigned char* buf, short val){ int sign = (val < 0); int size = __objc_code_unsigned_short (buf, sign ? -val : val); if (sign) buf[0] |= _B_SIGN; return size;}intobjc_write_short (struct objc_typed_stream* stream, short value){ unsigned char buf[sizeof (short)+1]; int len = __objc_code_short (buf, value); return (*stream->write)(stream->physical, buf, len);} static __inline__ int__objc_code_unsigned_int (unsigned char* buf, unsigned int val){ if ((val&_B_VALUE) == val) { buf[0] = val|_B_SINT; return 1; } else { int c, b; buf[0] = _B_NINT; for (c= sizeof(int); c != 0; c -= 1) if (((val>>(8*(c-1)))%0x100) != 0) break; buf[0] |= c; for (b = 1; c != 0; c--, b++) { buf[b] = (val >> (8*(c-1)))%0x100; } return b; }}intobjc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value){ unsigned char buf[sizeof(unsigned int)+1]; int len = __objc_code_unsigned_int (buf, value); return (*stream->write)(stream->physical, buf, len);}static __inline__ int__objc_code_int (unsigned char* buf, int val){ int sign = (val < 0); int size = __objc_code_unsigned_int (buf, sign ? -val : val); if (sign) buf[0] |= _B_SIGN; return size;}intobjc_write_int (struct objc_typed_stream* stream, int value){ unsigned char buf[sizeof(int)+1]; int len = __objc_code_int (buf, value); return (*stream->write)(stream->physical, buf, len);}static __inline__ int__objc_code_unsigned_long (unsigned char* buf, unsigned long val){ if ((val&_B_VALUE) == val) { buf[0] = val|_B_SINT; return 1; } else { int c, b; buf[0] = _B_NINT; for (c= sizeof(long); c != 0; c -= 1) if (((val>>(8*(c-1)))%0x100) != 0) break; buf[0] |= c; for (b = 1; c != 0; c--, b++) { buf[b] = (val >> (8*(c-1)))%0x100; } return b; }}intobjc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value){ unsigned char buf[sizeof(unsigned long)+1]; int len = __objc_code_unsigned_long (buf, value); return (*stream->write)(stream->physical, buf, len);}static __inline__ int__objc_code_long (unsigned char* buf, long val){ int sign = (val < 0); int size = __objc_code_unsigned_long (buf, sign ? -val : val); if (sign) buf[0] |= _B_SIGN; return size;}intobjc_write_long (struct objc_typed_stream* stream, long value){ unsigned char buf[sizeof(long)+1]; int len = __objc_code_long (buf, value); return (*stream->write)(stream->physical, buf, len);}intobjc_write_string (struct objc_typed_stream* stream, const unsigned char* string, unsigned int nbytes){ unsigned char buf[sizeof(unsigned int)+1]; int len = __objc_code_unsigned_int (buf, nbytes); if ((buf[0]&_B_CODE) == _B_SINT) buf[0] = (buf[0]&_B_VALUE)|_B_SSTR; else /* _B_NINT */ buf[0] = (buf[0]&_B_VALUE)|_B_NSTR; if ((*stream->write)(stream->physical, buf, len) != 0) return (*stream->write)(stream->physical, string, nbytes); else return 0;}intobjc_write_string_atomic (struct objc_typed_stream* stream, unsigned char* string, unsigned int nbytes){ unsigned long key; if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string)))) return objc_write_use_common (stream, key); else { int length; hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string); if ((length = objc_write_register_common (stream, key))) return objc_write_string (stream, string, nbytes); return length; }}static intobjc_write_register_common (struct objc_typed_stream* stream, unsigned long key){ unsigned char buf[sizeof (unsigned long)+2]; int len = __objc_code_unsigned_long (buf+1, key); if (len == 1) { buf[0] = _B_RCOMM|0x01; buf[1] &= _B_VALUE; return (*stream->write)(stream->physical, buf, len+1); } else { buf[1] = (buf[1]&_B_VALUE)|_B_RCOMM; return (*stream->write)(stream->physical, buf+1, len); }}static intobjc_write_use_common (struct objc_typed_stream* stream, unsigned long key){ unsigned char buf[sizeof (unsigned long)+2]; int len = __objc_code_unsigned_long (buf+1, key); if (len == 1) { buf[0] = _B_UCOMM|0x01; buf[1] &= _B_VALUE; return (*stream->write)(stream->physical, buf, 2); } else { buf[1] = (buf[1]&_B_VALUE)|_B_UCOMM; return (*stream->write)(stream->physical, buf+1, len); }}static __inline__ int__objc_write_extension (struct objc_typed_stream* stream, unsigned char code){ if (code <= _B_VALUE) { unsigned char buf = code|_B_EXT; return (*stream->write)(stream->physical, &buf, 1); } else { objc_error(nil, OBJC_ERR_BAD_OPCODE, "__objc_write_extension: bad opcode %c\n", code); return -1; }}__inline__ int__objc_write_object (struct objc_typed_stream* stream, id object){ unsigned char buf = '\0'; SEL write_sel = sel_get_any_uid ("write:"); if (object) { __objc_write_extension (stream, _BX_OBJECT); objc_write_class (stream, object->class_pointer); (*objc_msg_lookup(object, write_sel))(object, write_sel, stream); return (*stream->write)(stream->physical, &buf, 1); } else return objc_write_use_common(stream, 0);}int objc_write_object_reference (struct objc_typed_stream* stream, id object){ unsigned long key; if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object)))) return objc_write_use_common (stream, key); __objc_write_extension (stream, _BX_OBJREF); return objc_write_unsigned_long (stream, PTR2LONG (object));}int objc_write_root_object (struct objc_typed_stream* stream, id object){ int len = 0; if (stream->writing_root_p) objc_error (nil, OBJC_ERR_RECURSE_ROOT, "objc_write_root_object called recursively"); else { stream->writing_root_p = 1; __objc_write_extension (stream, _BX_OBJROOT); if((len = objc_write_object (stream, object))) __objc_finish_write_root_object(stream); stream->writing_root_p = 0; } return len;}int objc_write_object (struct objc_typed_stream* stream, id object){ unsigned long key; if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object)))) return objc_write_use_common (stream, key); else if (object == nil) return objc_write_use_common(stream, 0); else { int length; hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object); if ((length = objc_write_register_common (stream, key))) return __objc_write_object (stream, object); return length; }}#ifdef __alpha__extern int atoi (const char*);extern size_t strlen(const char*);extern size_t strcpy(char*, const char*);#endif__inline__ int__objc_write_class (struct objc_typed_stream* stream, struct objc_class* class){ __objc_write_extension (stream, _BX_CLASS); objc_write_string_atomic(stream, (char*)class->name, strlen((char*)class->name)); return objc_write_unsigned_long (stream, class->version);}static int objc_write_class (struct objc_typed_stream* stream, struct objc_class* class){ unsigned long key; if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class)))) return objc_write_use_common (stream, key); else { int length; hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class); if ((length = objc_write_register_common (stream, key))) return __objc_write_class (stream, class); return length; }}__inline__ int __objc_write_selector (struct objc_typed_stream* stream, SEL selector){ const char* sel_name; __objc_write_extension (stream, _BX_SEL); /* to handle NULL selectors */ if ((SEL)0 == selector) return objc_write_string (stream, "", 0); sel_name = sel_get_name (selector); return objc_write_string (stream, sel_name, strlen ((char*)sel_name));}int objc_write_selector (struct objc_typed_stream* stream, SEL selector){ const char* sel_name; unsigned long key; /* to handle NULL selectors */ if ((SEL)0 == selector) return __objc_write_selector (stream, selector); sel_name = sel_get_name (selector); if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name)))) return objc_write_use_common (stream, key); else { int length; hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name); if ((length = objc_write_register_common (stream, key))) return __objc_write_selector (stream, selector); return length; }}/*** Read operations */__inline__ intobjc_read_char (struct objc_typed_stream* stream, char* val){ unsigned char buf; int len; len = (*stream->read)(stream->physical, &buf, 1); if (len != 0) { if ((buf & _B_CODE) == _B_SINT) (*val) = (buf & _B_VALUE); else if ((buf & _B_NUMBER) == 1) { len = (*stream->read)(stream->physical, val, 1); if (buf&_B_SIGN) (*val) = -1*(*val); } else objc_error(nil, OBJC_ERR_BAD_DATA, "expected 8bit signed int, got %dbit int", (int)(buf&_B_NUMBER)*8); } return len;}__inline__ intobjc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val){ unsigned char buf; int len; if ((len = (*stream->read)(stream->physical, &buf, 1))) { if ((buf & _B_CODE) == _B_SINT) (*val) = (buf & _B_VALUE); else if ((buf & _B_NUMBER) == 1) len = (*stream->read)(stream->physical, val, 1); else
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -