/* Interface for the Object class for Objective-C.
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU CC.
- perform:(SEL)aSel with:anObject1 with:anObject2;
/* Forwarding */
-- forward:(SEL)aSel :(arglist_t)argFrame;
-- performv:(SEL)aSel :(arglist_t)argFrame;
+- (retval_t)forward:(SEL)aSel :(arglist_t)argFrame;
+- (retval_t)performv:(SEL)aSel :(arglist_t)argFrame;
/* Posing */
+ poseAs:(Class*)aClassObject;
/* Archiving */
+ (int)version;
+ setVersion:(int)aVersion;
-
-#ifndef __alpha__ /* TypedStream not supported on alpha yet. */
+ (int)streamVersion: (TypedStream*)aStream;
- read: (TypedStream*)aStream;
- write: (TypedStream*)aStream;
-#endif
-
- awake;
@end
however invalidate any other reasons why the executable file might be
covered by the GNU General Public License. */
-/*
-** Note: This version assumes that int and longs are both 32bit.
-*/
-
-#ifndef __alpha__
-
#include "runtime.h"
#include "typedstream.h"
+#include "encoding.h"
+
+extern 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))
#define __objc_fatal(format, args...) \
{ fprintf(stderr, "archiving: "); \
static int
objc_read_class (struct objc_typed_stream* stream, Class** class);
-static int
-objc_sizeof_type(const char* type);
+int objc_sizeof_type(const char* type);
static int
-objc_write_use_common (struct objc_typed_stream* stream, unsigned int key);
+objc_write_use_common (struct objc_typed_stream* stream, unsigned long key);
static int
objc_write_register_common (struct objc_typed_stream* stream,
- unsigned int key);
+ unsigned long key);
static int
objc_write_class (struct objc_typed_stream* stream,
struct objc_class* class);
-static const char*
-__objc_skip_type (const char* type);
+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_short (unsigned char* buf, unsigned short val)
{
- if (val <= 0xffU)
- return __objc_code_unsigned_char (buf, val);
-
+ if ((val&_B_VALUE) == val)
+ {
+ buf[0] = val|_B_SINT;
+ return 1;
+ }
else
{
- buf[0] = _B_NINT|0x02;
- buf[1] = val/0x100;
- buf[2] = val%0x100;
- return 3;
+ 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;
}
}
static __inline__ int
__objc_code_short (unsigned char* buf, short val)
{
- if (val > 0)
- return __objc_code_unsigned_short (buf, val);
-
- if (val > -0x7f) /* val > -128 */
- return __objc_code_char (buf, val);
-
- else
- {
- int len = __objc_code_unsigned_short (buf, -val);
- buf[0] |= _B_SIGN;
- return len;
- }
+ int sign = (val < 0);
+ int size = __objc_code_unsigned_short (buf, sign ? -val : val);
+ if (sign)
+ buf[0] |= _B_SIGN;
+ return size;
}
int
static __inline__ int
__objc_code_unsigned_int (unsigned char* buf, unsigned int val)
{
- if (val < 0x10000)
- return __objc_code_unsigned_short (buf, val%0x10000);
-
- else if (val < 0x1000000)
+ if ((val&_B_VALUE) == val)
{
- buf[0] = _B_NINT|3;
- buf[1] = val/0x10000;
- buf[2] = (val%0x10000)/0x100;
- buf[3] = val%0x100;
- return 4;
+ buf[0] = val|_B_SINT;
+ return 1;
}
-
else
{
- buf[0] = _B_NINT|4;
- buf[1] = val/0x1000000;
- buf[2] = (val%0x1000000)/0x10000;
- buf[3] = (val%0x10000)/0x100;
- buf[4] = val%0x100;
- return 5;
+ 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;
}
}
static __inline__ int
__objc_code_int (unsigned char* buf, int val)
{
- if (val >= 0)
- return __objc_code_unsigned_int (buf, val);
+ int sign = (val < 0);
+ int size = __objc_code_unsigned_int (buf, sign ? -val : val);
+ if (sign)
+ buf[0] |= _B_SIGN;
+ return size;
+}
- if (val > -0x7f)
- return __objc_code_char (buf, val);
+int
+objc_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 len = __objc_code_unsigned_int (buf, -val);
- buf[0] |= _B_SIGN;
- return len;
+ 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;
}
}
int
-objc_write_int (struct objc_typed_stream* stream, int value)
+objc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value)
{
- unsigned char buf[sizeof(int)+1];
- int len = __objc_code_int (buf, 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;
+}
+
+int
+objc_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);
+}
+
+
int
objc_write_string (struct objc_typed_stream* stream,
const unsigned char* string, unsigned int nbytes)
objc_write_string_atomic (struct objc_typed_stream* stream,
unsigned char* string, unsigned int nbytes)
{
- unsigned int key;
- if ((key = (unsigned int)hash_value_for_key (stream->stream_table, string)))
+ 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, (void*)key=(unsigned int)string, string);
+ 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 int
-objc_write_register_common (struct objc_typed_stream* stream, unsigned int key)
+objc_write_register_common (struct objc_typed_stream* stream, unsigned long key)
{
- unsigned char buf[sizeof (unsigned int)+2];
- int len = __objc_code_unsigned_int (buf+1, 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;
}
static int
-objc_write_use_common (struct objc_typed_stream* stream, unsigned int key)
+objc_write_use_common (struct objc_typed_stream* stream, unsigned long key)
{
- unsigned char buf[sizeof (unsigned int)+2];
- int len = __objc_code_unsigned_int (buf+1, 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;
__objc_write_object (struct objc_typed_stream* stream, id object)
{
unsigned char buf = '\0';
- SEL write_sel = sel_get_uid ("write:");
+ SEL write_sel = sel_get_any_uid ("write:");
if (object)
{
__objc_write_extension (stream, _BX_OBJECT);
int
objc_write_object_reference (struct objc_typed_stream* stream, id object)
{
- unsigned int key;
- if ((key = (unsigned int)hash_value_for_key (stream->object_table, 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_int (stream, (unsigned int)object);
+ return objc_write_unsigned_long (stream, PTR2LONG (object));
}
int
int
objc_write_object (struct objc_typed_stream* stream, id object)
{
- unsigned int key;
- if ((key = (unsigned int)hash_value_for_key (stream->object_table, 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)
else
{
int length;
- hash_add (&stream->object_table, (void*)key=(unsigned int)object, object);
+ 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_int (stream, CLS_GETNUMBER(class));
+ return objc_write_unsigned_long (stream, CLS_GETNUMBER(class));
}
objc_write_class (struct objc_typed_stream* stream,
struct objc_class* class)
{
- unsigned int key;
- if ((key = (unsigned int)hash_value_for_key (stream->stream_table, 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, (void*)key=(unsigned int)class, class);
+ 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;
objc_write_selector (struct objc_typed_stream* stream, SEL selector)
{
const char* sel_name = sel_get_name (selector);
- unsigned int key;
- if ((key = (unsigned int)hash_value_for_key (stream->stream_table, sel_name)))
+ unsigned long key;
+ 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, (void*)key=(unsigned int)sel_name, (char*)sel_name);
+ 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;
return len;
}
+__inline__ int
+objc_read_long (struct objc_typed_stream* stream, long* value)
+{
+ unsigned char buf[sizeof(long)+1];
+ int len;
+ if ((len = (*stream->read)(stream->physical, buf, 1)))
+ {
+ if ((buf[0] & _B_CODE) == _B_SINT)
+ (*value) = (buf[0] & _B_VALUE);
+
+ else
+ {
+ int pos = 1;
+ int nbytes = buf[0] & _B_NUMBER;
+ if (nbytes > sizeof (long))
+ __objc_fatal("expected long, got bigger");
+ len = (*stream->read)(stream->physical, buf+1, nbytes);
+ (*value) = 0;
+ while (pos <= nbytes)
+ (*value) = ((*value)*0x100) + buf[pos++];
+ if (buf[0] & _B_SIGN)
+ (*value) = -(*value);
+ }
+ }
+ return len;
+}
+
__inline__ int
__objc_read_nbyte_uint (struct objc_typed_stream* stream,
unsigned int nbytes, unsigned int* val)
return len;
}
+int
+__objc_read_nbyte_ulong (struct objc_typed_stream* stream,
+ unsigned int nbytes, unsigned long* val)
+{
+ int len, pos = 0;
+ unsigned char buf[sizeof(unsigned long)+1];
+
+ if (nbytes > sizeof (long))
+ __objc_fatal("expected long, got bigger");
+
+ len = (*stream->read)(stream->physical, buf, nbytes);
+ (*val) = 0;
+ while (pos < nbytes)
+ (*val) = ((*val)*0x100) + buf[pos++];
+ return len;
+}
+
+
+__inline__ int
+objc_read_unsigned_long (struct objc_typed_stream* stream,
+ unsigned long* value)
+{
+ unsigned char buf[sizeof(unsigned long)+1];
+ int len;
+ if ((len = (*stream->read)(stream->physical, buf, 1)))
+ {
+ if ((buf[0] & _B_CODE) == _B_SINT)
+ (*value) = (buf[0] & _B_VALUE);
+
+ else
+ len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value);
+
+ }
+ return len;
+}
+
__inline__ int
objc_read_string (struct objc_typed_stream* stream,
char** string)
int len;
if ((len = (*stream->read)(stream->physical, buf, 1)))
{
- unsigned int key = 0;
+ unsigned long key = 0;
if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
{
- len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
+ len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
len = (*stream->read)(stream->physical, buf, 1);
}
int length = buf[0]&_B_VALUE;
(*string) = (char*)__objc_xmalloc(length+1);
if (key)
- hash_add (&stream->stream_table, (void*)key, *string);
+ hash_add (&stream->stream_table, LONG2PTR(key), *string);
len = (*stream->read)(stream->physical, *string, length);
(*string)[length] = '\0';
}
case _B_UCOMM:
{
char *tmp;
- len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), &key);
- tmp = hash_value_for_key (stream->stream_table, (void*)key);
- *string = __objc_xmalloc (strlen (tmp) + 1);
+ len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
+ tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key));
+ *string = __objc_xmalloc (strlen(tmp) + 1);
strcpy (*string, tmp);
}
break;
if (len) {
(*string) = (char*)__objc_xmalloc(nbytes+1);
if (key)
- hash_add (&stream->stream_table, (void*)key, *string);
+ hash_add (&stream->stream_table, LONG2PTR(key), *string);
len = (*stream->read)(stream->physical, *string, nbytes);
(*string)[nbytes] = '\0';
}
int len;
if ((len = (*stream->read)(stream->physical, buf, 1)))
{
- SEL read_sel = sel_get_uid ("read:");
- unsigned int key = 0;
+ SEL read_sel = sel_get_any_uid ("read:");
+ unsigned long key = 0;
if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
{
- len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
+ len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
len = (*stream->read)(stream->physical, buf, 1);
}
/* register? */
if (key)
- hash_add (&stream->object_table, (void*)key, *object);
+ hash_add (&stream->object_table, LONG2PTR(key), *object);
/* send -read: */
if (__objc_responds_to (*object, read_sel))
{
if (key)
__objc_fatal("cannot register use upcode...");
- len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
- (*object) = hash_value_for_key (stream->object_table, (void*)key);
+ len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
+ (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
}
else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
{
struct objc_list* other;
- len = objc_read_unsigned_int (stream, &key);
- other = (struct objc_list*)hash_value_for_key (stream->object_refs, (void*)key);
- hash_add (&stream->object_refs, (void*)key, (void*)list_cons(object, other));
+ len = objc_read_unsigned_long (stream, &key);
+ other = (struct objc_list*)hash_value_for_key (stream->object_refs, LONG2PTR(key));
+ hash_add (&stream->object_refs, LONG2PTR(key), (void*)list_cons(object, other));
}
else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
int len;
if ((len = (*stream->read)(stream->physical, buf, 1)))
{
- unsigned int key = 0;
+ unsigned long key = 0;
if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
{
- len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
+ len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
len = (*stream->read)(stream->physical, buf, 1);
}
if (buf[0] == (_B_EXT | _BX_CLASS))
{
char* class_name;
- int version;
+ unsigned long version;
/* get class */
len = objc_read_string (stream, &class_name);
/* register */
if (key)
- hash_add (&stream->stream_table, (void*)key, *class);
+ hash_add (&stream->stream_table, LONG2PTR(key), *class);
- objc_read_unsigned_int(stream, &version);
+ objc_read_unsigned_long(stream, &version);
hash_add (&stream->class_table, (*class)->name, (void*)version);
}
{
if (key)
__objc_fatal("cannot register use upcode...");
- len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
- (*class) = hash_value_for_key (stream->stream_table, (void*)key);
+ len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
+ (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
if (!*class)
- __objc_fatal("cannot find class for key %x", key);
+ __objc_fatal("cannot find class for key %lu", key);
}
else
int len;
if ((len = (*stream->read)(stream->physical, buf, 1)))
{
- unsigned int key = 0;
+ unsigned long key = 0;
if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
{
- len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
+ len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
len = (*stream->read)(stream->physical, buf, 1);
}
/* get selector */
len = objc_read_string (stream, &selector_name);
- (*selector) = sel_get_uid(selector_name);
+ (*selector) = sel_get_any_uid(selector_name);
free (selector_name);
/* register */
if (key)
- hash_add (&stream->stream_table, (void*)key, *selector);
+ hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
}
else if ((buf[0]&_B_CODE) == _B_UCOMM)
{
if (key)
__objc_fatal("cannot register use upcode...");
- len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
- (*selector) = hash_value_for_key (stream->stream_table, (void*)key);
+ len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
+ (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
}
else
return len;
}
-static int
-objc_sizeof_type(const char* type)
-{
- switch(*type) {
- case _C_ID: return sizeof(id);
- break;
-
- case _C_CLASS:
- return sizeof(Class*);
- break;
-
- case _C_SEL:
- return sizeof(SEL);
- break;
-
- case _C_CHR:
- return sizeof(char);
- break;
-
- case _C_UCHR:
- return sizeof(unsigned char);
- break;
-
- case _C_SHT:
- return sizeof(short);
- break;
-
- case _C_USHT:
- return sizeof(unsigned short);
- break;
-
- case _C_INT:
- case _C_LNG:
- return sizeof(int);
- break;
-
- case _C_UINT:
- case _C_ULNG:
- return sizeof(unsigned int);
- break;
-
- case _C_ATOM:
- case _C_CHARPTR:
- return sizeof(char*);
- break;
-
- default:
- fprintf(stderr, "objc_sizeof_type: cannot parse typespec: %s\n", type);
- abort();
- }
-}
-
-
-static const char*
-__objc_skip_type (const char* type)
-{
- switch (*type) {
- case _C_ID:
- case _C_CLASS:
- case _C_SEL:
- case _C_CHR:
- case _C_UCHR:
- case _C_CHARPTR:
- case _C_ATOM:
- case _C_SHT:
- case _C_USHT:
- case _C_INT:
- case _C_UINT:
- case _C_LNG:
- case _C_ULNG:
- case _C_FLT:
- case _C_DBL:
- return ++type;
- break;
-
- case _C_ARY_B:
- while(isdigit(*++type));
- type = __objc_skip_type(type);
- if (*type == _C_ARY_E)
- return ++type;
- else
- __objc_fatal("cannot parse typespec: %s", type);
- break;
-
- default:
- fprintf(stderr, "__objc_skip_type: cannot parse typespec: %s\n", type);
- abort();
- }
-}
-
/*
** USER LEVEL FUNCTIONS
*/
break;
case _C_INT:
- case _C_LNG:
return objc_write_int(stream, *(int*)data);
break;
case _C_UINT:
- case _C_ULNG:
return objc_write_unsigned_int(stream, *(unsigned int*)data);
break;
+ case _C_LNG:
+ return objc_write_long(stream, *(long*)data);
+ break;
+
+ case _C_ULNG:
+ return objc_write_unsigned_long(stream, *(unsigned long*)data);
+ break;
+
case _C_CHARPTR:
return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
break;
}
break;
+ case _C_STRUCT_B:
+ {
+ int acc_size = 0;
+ int align;
+ while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
+ while (*type != _C_STRUCT_E);
+ {
+ align = objc_alignof_type (type); /* padd to alignment */
+ acc_size += ROUND (acc_size, align);
+ objc_write_type (stream, type, ((char*)data)+acc_size);
+ acc_size += objc_sizeof_type (type); /* add component size */
+ type = objc_skip_typespec (type); /* skip component */
+ }
+ return 1;
+ }
+
default:
fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
abort();
break;
case _C_INT:
- case _C_LNG:
return objc_read_int (stream, (int*)data);
break;
case _C_UINT:
- case _C_ULNG:
return objc_read_unsigned_int (stream, (unsigned int*)data);
break;
+ case _C_LNG:
+ return objc_read_long (stream, (long*)data);
+ break;
+
+ case _C_ULNG:
+ return objc_read_unsigned_long (stream, (unsigned long*)data);
+ break;
+
case _C_CHARPTR:
case _C_ATOM:
return objc_read_string (stream, (char**)data);
}
break;
+ case _C_STRUCT_B:
+ {
+ int acc_size = 0;
+ int align;
+ while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
+ while (*type != _C_STRUCT_E);
+ {
+ align = objc_alignof_type (type); /* padd to alignment */
+ acc_size += ROUND (acc_size, align);
+ objc_read_type (stream, type, ((char*)data)+acc_size);
+ acc_size += objc_sizeof_type (type); /* add component size */
+ type = objc_skip_typespec (type); /* skip component */
+ }
+ return 1;
+ }
+
default:
fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
abort();
va_start(args, type);
- for (c = type; *c; c = __objc_skip_type (c))
+ for (c = type; *c; c = objc_skip_typespec (c))
{
switch(*c) {
case _C_ID:
break;
case _C_INT:
- case _C_LNG:
res = objc_write_int(stream, *va_arg(args, int*));
break;
case _C_UINT:
- case _C_ULNG:
res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
break;
+ case _C_LNG:
+ res = objc_write_long(stream, *va_arg(args, long*));
+ break;
+
+ case _C_ULNG:
+ res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*));
+ break;
+
case _C_CHARPTR:
{
char** str = va_arg(args, char**);
const char* t = c;
while (isdigit(*++t));
res = objc_write_array (stream, t, len, va_arg(args, void*));
- t = __objc_skip_type (t);
+ t = objc_skip_typespec (t);
if (*t != _C_ARY_E)
__objc_fatal("expected `]', got: %s", t);
}
va_start(args, type);
- for (c = type; *c; c = __objc_skip_type(c))
+ for (c = type; *c; c = objc_skip_typespec(c))
{
switch(*c) {
case _C_ID:
break;
case _C_INT:
- case _C_LNG:
res = objc_read_int(stream, va_arg(args, int*));
break;
case _C_UINT:
- case _C_ULNG:
res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
break;
+ case _C_LNG:
+ res = objc_read_long(stream, va_arg(args, long*));
+ break;
+
+ case _C_ULNG:
+ res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*));
+ break;
+
case _C_CHARPTR:
case _C_ATOM:
{
const char* t = c;
while (isdigit(*++t));
res = objc_read_array (stream, t, len, va_arg(args, void*));
- t = __objc_skip_type (t);
+ t = objc_skip_typespec (t);
if (*t != _C_ARY_E)
__objc_fatal("expected `]', got: %s", t);
}
static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
{
node_ptr node;
- SEL awake_sel = sel_get_uid ("awake");
+ SEL awake_sel = sel_get_any_uid ("awake");
/* resolve object forward references */
for (node = hash_next (stream->object_refs, NULL); node;
TypedStream*
objc_open_typed_stream (FILE* physical, int mode)
{
- int fflush(FILE*);
-
TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
s->mode = mode;
(*stream->flush)(stream->physical);
}
-int
+long
objc_get_stream_class_version (TypedStream* stream, Class* class)
{
if (stream->class_table)
- return (int) hash_value_for_key (stream->class_table, class->name);
+ return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
else
return class_get_version (class);
}
-#endif /* __alpha__ */
abort();
}
+/* This function provides a way to enumerate all the classes in the
+ executable. Pass *ENUM_STATE == NULL to start the enumeration. The
+ function will return 0 when there are no more classes.
+ For example:
+ id class;
+ void *es = NULL;
+ while ((class = objc_next_class(&es)))
+ ... do something with class;
+*/
+Class*
+objc_next_class(void **enum_state)
+{
+ /* make sure the table is there */
+ assert(__objc_class_hash);
+
+ *(node_ptr*)enum_state =
+ hash_next(__objc_class_hash, *(node_ptr*)enum_state);
+ if (*(node_ptr*)enum_state)
+ return (*(node_ptr*)enum_state)->value;
+ return (Class*)0;
+}
/* Resolve super/subclass links for all classes. The only thing we
can be sure of is that the class_pointer for class objects point
Class*
class_pose_as (Class* impostor, Class* super_class)
{
+ node_ptr node;
+ Class* class1;
+
if (!CLS_ISRESOLV (impostor))
__objc_resolve_class_links ();
{
Class **subclass = &(super_class->subclass_list);
- BOOL super_is_base_class = NO;
/* move subclasses of super_class to impostor */
while (*subclass)
{
Class *nextSub = (*subclass)->sibling_class;
- /* this happens when super_class is a base class */
- if (*subclass == CLASSOF (super_class))
- {
- super_is_base_class = YES;
- }
- else if (*subclass != impostor)
+ if (*subclass != impostor)
{
Class *sub = *subclass;
sub->sibling_class = impostor->subclass_list;
sub->super_class = impostor;
impostor->subclass_list = sub;
-
- /* meta classes */
- CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list;
- CLASSOF (sub)->super_class = CLASSOF (impostor);
- CLASSOF (impostor)->subclass_list = CLASSOF (sub);
+
+ /* It will happen that SUB is not a class object if it is
+ the top of the meta class hierachy chain. (root
+ meta-class objects inherit theit class object) If that is
+ the case... dont mess with the meta-meta class. */
+ if (CLS_ISCLASS (sub))
+ {
+ /* meta classes */
+ CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list;
+ CLASSOF (sub)->super_class = CLASSOF (impostor);
+ CLASSOF (impostor)->subclass_list = CLASSOF (sub);
+ }
}
*subclass = nextSub;
/* set impostor to have no sibling classes */
impostor->sibling_class = 0;
CLASSOF (impostor)->sibling_class = 0;
-
- /* impostor has a sibling... */
- if (super_is_base_class)
- {
- CLASSOF (super_class)->sibling_class = 0;
- impostor->sibling_class = CLASSOF (super_class);
- }
}
- /* check relationship of impostor and super_class */
+ /* check relationship of impostor and super_class is kept. */
assert (impostor->super_class == super_class);
assert (CLASSOF (impostor)->super_class == CLASSOF (super_class));
- /* by now, the re-organization of the class hierachy
- is done. We only need to update various tables. */
-
- /* First, we change the names in the hash table.
- This will change the behavior of objc_get_class () */
- {
- char* buffer = (char*) __objc_xmalloc(strlen (super_class->name) + 2);
-
- strcpy (buffer+1, super_class->name);
- buffer[0] = '*';
+ /* This is how to update the lookup table. Regardless of
+ what the keys of the hashtable is, change all values that are
+ suprecalss into impostor. */
- /* keep on prepending '*' until the name is unique */
- while (hash_value_for_key (__objc_class_hash, buffer))
- {
- char *bbuffer = (char*) __objc_xmalloc (strlen (buffer)+2);
-
- strcpy (bbuffer+1, buffer);
- bbuffer[0] = '*';
- free (buffer);
- buffer = bbuffer;
- }
-
- hash_remove (__objc_class_hash, super_class->name);
- hash_add (&__objc_class_hash, buffer, super_class);
- hash_add (&__objc_class_hash, super_class->name, impostor);
-
- /* Note that -name and +name will still respond with
- the same strings as before. This way any
- -isKindOfGivenName: will always work. */
- }
+ for (node = hash_next (__objc_class_hash, NULL); node;
+ node = hash_next (__objc_class_hash, node))
+ {
+ class1 = (Class*)node->value;
+ if (class1 == super_class)
+ {
+ node->value = impostor; /* change hash table value */
+ }
+ }
/* next, we update the dispatch tables... */
- {
- Class *subclass;
-
- for (subclass = impostor->subclass_list;
- subclass; subclass = subclass->sibling_class)
- {
- /* we use the opportunity to check what we did */
- assert (subclass->super_class == impostor);
- assert (CLASSOF (subclass)->super_class == CLASSOF (impostor));
-
- __objc_update_dispatch_table_for_class (CLASSOF (subclass));
- __objc_update_dispatch_table_for_class (subclass);
- }
- }
+ __objc_update_dispatch_table_for_class (CLASSOF (impostor));
+ __objc_update_dispatch_table_for_class (impostor);
return impostor;
}
+
({ typeof(X) __x = (X), __y = (Y); \
(__x < __y ? __x : __y); })
+#define ROUND(V, A) \
+ ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+ __a*((__v+__a-1)/__a); })
+
static inline int
atoi (const char* str)
while (*type != _C_STRUCT_E);
{
align = objc_alignof_type (type); /* padd to alignment */
- if ((acc_size % align) != 0)
- acc_size += align - (acc_size % align);
+ acc_size += ROUND (acc_size, align);
acc_size += objc_sizeof_type (type); /* add component size */
type = objc_skip_typespec (type); /* skip component */
}
{
int size = objc_sizeof_type (type);
int align = objc_alignof_type (type);
-
- if ((size % align) != 0)
- return size + align - (size % align);
- else
- return size;
+ return ROUND (size, align);
}
/*
int size = objc_sizeof_type (type);
int wordsize = sizeof (void*);
- if ((size % wordsize) != 0)
- return size + wordsize - (size % wordsize);
- else
- return size;
+ return ROUND (size, wordsize);
}
/*
#define EXPANSION(cache) \
((cache)->size * 2)
+void *__objc_xcalloc (size_t, size_t);
+
cache_ptr
hash_new (unsigned int size, hash_func_type hash_func,
compare_func_type compare_func)
/* The version number of this runtime. This must match the number
defined in gcc (objc-act.c) */
-#define OBJC_VERSION 5
+#define OBJC_VERSION 6
#define PROTOCOL_VERSION 2
/* This list contains all modules currently loaded into the runtime */
/* Is all categories/classes resolved? */
BOOL __objc_dangling_categories = NO;
+extern SEL
+__sel_register_typed_name (const char *name, const char *types,
+ struct objc_selector *orig);
+
+
/* This function is called by constructor functions generated for each
module compiled. (_GLOBAL_$I$...) The purpose of this function is to
gather the module pointers so that they may be processed by the
struct objc_list** cell;
/* The table of selector references for this module */
- SEL *selectors = symtab->refs;
+ SEL selectors = symtab->refs;
/* dummy counter */
int i;
/* Save the module pointer for later processing. (not currently used) */
__objc_module_list = list_cons(module, __objc_module_list);
+ /* Replace referenced selectors from names to SEL's. */
+ if (selectors)
+ {
+ for (i = 0; selectors[i].sel_id; ++i)
+ {
+ const char *name, *type;
+ name = (char*)selectors[i].sel_id;
+ type = (char*)selectors[i].sel_types;
+ __sel_register_typed_name (name, type,
+ (struct objc_selector*)&(selectors[i]));
+ }
+ }
+
/* Parse the classes in the load module and gather selector information. */
DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
for (i = 0; i < symtab->cls_def_cnt; ++i)
__objc_init_protocols (class->protocols);
}
- /* Replace referenced selectors from names to SEL's. */
- if (selectors)
- {
- for (i = 0; selectors[i]; ++i)
- selectors[i] = sel_register_name ((const char *) selectors[i]);
- }
-
/* Process category information from the module. */
for (i = 0; i < symtab->cat_def_cnt; ++i)
{
categories to objects. */
for (cell = &unclaimed_categories;
*cell;
- *cell && ((cell = &(*cell)->tail)))
+ ({ if (*cell) cell = &(*cell)->tail; }))
{
Category_t category = (*cell)->head;
Class* class = objc_lookup_class (category->class_name);
if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
{
fprintf (stderr, "Module %s version %d doesn't match runtime %d\n",
- module->name, module->version, OBJC_VERSION);
+ module->name, (int)module->version, OBJC_VERSION);
if(module->version > OBJC_VERSION)
fprintf (stderr, "Runtime (libobjc.a) is out of date\n");
else if (module->version < OBJC_VERSION)
{
fprintf (stderr,
"Version %d doesn't match runtime protocol version %d\n",
- ((size_t)protos->list[i]->class_pointer),
+ (int)((char*)protos->list[i]->class_pointer-(char*)0),
PROTOCOL_VERSION);
abort ();
}
void (*_objc_error)(id, const char*, va_list) = objc_error;
+#ifdef __alpha__
+#include <stdlib.h>
+extern int write (int, const char*, int);
+extern size_t strlen (const char*);
+#endif
+
void
objc_error(id object, const char* fmt, va_list ap)
{
volatile void
objc_fatal(const char* msg)
{
- write(2, msg, (size_t)strlen((char*)msg));
+ write(2, msg, (int)strlen((const char*)msg));
abort();
}
void*
__objc_xcalloc(size_t nelem, size_t size)
{
- void* res = (void*)calloc(nelem, size);
+#ifdef __alpha__
+ extern bzero (void *, size_t);
+#endif
+ void* res = (void*)malloc(nelem * size);
if(!res)
objc_fatal("Virtual memory exhausted\n");
+ bzero (res, nelem * size);
return res;
}
char *types; /* type encoding */
};
-
-
/* Filer types used to describe Ivars and Methods. */
#define _C_ID '@'
#define _C_CLASS '#'
*/
typedef struct objc_symtab {
unsigned long sel_ref_cnt; /* Unknown. */
- SEL *refs; /* Unknown. */
+ SEL refs; /* Unknown. */
unsigned short cls_def_cnt; /* Number of classes compiled
(defined) in the module. */
unsigned short cat_def_cnt; /* Number of categories
const char* ivar_type; /* Description of the Ivar's
type. Useful for
debuggers. */
- int ivar_offset; /* Byte offset from the base
+ int ivar_offset; /* Byte offset from the base
address of the instance
structure to the variable. */
struct objc_method_list* method_next; /* This variable is used to link
a method list to another. It
is a singly linked list. */
- int method_count; /* Number of methods defined in
+ int method_count; /* Number of methods defined in
this structure. */
struct objc_method {
SEL method_name; /* This variable is the method's
Class* objc_lookup_class(const char *name);
+Class* objc_next_class(void **enum_state);
+
const char *sel_get_name(SEL selector);
+const char *sel_get_type(SEL selector);
+
SEL sel_get_uid(const char *name);
+SEL sel_get_any_uid(const char *name);
+
+SEL sel_get_typed_uid(const char *name, const char*);
+
SEL sel_register_name(const char *name);
+SEL sel_register_typed_name(const char *name, const char*type);
+
+
BOOL sel_is_mapped (SEL aSel);
extern id class_create_instance(Class* class);
#define NO (BOOL)0
/*
-** Definition of a selector. Selectors are really of type unsigned int.
-** The runtime does this mapping from SEL's to names internally in the
-** sel_... operations. You should never use the fact that it is actually
-** an integer, since other Objective-C implementations use other conventions.
+** Definition of a selector. Selectors themselves are not unique, but
+** the sel_id is a unique identifier.
*/
-typedef void* SEL;
+typedef const struct objc_selector
+{
+ void *sel_id;
+ const char *sel_types;
+} *SEL;
+
+inline static BOOL
+sel_eq (SEL s1, SEL s2)
+{
+ if (s1 == 0 || s2 == 0)
+ return s1 == s2;
+ else
+ return s1->sel_id == s2->sel_id;
+}
+
/*
** ObjC uses this typedef for untyped instances.
} *arglist_t; /* argument frame */
-#if defined(__OBJC__)
-#include "objc/sarray.h"
-
-/*
- This is the function called when messages are send to nil. You may
- set a breakpoint in your debugger at this function to catch messages
- too nil.
-*/
-extern id nil_method(id rcv, SEL op, ...);
-
-/*
- The messager is inlined, thus it is defined here directly. The
- inlining is quite time-consuming when optimizing. This will be
- taken care of later by hand-coding the messager in the compiler.
-*/
-extern __inline__ IMP
-objc_msg_lookup(id receiver, SEL op)
-{
- if(receiver)
- return sarray_get(receiver->class_pointer->dtable, (size_t)(op));
- else
- return nil_method;
-}
-
-#else
-
IMP objc_msg_lookup(id receiver, SEL op);
-#endif
-
#ifdef __cplusplus
}
#endif
new = (*_objc_object_alloc)(class);
if (new!=nil)
{
- bzero (new, class->instance_size);
+ memchr (new, 0, class->instance_size);
new->class_pointer = class;
}
return new;
extern int __objc_selector_max_index;
#ifdef DEBUG
-#define DEBUG_PRINTF printf
+#define DEBUG_PRINTF(format, args...) printf (format, ## args)
#else
-#define DEBUG_PRINTF
+#define DEBUG_PRINTF(format, args...)
#endif
BOOL __objc_responds_to (id object, SEL sel); /* for internal use only! */
+SEL __sel_register_typed_name (const char*, const char*,
+ struct objc_selector*);
#endif /* not __objc_runtime_INCLUDE_GNU */
const char* __objc_sparse3_id = "3 level sparse indices";
#endif
+#ifdef __alpha__
+const void *memcpy (void*, const void*, size_t);
+void free (const void*);
+#endif
+
void
sarray_at_put(struct sarray* array, sidx index, void* element)
{
/* The bucket was previously empty (or something like that), */
/* allocate a new. This is the effect of `lazy' allocation */
*the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket));
- memcpy( *the_bucket,array->empty_bucket, sizeof(struct sbucket));
+ memcpy((void *) *the_bucket, (const void*)array->empty_bucket, sizeof(struct sbucket));
(*the_bucket)->version = array->version;
nbuckets += 1;
#define SELECTOR_HASH_SIZE 128
/* Tables mapping selector names to uid and opposite */
-static struct sarray* __objc_selector_array = 0; /* uid -> name */
+static struct sarray* __objc_selector_array = 0; /* uid -> sel */
+static struct sarray* __objc_selector_names = 0; /* uid -> name */
static cache_ptr __objc_selector_hash = 0; /* name -> uid */
static void register_selectors_from_list(MethodList_t);
void __objc_init_selector_tables()
{
__objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
+ __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
__objc_selector_hash
= hash_new (SELECTOR_HASH_SIZE,
(hash_func_type) hash_string,
while (i < method_list->method_count)
{
Method_t method = &method_list->method_list[i];
- method->method_name = sel_register_name ((char*)method->method_name);
+ method->method_name
+ = sel_register_typed_name ((const char*)method->method_name,
+ method->method_types);
i += 1;
}
}
+/* return selector representing name */
+SEL
+sel_get_typed_uid (const char *name, const char *types)
+{
+ struct objc_list *l;
+ sidx i;
+
+ i = (sidx) hash_value_for_key (__objc_selector_hash, name);
+ if (i == 0)
+ return 0;
+
+ for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
+ l; l = l->tail)
+ {
+ SEL s = (SEL)l->head;
+ if (types == 0 || s->sel_types == 0)
+ {
+ if (s->sel_types == types)
+ {
+ return s;
+ }
+ }
+ else if (! strcmp (s->sel_types, types))
+ {
+ return s;
+ }
+ }
+
+ return 0;
+}
+
+/* return selector representing name */
+SEL
+sel_get_any_uid (const char *name)
+{
+ struct objc_list *l;
+ sidx i;
+
+ i = (sidx) hash_value_for_key (__objc_selector_hash, name);
+ if (soffset_decode (i) == 0)
+ return 0;
+
+ l = (struct objc_list*)sarray_get (__objc_selector_array, i);
+ if (l == 0)
+ return 0;
+
+ return (SEL)l->head;
+}
+
/* return selector representing name */
SEL
sel_get_uid (const char *name)
{
- return (SEL) hash_value_for_key (__objc_selector_hash, name);
+ return sel_register_typed_name (name, 0);
}
/* Get name of selector. If selector is unknown, the empty string ""
const char*
sel_get_name (SEL selector)
{
- if ((soffset_decode((sidx)selector) > 0)
- && (soffset_decode((sidx)selector) <= __objc_selector_max_index))
- return sarray_get (__objc_selector_array, (sidx) selector);
+ if ((soffset_decode((sidx)selector->sel_id) > 0)
+ && (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index))
+ return sarray_get (__objc_selector_array, (sidx) selector->sel_id);
else
- return NULL;
+ return 0;
}
BOOL
sel_is_mapped (SEL selector)
{
- unsigned int idx = soffset_decode ((sidx)selector);
+ unsigned int idx = soffset_decode ((sidx)selector->sel_id);
return ((idx > 0) && (idx <= __objc_selector_max_index));
}
+
+const char*
+sel_get_type (SEL selector)
+{
+ if (selector)
+ return selector->sel_types;
+ else
+ return 0;
+}
+
/* The uninstalled dispatch table */
extern struct sarray* __objc_uninstalled_dtable;
/* Store the passed selector name in the selector record and return its
selector value (value returned by sel_get_uid). */
SEL
-sel_register_name (const char *sel)
+__sel_register_typed_name (const char *name, const char *types,
+ struct objc_selector *orig)
{
- SEL j;
+ struct objc_selector* j;
sidx i;
+ struct objc_list *l;
- if ((j = sel_get_uid ((const char *) sel)))
- return j;
-
- /* Save the selector name. */
- __objc_selector_max_index += 1;
- i = soffset_encode(__objc_selector_max_index);
+ i = (sidx) hash_value_for_key (__objc_selector_hash, name);
+ if (soffset_decode (i) != 0)
+ {
+ for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
+ l; l = l->tail)
+ {
+ SEL s = (SEL)l->head;
+ if (types == 0 || s->sel_types == 0)
+ {
+ if (s->sel_types == types)
+ {
+ if (orig)
+ {
+ orig->sel_id = (void*)i;
+ return orig;
+ }
+ else
+ return s;
+ }
+ }
+ else if (strcmp (s->sel_types, types))
+ {
+ if (orig)
+ {
+ orig->sel_id = (void*)i;
+ return orig;
+ }
+ else
+ return s;
+ }
+ }
+ if (orig)
+ j = orig;
+ else
+ j = __objc_xmalloc (sizeof (struct objc_selector));
- DEBUG_PRINTF ("Record selector %s as: %#x\n", sel, i);
+ j->sel_id = (void*)i;
+ j->sel_types = (const char*)types;
+ l = (struct objc_list*)sarray_get (__objc_selector_array, i);
+ }
+ else
+ {
+ __objc_selector_max_index += 1;
+ i = soffset_encode(__objc_selector_max_index);
+ if (orig)
+ j = orig;
+ else
+ j = __objc_xmalloc (sizeof (struct objc_selector));
+
+ j->sel_id = (void*)i;
+ j->sel_types = (const char*)types;
+ l = 0;
+ }
- sarray_at_put_safe (__objc_selector_array, i, (void *) sel);
- hash_add (&__objc_selector_hash, (void *) sel, (void *) i);
+ DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
+ soffset_decode (i));
+
+ {
+ int is_new = (l == 0);
+ l = list_cons ((void*)j, l);
+ sarray_at_put_safe (__objc_selector_names, i, (void *) name);
+ sarray_at_put_safe (__objc_selector_array, i, (void *) l);
+ if (is_new)
+ hash_add (&__objc_selector_hash, (void *) name, (void *) i);
+ }
sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1);
- return (SEL) i;
+ return (SEL) j;
+}
+
+SEL
+sel_register_name (const char *name)
+{
+ return __sel_register_typed_name (name, 0, 0);
+}
+
+SEL
+sel_register_typed_name (const char *name, const char *type)
+{
+ return __sel_register_typed_name (name, type, 0);
}
however invalidate any other reasons why the executable file might be
covered by the GNU General Public License. */
+#include "../tconfig.h"
#include "runtime.h"
#include "sarray.h"
#include "encoding.h"
+/* this is how we hack STRUCT_VALUE to be 1 or 0 */
+#define gen_rtx(args...) 1
+#define rtx int
+
+#if STRUCT_VALUE == 0
+#define INVISIBLE_STRUCT_RETURN 1
+#else
+#define INVISIBLE_STRUCT_RETURN 0
+#endif
+
/* The uninstalled dispatch table */
struct sarray* __objc_uninstalled_dtable = 0;
/* Forward declare some functions */
static void __objc_init_install_dtable(id, SEL);
-static id __objc_missing_method(id, SEL, ...);
+static id __objc_word_forward(id, SEL, ...);
+typedef struct { id many[8]; } __big;
+#if INVISIBLE_STRUCT_RETURN
+static __big
+#else
+static id
+#endif
+__objc_block_forward(id, SEL, ...);
static Method_t search_for_method_in_hierarchy (Class* class, SEL sel);
static Method_t search_for_method_in_list(MethodList_t list, SEL op);
id nil_method(id, SEL, ...);
__inline__ IMP
get_imp (Class* class, SEL sel)
{
- void* res = sarray_get (class->dtable, (size_t) sel);
+ IMP impl;
+ void* res = sarray_get (class->dtable, (size_t) sel->sel_id);
if(res == __objc_init_install_dtable)
- __objc_install_dispatch_table_for_class (class);
- return sarray_get (class->dtable, (size_t) sel);
+ {
+ __objc_install_dispatch_table_for_class (class);
+ res = sarray_get (class->dtable, (size_t) sel->sel_id);
+ }
+ if (res == 0)
+ {
+ const char *t = sel->sel_types;
+ if (t && (*t == '[' || *t == '(' || *t == '{'))
+ res = (IMP)__objc_block_forward;
+ else
+ res = (IMP)__objc_word_forward;
+ }
+ return res;
}
__inline__ BOOL
__objc_responds_to (id object, SEL sel)
{
- return get_imp (object->class_pointer, sel) != __objc_missing_method;
+ void* res = sarray_get (object->class_pointer->dtable, (size_t) sel->sel_id);
+ if(res == __objc_init_install_dtable)
+ {
+ __objc_install_dispatch_table_for_class (object->class_pointer);
+ res = sarray_get (object->class_pointer->dtable, (size_t) sel->sel_id);
+ }
+ return (res != 0);
}
/* This is the lookup function. All entries in the table are either a
__inline__ IMP
objc_msg_lookup(id receiver, SEL op)
{
+ IMP result;
if(receiver)
- return sarray_get(receiver->class_pointer->dtable, (sidx)op);
+ {
+ result = sarray_get(receiver->class_pointer->dtable, (sidx)op->sel_id);
+ if (result == 0)
+ {
+ const char *t = op->sel_types;
+ if (t && (*t == '[' || *t == '(' || *t == '{'))
+ result = (IMP)__objc_block_forward;
+ else
+ result = (IMP)__objc_word_forward;
+ }
+ return result;
+ }
else
return nil_method;
}
return nil_method;
}
+int method_get_sizeof_arguments (Method*);
+
retval_t
objc_msg_sendv(id object, SEL op, arglist_t arg_frame)
{
/* Install real dtable for factory methods */
__objc_install_dispatch_table_for_class (receiver->class_pointer);
-
- if(op != sel_get_uid ("initialize"))
+
+ if (strcmp (sel_get_name (op), "initialize"))
__objc_send_initialize((Class*)receiver);
else
CLS_SETINITIALIZED((Class*)receiver);
args = __builtin_apply_args();
result = __builtin_apply((apply_t)imp, args, 96);
- __builtin_return (result);
+ if (result)
+ __builtin_return (result);
+ else
+ return;
}
/* Send +initialize to class if not already done */
static void __objc_send_initialize(Class* class)
{
- Method_t m;
-
/* This *must* be a class object */
assert(CLS_ISCLASS(class));
assert(!CLS_ISMETA(class));
Method_t method = &method_list->method_list[i];
- if (method->method_name == op)
+ if (method->method_name->sel_id == op->sel_id)
(*method->method_imp)((id) class, op);
}
/* Allocate dtable if nessecary */
if (super == 0)
{
- class->dtable = sarray_new (__objc_selector_max_index,
- __objc_missing_method);
+ class->dtable = sarray_new (__objc_selector_max_index, 0);
}
else
class->dtable = sarray_lazy_copy (super->dtable);
{
Method_t method = &(mlist->method_list[counter]);
sarray_at_put_safe (class->dtable,
- (sidx) method->method_name,
+ (sidx) method->method_name->sel_id,
method->method_imp);
counter -= 1;
}
void __objc_update_dispatch_table_for_class (Class* class)
{
Class* next;
- struct sarray* save;
/* not yet installed -- skip it */
if (class->dtable == __objc_uninstalled_dtable)
if (method->method_name) /* Sometimes these are NULL */
{
/* This is where selector names are transmogriffed to SEL's */
- method->method_name = sel_register_name ((char*)method->method_name);
+ method->method_name =
+ sel_register_typed_name ((const char*)method->method_name,
+ method->method_types);
if (search_for_method_in_list (class->methods, method->method_name)
- && method->method_name != initialize_sel)
+ && method->method_name->sel_id != initialize_sel->sel_id)
{
/* Duplication. Print a error message an change the method name
to NULL. */
Method_t method = &method_list->method_list[i];
if (method->method_name)
- if (method->method_name == op)
+ if (method->method_name->sel_id == op->sel_id)
return method;
}
return NULL;
}
+static retval_t __objc_forward (id object, SEL sel, arglist_t args);
+
+static id
+__objc_word_forward (id rcv, SEL op, ...)
+{
+ void *args, *res;
+
+ args = __builtin_apply_args ();
+ res = __objc_forward (rcv, op, args);
+ if (res)
+ __builtin_return (res);
+ else
+ return res;
+}
+
+#if INVISIBLE_STRUCT_RETURN
+static __big
+#else
+static id
+#endif
+__objc_block_forward (id rcv, SEL op, ...)
+{
+ void *args, *res;
+
+ args = __builtin_apply_args ();
+ res = __objc_forward (rcv, op, args);
+ if (res)
+ __builtin_return (res);
+}
+
/* This fuction is installed in the dispatch table for all methods which are
not implemented. Thus, it is called when a selector is not recognized. */
-static id
-__objc_missing_method (id object, SEL sel, ...)
+static retval_t
+__objc_forward (id object, SEL sel, arglist_t args)
{
IMP imp;
- SEL frwd_sel;
+ static SEL frwd_sel = 0;
SEL err_sel;
/* first try if the object understands forward:: */
- frwd_sel = sel_get_uid("forward::");
- imp = get_imp(object->class_pointer, frwd_sel);
- if(imp != __objc_missing_method)
+ if (!frwd_sel)
+ frwd_sel = sel_get_any_uid("forward::");
+
+ if (__objc_responds_to (object, frwd_sel))
{
- void *result, *args = __builtin_apply_args();
- result = (*imp)(object, frwd_sel, sel, args);
- __builtin_return(result);
+ imp = get_imp(object->class_pointer, frwd_sel);
+ return (*imp)(object, frwd_sel, sel, args);
}
/* If the object recognizes the doesNotRecognize: method then we're going
to send it. */
- err_sel = sel_get_uid ("doesNotRecognize:");
- imp = get_imp (object->class_pointer, err_sel);
- if (imp != __objc_missing_method)
+ err_sel = sel_get_any_uid ("doesNotRecognize:");
+ if (__objc_responds_to (object, err_sel))
{
+ imp = get_imp (object->class_pointer, err_sel);
return (*imp) (object, err_sel, sel);
}
/* The object doesn't recognize the method. Check for responding to
error:. If it does then sent it. */
{
- char msg[256 + strlen ((char*)sel_get_name (sel))
- + strlen ((char*)object->class_pointer->name)];
+ size_t strlen (const char*);
+ char msg[256 + strlen ((const char*)sel_get_name (sel))
+ + strlen ((const char*)object->class_pointer->name)];
sprintf (msg, "(%s) %s does not recognize %s",
(CLS_ISMETA(object->class_pointer)
: "instance" ),
object->class_pointer->name, sel_get_name (sel));
- err_sel = sel_get_uid ("error:");
- imp = get_imp (object->class_pointer, err_sel);
- if (imp != __objc_missing_method)
- return (*imp) (object, sel_get_uid ("error:"), msg);
+ err_sel = sel_get_any_uid ("error:");
+ if (__objc_responds_to (object, err_sel))
+ {
+ imp = get_imp (object->class_pointer, err_sel);
+ return (*imp) (object, sel_get_any_uid ("error:"), msg);
+ }
/* The object doesn't respond to doesNotRecognize: or error:; Therefore,
a default action is taken. */
#endif
);
- printf("arrays: %d = %d bytes\n", narrays, narrays*sizeof(struct sarray));
+ printf("arrays: %d = %ld bytes\n", narrays, (int)narrays*sizeof(struct sarray));
total += narrays*sizeof(struct sarray);
- printf("buckets: %d = %d bytes\n", nbuckets, nbuckets*sizeof(struct sbucket));
+ printf("buckets: %d = %ld bytes\n", nbuckets, (int)nbuckets*sizeof(struct sbucket));
total += nbuckets*sizeof(struct sbucket);
- printf("idxtables: %d = %d bytes\n", idxsize, idxsize*sizeof(void*));
+ printf("idxtables: %d = %ld bytes\n", idxsize, (int)idxsize*sizeof(void*));
total += idxsize*sizeof(void*);
printf("-----------------------------------\n");
printf("total: %d bytes\n", total);
#include "objc/hash.h"
#include <stdio.h>
-#ifndef __alpha__ /* alpha is currently not supported */
-
typedef int (*objc_typed_read_func)(void*, char*, int);
typedef int (*objc_typed_write_func)(void*, const char*, int);
typedef int (*objc_typed_flush_func)(void*);
int objc_write_object_reference (TypedStream* stream, id object);
int objc_write_root_object (TypedStream* stream, id object);
-int objc_get_stream_class_version (TypedStream* stream, Class* class);
+long objc_get_stream_class_version (TypedStream* stream, Class* class);
/*
BOOL objc_end_of_typed_stream (TypedStream* stream);
void objc_flush_typed_stream (TypedStream* stream);
-#endif /* __alpha__ */
-
#endif /* not __typedstream_INCLUDE_GNU */