This patch makes selectors in the Objective-C language be pointers to a struct { void *sel_id...

This patch makes selectors in the Objective-C language be pointers
        to a struct { void *sel_id, char *sel_types }, where the sel_types
        element is the type encoding of the method arguments.

From-SVN: r7622
This commit is contained in:
Kresten Krab Thorup 1994-06-30 16:18:55 +00:00
parent 7a1dd32325
commit a39d31bc0c
15 changed files with 731 additions and 422 deletions

View File

@ -1,5 +1,5 @@
/* 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.
@ -93,8 +93,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
- 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;
@ -112,14 +112,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* 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

View File

@ -24,14 +24,18 @@ You should have received a copy of the GNU General Public License along with
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: "); \
@ -43,22 +47,20 @@ You should have received a copy of the GNU General Public License along with
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*);
@ -112,15 +114,29 @@ objc_write_char (struct objc_typed_stream* stream, char value)
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;
}
}
@ -135,18 +151,11 @@ objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short valu
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
@ -161,26 +170,29 @@ objc_write_short (struct objc_typed_stream* stream, short value)
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;
}
}
@ -195,18 +207,11 @@ objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value)
static __inline__ int
__objc_code_int (unsigned char* buf, int val)
{
if (val >= 0)
return __objc_code_unsigned_int (buf, val);
if (val > -0x7f)
return __objc_code_char (buf, val);
else
{
int len = __objc_code_unsigned_int (buf, -val);
buf[0] |= _B_SIGN;
return len;
}
int sign = (val < 0);
int size = __objc_code_unsigned_int (buf, sign ? -val : val);
if (sign)
buf[0] |= _B_SIGN;
return size;
}
int
@ -217,6 +222,62 @@ objc_write_int (struct objc_typed_stream* stream, int 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;
}
}
int
objc_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;
}
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)
@ -240,13 +301,13 @@ int
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;
@ -254,10 +315,10 @@ objc_write_string_atomic (struct objc_typed_stream* stream,
}
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;
@ -272,10 +333,10 @@ objc_write_register_common (struct objc_typed_stream* stream, unsigned int key)
}
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;
@ -305,7 +366,7 @@ __inline__ int
__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);
@ -320,12 +381,12 @@ __objc_write_object (struct objc_typed_stream* stream, id 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
@ -348,8 +409,8 @@ objc_write_root_object (struct objc_typed_stream* stream, id object)
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)
@ -358,20 +419,26 @@ objc_write_object (struct objc_typed_stream* stream, id object)
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));
}
@ -379,13 +446,13 @@ static int
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;
@ -405,13 +472,13 @@ int
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;
@ -551,6 +618,33 @@ objc_read_int (struct objc_typed_stream* stream, int* value)
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)
@ -587,6 +681,42 @@ objc_read_unsigned_int (struct objc_typed_stream* stream,
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)
@ -595,11 +725,11 @@ objc_read_string (struct objc_typed_stream* stream,
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);
}
@ -609,7 +739,7 @@ objc_read_string (struct objc_typed_stream* stream,
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';
}
@ -618,9 +748,9 @@ objc_read_string (struct objc_typed_stream* stream,
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;
@ -632,7 +762,7 @@ objc_read_string (struct objc_typed_stream* stream,
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';
}
@ -655,12 +785,12 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
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);
}
@ -676,7 +806,7 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
/* 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))
@ -692,16 +822,16 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
{
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 */
@ -725,18 +855,18 @@ objc_read_class (struct objc_typed_stream* stream, Class** class)
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);
@ -745,9 +875,9 @@ objc_read_class (struct objc_typed_stream* stream, Class** class)
/* 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);
}
@ -755,10 +885,10 @@ objc_read_class (struct objc_typed_stream* stream, Class** class)
{
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
@ -774,11 +904,11 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
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);
}
@ -788,20 +918,20 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
/* 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
@ -810,96 +940,6 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
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
*/
@ -942,15 +982,21 @@ objc_write_type(TypedStream* stream, const char* type, const void* data)
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;
@ -967,6 +1013,22 @@ objc_write_type(TypedStream* stream, const char* type, const void* 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_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();
@ -1014,15 +1076,21 @@ objc_read_type(TypedStream* stream, const char* type, void* data)
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);
@ -1036,6 +1104,22 @@ objc_read_type(TypedStream* stream, const char* type, void* 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();
@ -1061,7 +1145,7 @@ objc_write_types (TypedStream* stream, const char* type, ...)
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:
@ -1095,15 +1179,21 @@ objc_write_types (TypedStream* stream, const char* type, ...)
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**);
@ -1124,7 +1214,7 @@ objc_write_types (TypedStream* stream, const char* type, ...)
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);
}
@ -1154,7 +1244,7 @@ objc_read_types(TypedStream* stream, const char* type, ...)
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:
@ -1186,15 +1276,21 @@ objc_read_types(TypedStream* stream, const char* type, ...)
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:
{
@ -1209,7 +1305,7 @@ objc_read_types(TypedStream* stream, const char* type, ...)
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);
}
@ -1331,7 +1427,7 @@ static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
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;
@ -1379,8 +1475,6 @@ static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
TypedStream*
objc_open_typed_stream (FILE* physical, int mode)
{
int fflush(FILE*);
TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
s->mode = mode;
@ -1483,13 +1577,12 @@ objc_flush_typed_stream (TypedStream* stream)
(*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__ */

View File

@ -132,6 +132,27 @@ objc_get_class (const char *name)
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
@ -217,6 +238,9 @@ void __objc_resolve_class_links()
Class*
class_pose_as (Class* impostor, Class* super_class)
{
node_ptr node;
Class* class1;
if (!CLS_ISRESOLV (impostor))
__objc_resolve_class_links ();
@ -230,19 +254,13 @@ class_pose_as (Class* impostor, Class* super_class)
{
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;
@ -250,11 +268,18 @@ class_pose_as (Class* impostor, Class* super_class)
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;
@ -267,66 +292,31 @@ class_pose_as (Class* impostor, Class* super_class)
/* 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. */
/* 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. */
/* 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] = '*';
/* 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;
}

View File

@ -35,6 +35,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
({ 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)
@ -121,8 +125,7 @@ objc_sizeof_type(const char* type)
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 */
}
@ -244,11 +247,7 @@ objc_aligned_size (const char* type)
{
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);
}
/*
@ -262,10 +261,7 @@ objc_promoted_size (const char* type)
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);
}
/*

View File

@ -39,6 +39,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#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)

View File

@ -28,7 +28,7 @@ You should have received a copy of the GNU General Public License along with
/* 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 */
@ -49,6 +49,11 @@ static void __objc_class_add_protocols (Class*, struct objc_protocol_list*);
/* 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
@ -70,7 +75,7 @@ __objc_exec_class (Module_t module)
struct objc_list** cell;
/* The table of selector references for this module */
SEL *selectors = symtab->refs;
SEL selectors = symtab->refs;
/* dummy counter */
int i;
@ -91,6 +96,19 @@ __objc_exec_class (Module_t module)
/* 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)
@ -117,13 +135,6 @@ __objc_exec_class (Module_t module)
__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)
{
@ -166,7 +177,7 @@ __objc_exec_class (Module_t module)
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);
@ -209,7 +220,7 @@ static void init_check_module_version(Module_t module)
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)
@ -255,7 +266,7 @@ __objc_init_protocols (struct objc_protocol_list* protos)
{
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 ();
}

View File

@ -30,6 +30,12 @@ void objc_error(id object, const char* fmt, va_list);
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)
{
@ -40,7 +46,7 @@ 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();
}
@ -65,8 +71,12 @@ __objc_xrealloc(void* mem, size_t size)
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;
}

View File

@ -44,8 +44,6 @@ struct objc_method_description
char *types; /* type encoding */
};
/* Filer types used to describe Ivars and Methods. */
#define _C_ID '@'
#define _C_CLASS '#'
@ -92,7 +90,7 @@ extern BOOL objc_trace;
*/
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
@ -146,7 +144,7 @@ typedef struct objc_ivar_list {
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. */
@ -169,7 +167,7 @@ typedef struct objc_method_list {
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
@ -303,12 +301,23 @@ Class* objc_get_class(const char *name);
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);

View File

@ -40,12 +40,24 @@ typedef char BOOL;
#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.
@ -131,36 +143,8 @@ typedef union {
} *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

View File

@ -43,7 +43,7 @@ class_create_instance(Class* class)
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;

View File

@ -61,12 +61,14 @@ extern BOOL __objc_class_links_resolved;
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 */

View File

@ -40,6 +40,11 @@ const char* __objc_sparse2_id = "2 level sparse indices";
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)
{
@ -117,7 +122,7 @@ 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;

View File

@ -31,7 +31,8 @@ You should have received a copy of the GNU General Public License along with
#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);
@ -42,6 +43,7 @@ int __objc_selector_max_index = 0;
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,
@ -78,16 +80,67 @@ register_selectors_from_list (MethodList_t method_list)
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 ""
@ -95,45 +148,123 @@ sel_get_uid (const char *name)
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;
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));
/* Save the selector name. */
__objc_selector_max_index += 1;
i = soffset_encode(__objc_selector_max_index);
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;
}
DEBUG_PRINTF ("Record selector %s as: %#x\n", sel, i);
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);
}

View File

@ -24,10 +24,21 @@ You should have received a copy of the GNU General Public License along with
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;
@ -38,7 +49,14 @@ static void __objc_install_dispatch_table_for_class (Class*);
/* 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, ...);
@ -53,16 +71,34 @@ nil_method(id receiver, SEL op, ...)
__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
@ -72,8 +108,20 @@ __objc_responds_to (id object, SEL sel)
__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;
}
@ -87,6 +135,8 @@ objc_msg_lookup_super (Super_t super, SEL sel)
return nil_method;
}
int method_get_sizeof_arguments (Method*);
retval_t
objc_msg_sendv(id object, SEL op, arglist_t arg_frame)
{
@ -141,8 +191,8 @@ static void __objc_init_install_dtable(id receiver, SEL op)
/* 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);
@ -155,7 +205,10 @@ allready_initialized:
args = __builtin_apply_args();
result = __builtin_apply((apply_t)imp, args, 96);
__builtin_return (result);
if (result)
__builtin_return (result);
else
return;
}
@ -170,8 +223,6 @@ void __objc_install_premature_dtable(Class* class)
/* 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));
@ -199,7 +250,7 @@ static void __objc_send_initialize(Class* 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);
}
@ -231,8 +282,7 @@ __objc_install_dispatch_table_for_class (Class* class)
/* 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);
@ -244,7 +294,7 @@ __objc_install_dispatch_table_for_class (Class* class)
{
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;
}
@ -254,7 +304,6 @@ __objc_install_dispatch_table_for_class (Class* class)
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)
@ -297,10 +346,12 @@ class_add_method_list (Class* class, MethodList_t list)
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. */
@ -375,7 +426,7 @@ search_for_method_in_list (MethodList_t list, SEL op)
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;
}
@ -387,40 +438,71 @@ search_for_method_in_list (MethodList_t list, SEL op)
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)
@ -428,10 +510,12 @@ __objc_missing_method (id object, SEL sel, ...)
: "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. */
@ -451,12 +535,12 @@ void __objc_print_dtable_stats()
#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);

View File

@ -30,8 +30,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#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*);
@ -100,7 +98,7 @@ int objc_read_types (TypedStream* stream, const char* type, ...);
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);
/*
@ -130,6 +128,4 @@ void objc_close_typed_stream (TypedStream* stream);
BOOL objc_end_of_typed_stream (TypedStream* stream);
void objc_flush_typed_stream (TypedStream* stream);
#endif /* __alpha__ */
#endif /* not __typedstream_INCLUDE_GNU */