summaryrefslogtreecommitdiff
path: root/libobjc
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-12 19:25:01 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-12 19:25:01 +0000
commitb4cab6749ba18cf0b3a3c1bd01085cfe94616c3b (patch)
tree2b77880a4930b3a58042e9b269e3e3e5e97d7b8f /libobjc
parent77d3568815aaad6487a295a42e0fce17c1c71b19 (diff)
downloadgcc-b4cab6749ba18cf0b3a3c1bd01085cfe94616c3b.tar.gz
2010-10-12 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 165392 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@165394 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libobjc')
-rw-r--r--libobjc/ChangeLog120
-rw-r--r--libobjc/Makefile.in1
-rw-r--r--libobjc/archive.c1
-rw-r--r--libobjc/class.c67
-rw-r--r--libobjc/encoding.c5
-rw-r--r--libobjc/error.c3
-rw-r--r--libobjc/exception.c15
-rw-r--r--libobjc/gc.c8
-rw-r--r--libobjc/hash.c4
-rw-r--r--libobjc/init.c23
-rw-r--r--libobjc/ivars.c24
-rw-r--r--libobjc/linking.m3
-rw-r--r--libobjc/memory.c3
-rw-r--r--libobjc/objc-private/hash.h3
-rw-r--r--libobjc/objc-private/module-abi-8.h61
-rw-r--r--libobjc/objc-private/protocols.h46
-rw-r--r--libobjc/objc-private/runtime.h9
-rw-r--r--libobjc/objc-sync.c2
-rw-r--r--libobjc/objc/deprecated/hash.h3
-rw-r--r--libobjc/objc/deprecated/struct_objc_class.h1
-rw-r--r--libobjc/objc/objc-decls.h14
-rw-r--r--libobjc/objc/runtime.h215
-rw-r--r--libobjc/objects.c9
-rw-r--r--libobjc/protocols.c549
-rw-r--r--libobjc/sarray.c5
-rw-r--r--libobjc/selector.c15
-rw-r--r--libobjc/sendmsg.c1
-rw-r--r--libobjc/thr.c3
28 files changed, 1144 insertions, 69 deletions
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index e2d93108abf..ec0a98f3790 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,123 @@
+2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * class.c: Include objc/runtime.h and objc-private/module-abi-8.h
+ instead of objc/objc-api.h.
+ (objc_get_unknown_class_handler): Do not define.
+ (class_isMetaClass): New.
+ (class_getSuperclass): New.
+ (class_getVersion): New.
+ (class_setVersion): New.
+ (class_getInstanceSize): New.
+ * exceptions.c: Include objc/runtime.h instead of objc/objc-api.h.
+ (is_kind_of_exception_matcher): Use objc_getSuperclass instead of
+ objc_get_super_class.
+ (get_ttype_entry): Use objc_getRequiredClass instead of
+ objc_get_class.
+ * ivars.c (class_getClassVariable): New.
+ * objects.c: Include objc/runtime.h, objc/thr.h and
+ objc-private/module-abi-8.h instead of objc/objc-api.h
+ * objc/runtime.h (class_getClassVariable): New.
+ (class_isMetaClass): New.
+ (class_getSuperclass): New.
+ (class_getVersion): New.
+ (class_setVersion): New.
+ (class_getInstanceSize): New.
+ * objc-private/module-abi-8.h (HOST_BITS_PER_LONG): New (from
+ objc/objc-api.h)
+ (__CLS_INFO): Same.
+ (__CLS_ISINFO): Same.
+ (__CLS_SETINFO): Same.
+ (CLS_ISMETA): Same.
+ (CLS_ISCLASS): Same.
+ (CLS_ISRESOLV): Same.
+ (CLS_SETRESOLV): Same.
+ (CLS_ISINITIALIZED): Same.
+ (CLS_SETINITIALIZED): Same.
+ (CLS_GETNUMBER): Same.
+ (CLS_SETNUMBER): Same.
+
+2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * archive.c: Do not include objc/objc.h.
+ * class.c: Do not include objc/objc.h.
+ * encoding.c: Include objc/runtime.h, ctype.h and
+ objc-private/module-abi-8.h instead of objc/objc-api.h and
+ objc/encoding.h.
+ * error.c: Do not include objc/objc.h.
+ * gc.c: Include tconfig.h and objc/encoding.h only if
+ OBJC_WITH_GC.
+ * hash.c: Include objc/runtime.h and objc/thr.h instead of
+ objc/objc-api.h. Do not include objc/objc.h.
+ * init.c: Do not include objc/objc.h.
+ * ivars.c: Include objc/runtime.h, objc-private/module-abi-8.h and
+ objc/thr.h instead of objc/objc-api.h. Do not include
+ objc/objc.h.
+ * linking.m: Tidied comment.
+ * memory.c: Include objc/runtime.h instead of objc/objc-api.h.
+ Do not include objc/objc.h.
+ * objects.c: Do not include objc/objc.h.
+ * objc-sync.c: Include objc/runtime.h instead of objc/objc-api.h.
+ * protocols.c: Do not include objc/objc.h.
+ * sarray.c: Include objc/runtime.h instead of objc/objc-api.h. Do
+ not include objc/objc.h.
+ * selector.c: Do not include objc/objc.h.
+ * sendmsg.c: Do not include objc/objc.h.
+ * thr.c: Include objc/runtime.h instead of objc/objc-api.h.
+ Do not include objc/objc.h.
+ * objc/objc-decls.h: Reindented code.
+ * objc/runtime.h Include objc-decls.h. Updated comments.
+ (objc_malloc): New.
+ (objc_atomic_malloc): New.
+ (objc_calloc): New.
+ (objc_realloc): New.
+ (objc_free): New.
+ * objc-private/runtime.h: Updated comments.
+
+2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * Makefile.in (C_SOURCE_FILES): Added protocols.c.
+ * objc-private/protocols.h: New.
+ * protocols.c: New.
+ * init.c: Include objc-private/protocols.h.
+ (__objc_exec_class): Call __objc_protocols_init on startup.
+ (__objc_init_protocols): Call __objc_protocols_add_protocol.
+ * objc-private/runtime.h: Use (struct objc_method_list *) instead
+ of MethodList_t, and (struct objc_method *) instead of Method_t.
+ * objc/deprecated/struct_objc_class.h: Define
+ __objc_STRUCT_OBJC_CLASS_defined.
+ * objc-private/module-abi-8.h (struct
+ objc_method_description_list): New.
+ (struct objc_class): Only define if
+ __objc_STRUCT_OBJC_CLASS_defined is undefined.
+ * objc/runtime.h (class_getName): New.
+ (objc_getProtocol): New.
+ (objc_copyProtocolList): New.
+ (class_addProtocol): New.
+ (class_conformsToProtocol): New.
+ (class_copyProtocolList): New.
+ (protocol_conformsToProtocol): New.
+ (protocol_isEqual): New.
+ (protocol_getName): New.
+ (protocol_getMethodDescription): New.
+ (protocol_copyMethodDescriptionList): New.
+ (protocol_getProperty): New.
+ (protocol_copyPropertyList): New.
+ (protocol_copyProtocolList): New.
+ * class.c (class_getName): New.
+ * selector.c (sel_isEqual): New.
+
+2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * selector.c (sel_getName): Return "<null selector>" for a NULL
+ argument.
+ (sel_get_name): Return 0 for a NULL argument.
+ * objc/runtime.h (sel_getName): Updated documentation.
+
+ * objc-private/hash.h (class_hash_table): Unused declaration
+ removed.
+ (module_hash_table): Same.
+ * objc/deprecated/hash.h: Same changes.
+
2010-10-11 Nicola Pero <nicola.pero@meta-innovation.com>
* class.c (objc_getClassList): New.
diff --git a/libobjc/Makefile.in b/libobjc/Makefile.in
index 86f65bad844..4790f952b9d 100644
--- a/libobjc/Makefile.in
+++ b/libobjc/Makefile.in
@@ -177,6 +177,7 @@ C_SOURCE_FILES = \
objc-foreach.c \
objc-sync.c \
objects.c \
+ protocols.c \
sarray.c \
selector.c \
sendmsg.c \
diff --git a/libobjc/archive.c b/libobjc/archive.c
index f36f1b748fb..b539ca1163e 100644
--- a/libobjc/archive.c
+++ b/libobjc/archive.c
@@ -27,7 +27,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "objc-private/common.h"
#include "objc-private/error.h"
#include "tconfig.h"
-#include "objc/objc.h"
#include "objc/objc-api.h"
#include "objc/hash.h"
#include "objc/objc-list.h"
diff --git a/libobjc/class.c b/libobjc/class.c
index 216d6ace0dc..4eb86761ee8 100644
--- a/libobjc/class.c
+++ b/libobjc/class.c
@@ -89,11 +89,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "objc-private/common.h"
#include "objc-private/error.h"
-#include "objc/objc.h"
-#include "objc/objc-api.h"
+#include "objc/runtime.h"
#include "objc/thr.h"
-#include "objc-private/runtime.h" /* the kitchen sink */
-#include <string.h> /* For memset */
+#include "objc-private/module-abi-8.h" /* For CLS_ISCLASS and similar. */
+#include "objc-private/runtime.h" /* the kitchen sink */
+#include <string.h> /* For memset */
/* We use a table which maps a class name to the corresponding class
* pointer. The first part of this file defines this table, and
@@ -139,7 +139,8 @@ static class_node_ptr class_table_array[CLASS_TABLE_SIZE];
/* The table writing mutex - we lock on writing to avoid conflicts
between different writers, but we read without locks. That is
possible because we assume pointer assignment to be an atomic
- operation. */
+ operation. TODO: This is only true under certain circumstances,
+ which should be clarified. */
static objc_mutex_t __class_table_lock = NULL;
/* CLASS_TABLE_HASH is how we compute the hash of a class name. It is
@@ -417,11 +418,6 @@ class_table_print_histogram (void)
*/
Class (*_objc_lookup_class) (const char *name) = 0; /* !T:SAFE */
-/* Temporarily while we still include objc/objc-api.h instead of objc/runtime.h. */
-#ifndef __objc_runtime_INCLUDE_GNU
-typedef Class (*objc_get_unknown_class_handler)(const char *class_name);
-#endif
-
/* The handler currently in use. PS: if both
__obj_get_unknown_class_handler and _objc_lookup_class are defined,
__objc_get_unknown_class_handler is called first. */
@@ -591,6 +587,7 @@ objc_lookup_class (const char *name)
called automatically by the compiler while messaging (if using the
traditional ABI), so it is worth keeping it fast; don't make it
just a wrapper around objc_getClass(). */
+/* Note that this is roughly equivalent to objc_getRequiredClass(). */
/* Get the class object for the class named NAME. If NAME does not
identify a known class, the hook _objc_lookup_class is called. If
this fails, an error message is issued and the system aborts. */
@@ -730,7 +727,57 @@ __objc_resolve_class_links (void)
objc_mutex_unlock (__objc_runtime_mutex);
}
+const char *
+class_getName (Class class_)
+{
+ if (class_ == Nil)
+ return "nil";
+
+ return class_->name;
+}
+
+BOOL
+class_isMetaClass (Class class_)
+{
+ /* CLS_ISMETA includes the check for Nil class_. */
+ return CLS_ISMETA (class_);
+}
+
+Class
+class_getSuperclass (Class class_)
+{
+ if (class_ == Nil)
+ return Nil;
+ return class_->super_class;
+}
+
+int
+class_getVersion (Class class_)
+{
+ if (class_ == Nil)
+ return 0;
+
+ return (int)(class_->version);
+}
+
+void
+class_setVersion (Class class_, int version)
+{
+ if (class_ == Nil)
+ return;
+
+ class_->version = version;
+}
+
+size_t
+class_getInstanceSize (Class class_)
+{
+ if (class_ == Nil)
+ return 0;
+
+ return class_->instance_size;
+}
#define CLASSOF(c) ((c)->class_pointer)
diff --git a/libobjc/encoding.c b/libobjc/encoding.c
index d417b87396e..87517f4eaf8 100644
--- a/libobjc/encoding.c
+++ b/libobjc/encoding.c
@@ -36,9 +36,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tconfig.h"
#include "coretypes.h"
#include "tm.h"
-#include "objc/objc-api.h"
-#include "objc/encoding.h"
+#include "objc/runtime.h"
+#include "objc-private/module-abi-8.h" /* For struct objc_method */
#include <stdlib.h>
+#include <ctype.h>
#undef MAX
#define MAX(X, Y) \
diff --git a/libobjc/error.c b/libobjc/error.c
index 0dc8fd8dae0..7c6ba44b76f 100644
--- a/libobjc/error.c
+++ b/libobjc/error.c
@@ -48,8 +48,7 @@ _objc_abort (const char *fmt, ...)
}
/* The rest of the file is deprecated. */
-#include "objc/objc.h"
-#include "objc/objc-api.h"
+#include "objc/objc-api.h" /* For objc_error_handler. */
/*
** Error handler function
diff --git a/libobjc/exception.c b/libobjc/exception.c
index a221a3e77e3..4883448afad 100644
--- a/libobjc/exception.c
+++ b/libobjc/exception.c
@@ -25,7 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "objc-private/common.h"
#include <stdlib.h>
#include "config.h"
-#include "objc/objc-api.h"
+#include "objc/runtime.h"
#include "objc/objc-exception.h"
#include "unwind.h"
#include "unwind-pe.h"
@@ -57,7 +57,7 @@ is_kind_of_exception_matcher (Class catch_class, id exception)
Class c;
for (c = exception->class_pointer; c != Nil;
- c = class_get_super_class (c))
+ c = class_getSuperclass (c))
if (c == catch_class)
return 1;
}
@@ -191,9 +191,11 @@ get_ttype_entry (struct lsda_header_info *info, _uleb128_t i)
ptr = (_Unwind_Ptr) (info->TType - (i * 4));
ptr = _Unwind_decode_target2 (ptr);
-
+
+ /* NULL ptr means catch-all. Note that if the class is not found,
+ this will abort the program. */
if (ptr)
- return objc_get_class ((const char *) ptr);
+ return objc_getRequiredClass ((const char *) ptr);
else
return 0;
}
@@ -209,9 +211,10 @@ get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
info->TType - i, &ptr);
- /* NULL ptr means catch-all. */
+ /* NULL ptr means catch-all. Note that if the class is not found,
+ this will abort the program. */
if (ptr)
- return objc_get_class ((const char *) ptr);
+ return objc_getRequiredClass ((const char *) ptr);
else
return 0;
}
diff --git a/libobjc/gc.c b/libobjc/gc.c
index a67ba1c9855..ed5effbb437 100644
--- a/libobjc/gc.c
+++ b/libobjc/gc.c
@@ -24,15 +24,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "objc-private/common.h"
-#include "tconfig.h"
#include "objc/objc.h"
-#include "objc/encoding.h"
+#if OBJC_WITH_GC
+
+#include "tconfig.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
-
-#if OBJC_WITH_GC
+#include "objc/encoding.h"
#include <gc.h>
#include <limits.h>
diff --git a/libobjc/hash.c b/libobjc/hash.c
index 602fc84a874..3ecc54a170a 100644
--- a/libobjc/hash.c
+++ b/libobjc/hash.c
@@ -25,8 +25,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "objc-private/common.h"
#include <assert.h> /* For assert */
-#include "objc/objc.h"
-#include "objc/objc-api.h"
+#include "objc/runtime.h" /* For objc_calloc */
+#include "objc/thr.h" /* Required by objc-private/runtime.h. */
#include "objc-private/hash.h"
#include "objc-private/runtime.h" /* for DEBUG_PRINTF */
diff --git a/libobjc/init.c b/libobjc/init.c
index deb089d7e16..0f714c40596 100644
--- a/libobjc/init.c
+++ b/libobjc/init.c
@@ -26,13 +26,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "objc-private/common.h"
#include "objc-private/error.h"
-#include "objc/objc.h"
#include "objc/objc-api.h"
#include "objc/thr.h"
#include "objc-private/hash.h"
#include "objc-private/objc-list.h"
#include "objc-private/runtime.h"
#include "objc-private/objc-sync.h" /* For __objc_sync_init() */
+#include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */
/* The version number of this runtime. This must match the number
defined in gcc (objc-act.c). */
@@ -48,7 +48,17 @@ static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */
/* List of unresolved static instances. */
static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
-/* Global runtime "write" mutex. */
+/* Global runtime "write" mutex. Having a single mutex prevents
+ deadlocks, but reduces concurrency. To improve concurrency, some
+ groups of functions in the runtime have their own separate mutex
+ (eg, __class_table_lock in class.c); to avoid deadlocks, these
+ routines must make sure that they never acquire any other lock
+ while holding their own local lock. Ie, they should lock, execute
+ some C code that does not perform any calls to other runtime
+ functions which may potentially lock different locks, then unlock.
+ If they need to perform any calls to other runtime functions that
+ may potentially lock other locks, then they should use the global
+ __objc_runtime_mutex. */
objc_mutex_t __objc_runtime_mutex = 0;
/* Number of threads that are alive. */
@@ -551,6 +561,7 @@ __objc_exec_class (Module_t module)
__objc_load_methods = objc_hash_new (128,
(hash_func_type)objc_hash_ptr,
objc_compare_ptrs);
+ __objc_protocols_init ();
__objc_sync_init ();
previous_constructors = 1;
}
@@ -862,10 +873,14 @@ __objc_init_protocols (struct objc_protocol_list *protos)
struct objc_protocol *aProto = protos->list[i];
if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
{
- /* assign class pointer */
+ /* Assign class pointer */
aProto->class_pointer = proto_class;
- /* init super protocols */
+ /* Register the protocol in the hashtable or protocols by
+ name. */
+ __objc_protocols_add_protocol (aProto->protocol_name, aProto);
+
+ /* Init super protocols */
__objc_init_protocols (aProto->protocol_list);
}
else if (protos->list[i]->class_pointer != proto_class)
diff --git a/libobjc/ivars.c b/libobjc/ivars.c
index 18c6e8af29d..52b71af1124 100644
--- a/libobjc/ivars.c
+++ b/libobjc/ivars.c
@@ -23,8 +23,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "objc-private/common.h"
-#include "objc/objc.h"
-#include "objc/objc-api.h"
+#include "objc/runtime.h"
+#include "objc-private/module-abi-8.h" /* For runtime structures */
+#include "objc/thr.h"
#include "objc-private/runtime.h" /* the kitchen sink */
#include <string.h> /* For strcmp */
@@ -59,6 +60,25 @@ class_getInstanceVariable (Class class_, const char *name)
return NULL;
}
+struct objc_ivar *
+class_getClassVariable (Class class_, const char *name)
+{
+ if (class_ == Nil)
+ return NULL;
+
+ /* Logically, since a class is an instance of its meta-class, and
+ since its class methods are the instance methods of the
+ meta-class, class variables should be instance variables of the
+ meta-class. That is different from the normal use of having
+ 'static' variables in the class implementation file, because
+ every class would have its own variables.
+
+ Anyway, it is all speculative at this stage, but if we get class
+ variables in Objective-C, it is conceivable that this
+ implementation should work. */
+ return class_getInstanceVariable (class_->class_pointer, name);
+}
+
void *
object_getIndexedIvars (id object)
{
diff --git a/libobjc/linking.m b/libobjc/linking.m
index 6372e91df45..e94c8ea8c4b 100644
--- a/libobjc/linking.m
+++ b/libobjc/linking.m
@@ -28,8 +28,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <objc/NXConstStr.h>
/* Generate references to Object and NXConstanstString classes since they are
- needed by the runtime system to run correctly. */
-
+ needed by the runtime system to run correctly. */
void __objc_linking (void)
{
diff --git a/libobjc/memory.c b/libobjc/memory.c
index a0d6e130ad9..458d2566fcb 100644
--- a/libobjc/memory.c
+++ b/libobjc/memory.c
@@ -42,8 +42,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define __USE_FIXED_PROTOTYPES__
#include <stdlib.h>
-#include "objc/objc.h"
-#include "objc/objc-api.h"
+#include "objc/runtime.h"
#if OBJC_WITH_GC
#include <gc.h>
diff --git a/libobjc/objc-private/hash.h b/libobjc/objc-private/hash.h
index 7c57a4d2589..ba4c4943438 100644
--- a/libobjc/objc-private/hash.h
+++ b/libobjc/objc-private/hash.h
@@ -104,9 +104,6 @@ typedef struct cache
} *cache_ptr;
-/* Two important hash tables. */
-extern cache_ptr module_hash_table, class_hash_table;
-
/* Allocate and initialize a hash table. */
cache_ptr objc_hash_new (unsigned int size,
diff --git a/libobjc/objc-private/module-abi-8.h b/libobjc/objc-private/module-abi-8.h
index a20e3a3ae6e..414e5e354ec 100644
--- a/libobjc/objc-private/module-abi-8.h
+++ b/libobjc/objc-private/module-abi-8.h
@@ -138,6 +138,24 @@ struct objc_method_list
structure. */
};
+/* Currently defined in Protocol.m (that definition should go away
+ once we include this file). */
+struct objc_method_description_list
+{
+ int count;
+ struct objc_method_description list[1];
+};
+
+/* Currently defined by objc/objc.h. */
+/*
+struct objc_protocol {
+ struct objc_class* class_pointer;
+ char *protocol_name;
+ struct objc_protocol_list *protocol_list;
+ struct objc_method_description_list *instance_methods, *class_methods;
+};
+*/
+
struct objc_protocol_list
{
struct objc_protocol_list *next;
@@ -155,6 +173,7 @@ struct objc_protocol_list
some members change type. The compiler generates "char* const" and
places a string in the following member variables: super_class.
*/
+#ifndef __objc_STRUCT_OBJC_CLASS_defined
struct objc_class {
struct objc_class* class_pointer; /* Pointer to the class's meta
class. */
@@ -164,7 +183,7 @@ struct objc_class {
const char* name; /* Name of the class. */
long version; /* Unknown. */
unsigned long info; /* Bit mask. See class masks
- defined above. */
+ defined below. */
long instance_size; /* Size in bytes of the class.
The sum of the class
definition and all super
@@ -197,6 +216,46 @@ struct objc_class {
struct objc_protocol_list *protocols; /* Protocols conformed to */
void* gc_object_type;
};
+#endif /* __objc_STRUCT_OBJC_CLASS_defined */
+
+/* This is used to assure consistent access to the info field of
+ classes. */
+#ifndef HOST_BITS_PER_LONG
+# define HOST_BITS_PER_LONG (sizeof(long)*8)
+#endif
+
+#define __CLS_INFO(cls) ((cls)->info)
+#define __CLS_ISINFO(cls, mask) ((__CLS_INFO(cls)&mask)==mask)
+#define __CLS_SETINFO(cls, mask) (__CLS_INFO(cls) |= mask)
+
+/* The structure is of type MetaClass */
+#define _CLS_META 0x2L
+#define CLS_ISMETA(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_META))
+
+/* The structure is of type Class */
+#define _CLS_CLASS 0x1L
+#define CLS_ISCLASS(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_CLASS))
+
+/* The class is initialized within the runtime. This means that it
+ has had correct super and sublinks assigned. */
+#define _CLS_RESOLV 0x8L
+#define CLS_ISRESOLV(cls) __CLS_ISINFO(cls, _CLS_RESOLV)
+#define CLS_SETRESOLV(cls) __CLS_SETINFO(cls, _CLS_RESOLV)
+
+/* The class has been send a +initialize message or a such is not
+ defined for this class. */
+#define _CLS_INITIALIZED 0x04L
+#define CLS_ISINITIALIZED(cls) __CLS_ISINFO(cls, _CLS_INITIALIZED)
+#define CLS_SETINITIALIZED(cls) __CLS_SETINFO(cls, _CLS_INITIALIZED)
+
+/* The class number of this class. This must be the same for both the
+ class and its meta class object. */
+#define CLS_GETNUMBER(cls) (__CLS_INFO(cls) >> (HOST_BITS_PER_LONG/2))
+#define CLS_SETNUMBER(cls, num) \
+ ({ (cls)->info <<= (HOST_BITS_PER_LONG/2); \
+ (cls)->info >>= (HOST_BITS_PER_LONG/2); \
+ __CLS_SETINFO(cls, (((unsigned long)num) << (HOST_BITS_PER_LONG/2))); })
+
/* The compiler generates one of these structures for each category.
A class may have many categories and contain both instance and
diff --git a/libobjc/objc-private/protocols.h b/libobjc/objc-private/protocols.h
new file mode 100644
index 00000000000..49a2d92648f
--- /dev/null
+++ b/libobjc/objc-private/protocols.h
@@ -0,0 +1,46 @@
+/* GNU Objective C Runtime protocols - Private functions
+ Copyright (C) 2010 Free Software Foundation, Inc.
+ Contributed by Nicola Pero <nicola.pero@meta-innovation.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 3, or (at your option) any later version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef __objc_private_protocols_INCLUDE_GNU
+#define __objc_private_protocols_INCLUDE_GNU
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* This function needs to be called at startup by init.c. */
+void
+__objc_protocols_init (void);
+
+/* This function adds a protocol to the internal hashtable of
+ protocols by name, which allows objc_getProtocol(name) to be
+ implemented efficiently. */
+void
+__objc_protocols_add_protocol (const char *name, Protocol *object);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* not __objc_private_protocols_INCLUDE_GNU */
diff --git a/libobjc/objc-private/runtime.h b/libobjc/objc-private/runtime.h
index 690427ed5a3..b7e75ae4304 100644
--- a/libobjc/objc-private/runtime.h
+++ b/libobjc/objc-private/runtime.h
@@ -34,7 +34,8 @@ The original list was:
but can almost certainly be shrinked down.
-*/
+Note that you can use this file both with objc/objc-api.h and with
+objc/runtime.h. */
#ifndef __objc_private_runtime_INCLUDE_GNU
#define __objc_private_runtime_INCLUDE_GNU
@@ -58,18 +59,18 @@ extern void __objc_init_dispatch_tables(void); /* (objc-dispatch.c) */
extern void __objc_install_premature_dtable(Class); /* (objc-dispatch.c) */
extern void __objc_resolve_class_links(void); /* (objc-class.c) */
extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */
-extern void __objc_register_selectors_from_list (MethodList_t); /* (selector.c) */
+extern void __objc_register_selectors_from_list (struct objc_method_list *); /* (selector.c) */
extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */
extern int __objc_init_thread_system(void); /* thread.c */
extern int __objc_fini_thread_system(void); /* thread.c */
extern void __objc_print_dtable_stats(void); /* sendmsg.c */
-extern void class_add_method_list(Class, MethodList_t);
+extern void class_add_method_list(Class, struct objc_method_list *);
/* Registering instance methods as class methods for root classes */
extern void __objc_register_instance_methods_to_class(Class);
-extern Method_t search_for_method_in_list(MethodList_t list, SEL op);
+extern struct objc_method * search_for_method_in_list(struct objc_method_list * list, SEL op);
/* True when class links has been resolved */
extern BOOL __objc_class_links_resolved;
diff --git a/libobjc/objc-sync.c b/libobjc/objc-sync.c
index 97349e64029..d01707ca659 100644
--- a/libobjc/objc-sync.c
+++ b/libobjc/objc-sync.c
@@ -79,7 +79,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "objc-private/common.h"
#include "objc/objc-sync.h" /* For objc_sync_enter(), objc_sync_exit() */
-#include "objc/objc-api.h" /* For objc_malloc() */
+#include "objc/runtime.h" /* For objc_malloc() */
#include "objc/thr.h" /* For objc_mutex_loc() and similar */
#include "objc-private/objc-sync.h" /* For __objc_sync_init() */
diff --git a/libobjc/objc/deprecated/hash.h b/libobjc/objc/deprecated/hash.h
index 52ee8c31345..8b718a4417d 100644
--- a/libobjc/objc/deprecated/hash.h
+++ b/libobjc/objc/deprecated/hash.h
@@ -104,9 +104,6 @@ typedef struct cache
} *cache_ptr;
-/* Two important hash tables. */
-extern cache_ptr module_hash_table, class_hash_table;
-
/* Allocate and initialize a hash table. */
cache_ptr objc_hash_new (unsigned int size,
diff --git a/libobjc/objc/deprecated/struct_objc_class.h b/libobjc/objc/deprecated/struct_objc_class.h
index 5a4859cbd65..07927feb69d 100644
--- a/libobjc/objc/deprecated/struct_objc_class.h
+++ b/libobjc/objc/deprecated/struct_objc_class.h
@@ -1,4 +1,5 @@
/* This structure used to be public, but is now private to the runtime. */
+#define __objc_STRUCT_OBJC_CLASS_defined
/*
** The compiler generates one of these structures for each class.
diff --git a/libobjc/objc/objc-decls.h b/libobjc/objc/objc-decls.h
index e5388e33c4c..b3cfb2120f2 100644
--- a/libobjc/objc/objc-decls.h
+++ b/libobjc/objc/objc-decls.h
@@ -28,13 +28,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#if defined (_WIN32) || defined (__WIN32__) || defined (WIN32)
-# ifdef DLL_EXPORT /* defined by libtool (if required) */
-# define objc_EXPORT
-# define objc_DECLARE
-#else
-# define objc_EXPORT extern __declspec(dllimport)
-# define objc_DECLARE extern __declspec(dllimport)
-#endif
+# ifdef DLL_EXPORT /* defined by libtool (if required) */
+# define objc_EXPORT
+# define objc_DECLARE
+# else
+# define objc_EXPORT extern __declspec(dllimport)
+# define objc_DECLARE extern __declspec(dllimport)
+# endif
#else
diff --git a/libobjc/objc/runtime.h b/libobjc/objc/runtime.h
index b15c522235d..a52c7611857 100644
--- a/libobjc/objc/runtime.h
+++ b/libobjc/objc/runtime.h
@@ -48,6 +48,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* TODO: This file is incomplete. */
#include "objc.h"
+#include "objc-decls.h"
/* An 'Ivar' represents an instance variable. It holds information
about the name, type and offset of the instance variable. */
@@ -168,7 +169,8 @@ object_getClass (id object)
/** Implementation: the following functions are in selector.c. */
-/* Return the name of a given selector. */
+/* Return the name of a given selector. If 'selector' is NULL, return
+ "<null selector>". */
objc_EXPORT const char *sel_getName (SEL selector);
/* Return the type of a given selector.
@@ -237,6 +239,14 @@ objc_EXPORT Class object_setClass (id object, Class class_);
reuse the returned Ivar if you can. */
objc_EXPORT Ivar class_getInstanceVariable (Class class_, const char *name);
+/* Return a class variable given the class and the class variable
+ name. This is an expensive function to call, so try to reuse the
+ returned Ivar if you can.
+
+ This function always returns NULL since class variables are
+ currently unavailable in Objective-C. */
+objc_EXPORT Ivar class_getClassVariable (Class class_, const char *name);
+
/* If the object was created in class_createInstance() with some
extraBytes, returns a pointer to them. If it was not, then the
returned pointer may make no sense. */
@@ -355,6 +365,180 @@ objc_EXPORT int objc_getClassList (Class *returnValue, int maxNumberOfClassesToR
the documentation is unclear on what they are supposed to do, and
the GNU Objective-C Runtime currently does not provide them. */
+/* Return the name of the class 'class_', or the string "nil" if the
+ class_ is Nil. */
+objc_EXPORT const char * class_getName (Class class_);
+
+/* Return YES if 'class_' is a meta class, and NO if not. If 'class_'
+ is Nil, return NO. */
+objc_EXPORT BOOL class_isMetaClass (Class class_);
+
+/* Return the superclass of 'class_'. If 'class_' is Nil, or it is a root
+ class, return Nil.
+
+ TODO: It may be worth to define this inline, since it is usually
+ used in loops when traversing the class hierarchy. */
+objc_EXPORT Class class_getSuperclass (Class class_);
+
+/* Return the 'version' number of the class, which is an integer that
+ can be used to track changes in the class API, methods and
+ variables. If class_ is Nil, return 0. If class_ is not Nil, the
+ version is 0 unless class_setVersion() has been called to set a
+ different one.
+
+ Please note that internally the version is a long, but the API only
+ allows you to set and retrieve int values. */
+objc_EXPORT int class_getVersion (Class class_);
+
+/* Set the 'version' number of the class, which is an integer that can
+ be used to track changes in the class API, methods and variables.
+ If 'class_' is Nil, does nothing.
+
+ This is typically used internally by "Foundation" libraries such as
+ GNUstep Base to support serialization / deserialization of objects
+ that work across changes in the classes. If you are using such a
+ library, you probably want to use their versioning API, which may
+ be based on this one, but is integrated with the rest of the
+ library.
+
+ Please note that internally the version is a long, but the API only
+ allows you to set and retrieve int values. */
+objc_EXPORT void class_setVersion (Class class_, int version);
+
+/* Return the size in bytes (a byte is the size of a char) of an
+ instance of the class. If class_ is Nil, return 0; else it return
+ a non-zero number (since the 'isa' instance variable is required
+ for all classes). */
+objc_EXPORT size_t class_getInstanceSize (Class class_);
+
+
+/** Implementation: the following functions are in protocols.c. */
+
+/* Return the protocol with name 'name', or nil if it the protocol is
+ not known to the runtime. */
+objc_EXPORT Protocol *objc_getProtocol (const char *name);
+
+/* Return all the protocols known to the runtime. The return value of
+ the function is a pointer to an area, allocated with malloc(), that
+ contains all the protocols known to the runtime; the list is
+ terminated by NULL. You should free this area using free() once
+ you no longer need it. Optionally, if you pass a non-NULL
+ 'numberOfReturnedProtocols' pointer, the unsigned int that it
+ points to will be filled with the number of protocols returned. If
+ there are no protocols known to the runtime, NULL is returned. */
+objc_EXPORT Protocol **objc_copyProtocolList (unsigned int *numberOfReturnedProtocols);
+
+/* Add a protocol to a class, and return YES if it was done
+ succesfully, and NO if not. At the moment, NO should only happen
+ if class_ or protocol are nil, if the protocol is not a Protocol
+ object or if the class already conforms to the protocol. */
+objc_EXPORT BOOL class_addProtocol (Class class_, Protocol *protocol);
+
+/* Return YES if the class 'class_' conforms to Protocol 'protocol',
+ and NO if not. */
+objc_EXPORT BOOL class_conformsToProtocol (Class class_, Protocol *protocol);
+
+/* Return all the protocols that the class conforms to. The return
+ value of the function is a pointer to an area, allocated with
+ malloc(), that contains all the protocols formally adopted by the
+ class. It does not include protocols adopted by superclasses. The
+ list is terminated by NULL. Optionally, if you pass a non-NULL
+ 'numberOfReturnedProtocols' pointer, the unsigned int that it
+ points to will be filled with the number of protocols returned. */
+objc_EXPORT Protocol **class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols);
+
+/* Return YES if protocol 'protocol' conforms to protocol
+ 'anotherProtocol', and NO if not. Note that if one of the two
+ protocols is nil, it returns NO. */
+objc_EXPORT BOOL protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol);
+
+/* Return YES if protocol 'protocol' is the same as protocol
+ 'anotherProtocol', and 'NO' if not. Note that it returns YES if
+ the two protocols are both nil. */
+objc_EXPORT BOOL protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol);
+
+/* Return the name of protocol 'protocol'. If 'protocol' is nil or is
+ not a Protocol, return NULL. */
+objc_EXPORT const char *protocol_getName (Protocol *protocol);
+
+/* Return the method description for the method with selector
+ 'selector' in protocol 'protocol'; if 'requiredMethod' is YES, the
+ function searches the list of required methods; if NO, the list of
+ optional methods. If 'instanceMethod' is YES, the function search
+ for an instance method; if NO, for a class method. If there is no
+ matching method, an objc_method_description structure with both
+ name and types set to NULL is returned. This function will only
+ find methods that are directly declared in the protocol itself, not
+ in other protocols that this protocol adopts.
+
+ Note that the traditional ABI does not store the list of optional
+ methods of a protocol in a compiled module, so the traditional ABI
+ will always return (NULL, NULL) when requiredMethod == NO. */
+objc_EXPORT struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
+ SEL selector,
+ BOOL requiredMethod,
+ BOOL instanceMethod);
+
+/* Return the method descriptions of all the methods of the protocol.
+ The return value of the function is a pointer to an area, allocated
+ with malloc(), that contains all the method descriptions of the
+ methods of the protocol. It does not recursively include methods
+ of the protocols adopted by this protocol. The list is terminated
+ by a NULL objc_method_description (one with both fields set to
+ NULL). Optionally, if you pass a non-NULL
+ 'numberOfReturnedMethods' pointer, the unsigned int that it points
+ to will be filled with the number of properties returned.
+
+ Note that the traditional ABI does not store the list of optional
+ methods of a protocol in a compiled module, so the traditional ABI
+ will always return an empty list if requiredMethod is set to
+ NO. */
+objc_EXPORT struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
+ BOOL requiredMethod,
+ BOOL instanceMethod,
+ unsigned int *numberOfReturnedMethods);
+
+/* Return the property with name 'propertyName' of the protocol
+ 'protocol'. If 'requiredProperty' is YES, the function searches
+ the list of required properties; if NO, the list of optional
+ properties. If 'instanceProperty' is YES, the function searches
+ the list of instance properties; if NO, the list of class
+ properties. At the moment, optional properties and class
+ properties are not part of the Objective-C language, so both
+ 'requiredProperty' and 'instanceProperty' should be set to YES.
+ This function returns NULL if the required property can not be
+ found.
+
+ Note that the traditional ABI does not store the list of properties
+ of a protocol in a compiled module, so the traditional ABI will
+ always return NULL. */
+objc_EXPORT Property protocol_getProperty (Protocol *protocol, const char *propertyName,
+ BOOL requiredProperty, BOOL instanceProperty);
+
+/* Return all the properties of the protocol. The return value of the
+ function is a pointer to an area, allocated with malloc(), that
+ contains all the properties of the protocol. It does not
+ recursively include properties of the protocols adopted by this
+ protocol. The list is terminated by NULL. Optionally, if you pass
+ a non-NULL 'numberOfReturnedProperties' pointer, the unsigned int
+ that it points to will be filled with the number of properties
+ returned.
+
+ Note that the traditional ABI does not store the list of properties
+ of a protocol in a compiled module, so the traditional ABI will
+ always return NULL and store 0 in numberOfReturnedProperties. */
+objc_EXPORT Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties);
+
+/* Return all the protocols that the protocol conforms to. The return
+ value of the function is a pointer to an area, allocated with
+ malloc(), that contains all the protocols formally adopted by the
+ protocol. It does not recursively include protocols adopted by the
+ protocols adopted by this protocol. The list is terminated by
+ NULL. Optionally, if you pass a non-NULL
+ 'numberOfReturnedProtocols' pointer, the unsigned int that it
+ points to will be filled with the number of protocols returned. */
+objc_EXPORT Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols);
+
/* TODO: Add all the other functions in the API. */
@@ -410,11 +594,38 @@ struct __objcFastEnumerationState
*/
+/** Implementation: the following functions are in memory.c. */
+
+/* Traditional GNU Objective-C Runtime functions that are used for
+ memory allocation and disposal. These functions are used in the
+ same way as you use malloc, realloc, calloc and free and make sure
+ that memory allocation works properly with the garbage
+ collector.
+
+ Compatibility Note: these functions are not available with the
+ Apple/NeXT runtime. */
+
+objc_EXPORT void *objc_malloc(size_t size);
+
+/* FIXME: Shouldn't the following be called objc_malloc_atomic ? The
+ GC function is GC_malloc_atomic() which makes sense.
+ */
+objc_EXPORT void *objc_atomic_malloc(size_t size);
+
+objc_EXPORT void *objc_realloc(void *mem, size_t size);
+
+objc_EXPORT void *objc_calloc(size_t nelem, size_t size);
+
+objc_EXPORT void objc_free(void *mem);
+
+
/** Implementation: the following functions are in encoding.c. */
/* Traditional GNU Objective-C Runtime functions that are currently
used to implement method forwarding.
-*/
+
+ Compatibility Note: these functions are not available with the
+ Apple/NeXT runtime. */
/* Return the size of a variable which has the specified 'type'
encoding. */
diff --git a/libobjc/objects.c b/libobjc/objects.c
index 2562be55f24..71b09afee56 100644
--- a/libobjc/objects.c
+++ b/libobjc/objects.c
@@ -23,11 +23,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "objc-private/common.h"
-#include "objc/objc.h"
-#include "objc/objc-api.h"
-#include "objc-private/runtime.h" /* the kitchen sink */
+#include "objc/runtime.h"
+#include "objc/thr.h" /* Required by objc-private/runtime.h. */
+#include "objc-private/module-abi-8.h" /* For CLS_ISCLASS and similar. */
+#include "objc-private/runtime.h" /* the kitchen sink */
-#include <string.h> /* For memcpy() */
+#include <string.h> /* For memcpy() */
#if OBJC_WITH_GC
# include <gc.h>
diff --git a/libobjc/protocols.c b/libobjc/protocols.c
new file mode 100644
index 00000000000..6d429803c8f
--- /dev/null
+++ b/libobjc/protocols.c
@@ -0,0 +1,549 @@
+/* GNU Objective C Runtime protocol related functions.
+ Copyright (C) 2010 Free Software Foundation, Inc.
+ Contributed by Nicola Pero
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 3, or (at your option) any later version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "objc-private/common.h"
+#include "objc/runtime.h"
+#include "objc-private/module-abi-8.h" /* For runtime structures */
+#include "objc/thr.h"
+#include "objc-private/runtime.h" /* the kitchen sink */
+#include "objc-private/hash.h" /* For the hash table of protocols. */
+#include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */
+
+/* This is a table that maps a name to a Protocol instance with that
+ name. Because there may be multiple Protocol instances with the
+ same name (no harm in that) the table records only one
+ instance. */
+static cache_ptr __protocols_hashtable;
+
+/* A mutex protecting the protocol_hashtable. */
+static objc_mutex_t __protocols_hashtable_lock = NULL;
+
+/* Called at startup by init.c. */
+void
+__objc_protocols_init (void)
+{
+ __protocols_hashtable_lock = objc_mutex_allocate ();
+
+ /* The keys in the table are strings, and the values are Protocol
+ objects. */
+ __protocols_hashtable = objc_hash_new (64, (hash_func_type) objc_hash_string,
+ (compare_func_type) objc_compare_strings);
+}
+
+/* Add a protocol to the hashtable. */
+void
+__objc_protocols_add_protocol (const char *name, Protocol *object)
+{
+ objc_mutex_lock (__protocols_hashtable_lock);
+
+ /* If we find a protocol with the same name already in the
+ hashtable, we do not need to add the new one, because it will be
+ identical to it. This in the reasonable assumption that two
+ protocols with the same name are identical, which is expected in
+ any sane program. If we are really paranoid, we would compare
+ the protocols and abort if they are not identical.
+ Unfortunately, this would slow down the startup of all
+ Objective-C programs while trying to catch a problem that has
+ never been seen in practice, so we don't do it. */
+ if (! objc_hash_is_key_in_hash (__protocols_hashtable, name))
+ {
+ objc_hash_add (&__protocols_hashtable, name, object);
+ }
+
+ objc_mutex_unlock (__protocols_hashtable_lock);
+}
+
+Protocol *
+objc_getProtocol (const char *name)
+{
+ Protocol *protocol;
+
+ if (name == NULL)
+ return NULL;
+
+ objc_mutex_lock (__protocols_hashtable_lock);
+ protocol = (Protocol *)(objc_hash_value_for_key (__protocols_hashtable, name));
+ objc_mutex_unlock (__protocols_hashtable_lock);
+
+ return protocol;
+}
+
+Protocol **
+objc_copyProtocolList (unsigned int *numberOfReturnedProtocols)
+{
+ unsigned int count = 0;
+ Protocol **returnValue = NULL;
+ node_ptr node;
+
+ objc_mutex_lock (__protocols_hashtable_lock);
+
+ /* Count how many protocols we have. */
+ node = objc_hash_next (__protocols_hashtable, NULL);
+ while (node)
+ {
+ count++;
+ node = objc_hash_next (__protocols_hashtable, node);
+ }
+
+ if (count != 0)
+ {
+ unsigned int i = 0;
+
+ /* Allocate enough memory to hold them. */
+ returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
+
+ /* Copy the protocols. */
+ node = objc_hash_next (__protocols_hashtable, NULL);
+ while (node)
+ {
+ returnValue[i] = node->value;
+ i++;
+ node = objc_hash_next (__protocols_hashtable, node);
+ }
+
+ returnValue[i] = NULL;
+ }
+ objc_mutex_unlock (__protocols_hashtable_lock);
+
+ if (numberOfReturnedProtocols)
+ *numberOfReturnedProtocols = count;
+
+ return returnValue;
+}
+
+BOOL
+class_addProtocol (Class class_, Protocol *protocol)
+{
+ struct objc_protocol_list *protocols;
+
+ if (class_ == Nil || protocol == NULL)
+ return NO;
+
+ if (class_conformsToProtocol (class_, protocol))
+ return NO;
+
+ /* Check that it is a Protocol object before casting it to (struct
+ objc_protocol *). */
+ if (protocol->class_pointer != objc_lookupClass ("Protocol"))
+ return NO;
+
+ objc_mutex_lock (__objc_runtime_mutex);
+
+ /* Create the objc_protocol_list. */
+ protocols = malloc (sizeof (struct objc_protocol_list));
+ protocols->count = 1;
+ protocols->list[0] = protocol;
+
+ /* Attach it to the list of class protocols. */
+ protocols->next = class_->protocols;
+ class_->protocols = protocols;
+
+ objc_mutex_unlock (__objc_runtime_mutex);
+
+ return YES;
+}
+
+BOOL
+class_conformsToProtocol (Class class_, Protocol *protocol)
+{
+ struct objc_protocol_list* proto_list;
+
+ if (class_ == Nil || protocol == NULL)
+ return NO;
+
+ /* Check that it is a Protocol object before casting it to (struct
+ objc_protocol *). */
+ if (protocol->class_pointer != objc_lookupClass ("Protocol"))
+ return NO;
+
+ /* Acquire the runtime lock because the list of protocols for a
+ class may be modified concurrently, for example if another thread
+ calls class_addProtocol(), or dynamically loads from a file a
+ category of the class. */
+ objc_mutex_lock (__objc_runtime_mutex);
+ proto_list = class_->protocols;
+
+ while (proto_list)
+ {
+ size_t i;
+ for (i = 0; i < proto_list->count; i++)
+ {
+ if (proto_list->list[i] == protocol
+ || protocol_conformsToProtocol (proto_list->list[i],
+ protocol))
+ {
+ objc_mutex_unlock (__objc_runtime_mutex);
+ return YES;
+ }
+ }
+ proto_list = proto_list->next;
+ }
+
+ objc_mutex_unlock (__objc_runtime_mutex);
+ return NO;
+}
+
+Protocol **
+class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols)
+{
+ unsigned int count = 0;
+ Protocol **returnValue = NULL;
+ struct objc_protocol_list* proto_list;
+
+ /* Lock the runtime mutex because the class protocols may be
+ concurrently modified. */
+ objc_mutex_lock (__objc_runtime_mutex);
+
+ /* Count how many protocols we have. */
+ proto_list = class_->protocols;
+
+ while (proto_list)
+ {
+ count = count + proto_list->count;
+ proto_list = proto_list->next;
+ }
+
+ if (count != 0)
+ {
+ unsigned int i = 0;
+
+ /* Allocate enough memory to hold them. */
+ returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
+
+ /* Copy the protocols. */
+ proto_list = class_->protocols;
+
+ while (proto_list)
+ {
+ size_t j;
+ for (j = 0; j < proto_list->count; j++)
+ {
+ returnValue[i] = proto_list->list[j];
+ i++;
+ }
+ proto_list = proto_list->next;
+ }
+
+ returnValue[i] = NULL;
+ }
+ objc_mutex_unlock (__objc_runtime_mutex);
+
+ if (numberOfReturnedProtocols)
+ *numberOfReturnedProtocols = count;
+
+ return returnValue;
+}
+
+BOOL
+protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol)
+{
+ struct objc_protocol_list* proto_list;
+
+ if (protocol == NULL || anotherProtocol == NULL)
+ return NO;
+
+ if (protocol == anotherProtocol)
+ return YES;
+
+ /* Check that the objects are Protocol objects before casting them
+ to (struct objc_protocol *). */
+ if (protocol->class_pointer != anotherProtocol->class_pointer)
+ return NO;
+
+ if (protocol->class_pointer != objc_lookupClass ("Protocol"))
+ return NO;
+
+ if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
+ ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
+ return YES;
+
+ /* We do not acquire any lock because protocols are currently
+ immutable. We can freely iterate over a protocol structure. */
+ proto_list = ((struct objc_protocol *)protocol)->protocol_list;
+ while (proto_list)
+ {
+ size_t i;
+
+ for (i = 0; i < proto_list->count; i++)
+ {
+ if (protocol_conformsToProtocol (proto_list->list[i], anotherProtocol))
+ return YES;
+ }
+ proto_list = proto_list->next;
+ }
+
+ return NO;
+}
+
+BOOL
+protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol)
+{
+ if (protocol == anotherProtocol)
+ return YES;
+
+ if (protocol == NULL || anotherProtocol == NULL)
+ return NO;
+
+ /* Check that the objects are Protocol objects before casting them
+ to (struct objc_protocol *). */
+ if (protocol->class_pointer != anotherProtocol->class_pointer)
+ return NO;
+
+ if (protocol->class_pointer != objc_lookupClass ("Protocol"))
+ return NO;
+
+ /* Equality between formal protocols is only formal (nothing to do
+ with actually checking the list of methods they have!). Two
+ formal Protocols are equal if and only if they have the same
+ name.
+
+ Please note (for comparisons with other implementations) that
+ checking the names is equivalent to checking that Protocol A
+ conforms to Protocol B and Protocol B conforms to Protocol A,
+ because this happens iff they have the same name. If they have
+ different names, A conforms to B if and only if A includes B, but
+ the situation where A includes B and B includes A is a circular
+ dependency between Protocols which is forbidden by the compiler,
+ so A conforms to B and B conforms to A with A and B having
+ different names is an impossible case. */
+ if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
+ ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
+ return YES;
+
+ return NO;
+}
+
+const char *
+protocol_getName (Protocol *protocol)
+{
+ /* Check that it is a Protocol object before casting it to (struct
+ objc_protocol *). */
+ if (protocol->class_pointer != objc_lookupClass ("Protocol"))
+ return NULL;
+
+ return ((struct objc_protocol *)protocol)->protocol_name;
+}
+
+struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
+ SEL selector,
+ BOOL requiredMethod,
+ BOOL instanceMethod)
+{
+ struct objc_method_description no_result = { NULL, NULL };
+ const char* selector_name;
+ struct objc_method_description_list *methods;
+ int i;
+
+ /* TODO: New ABI. */
+ /* The current ABI does not have any information on optional protocol methods. */
+ if (! requiredMethod)
+ return no_result;
+
+ /* Check that it is a Protocol object before casting it to (struct
+ objc_protocol *). */
+ if (protocol->class_pointer != objc_lookupClass ("Protocol"))
+ return no_result;
+
+ selector_name = sel_getName (selector);
+
+ if (instanceMethod)
+ methods = ((struct objc_protocol *)protocol)->instance_methods;
+ else
+ methods = ((struct objc_protocol *)protocol)->class_methods;
+
+ if (methods)
+ {
+ for (i = 0; i < methods->count; i++)
+ {
+ if (strcmp ((char*)(methods->list[i].name), selector_name) == 0)
+ return methods->list[i];
+ }
+ }
+
+ return no_result;
+}
+
+struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
+ BOOL requiredMethod,
+ BOOL instanceMethod,
+ unsigned int *numberOfReturnedMethods)
+{
+ struct objc_method_description_list *methods;
+ unsigned int count = 0;
+ struct objc_method_description *returnValue = NULL;
+
+ /* TODO: New ABI */
+ /* The current ABI does not have any information on optional protocol methods. */
+ if (! requiredMethod)
+ {
+ if (numberOfReturnedMethods)
+ *numberOfReturnedMethods = 0;
+
+ return NULL;
+ }
+
+ /* Check that it is a Protocol object before casting it to (struct
+ objc_protocol *). */
+ if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
+ {
+ if (numberOfReturnedMethods)
+ *numberOfReturnedMethods = 0;
+
+ return NULL;
+ }
+
+ /* We do not acquire any lock because protocols are currently
+ immutable. We can freely iterate over a protocol structure. */
+
+ if (instanceMethod)
+ methods = ((struct objc_protocol *)protocol)->instance_methods;
+ else
+ methods = ((struct objc_protocol *)protocol)->class_methods;
+
+ if (methods)
+ {
+ unsigned int i;
+ count = methods->count;
+
+ /* Allocate enough memory to hold them. */
+ returnValue = (struct objc_method_description *)(malloc (sizeof (struct objc_method_description) * (count + 1)));
+
+ /* Copy them. */
+ for (i = 0; i < count; i++)
+ {
+ returnValue[i].name = methods->list[i].name;
+ returnValue[i].types = methods->list[i].types;
+ }
+ returnValue[i].name = NULL;
+ returnValue[i].types = NULL;
+ }
+
+ if (numberOfReturnedMethods)
+ *numberOfReturnedMethods = count;
+
+ return returnValue;
+}
+
+Property protocol_getProperty (Protocol *protocol, const char *propertyName,
+ BOOL requiredProperty, BOOL instanceProperty)
+{
+ if (protocol == NULL || propertyName == NULL)
+ return NULL;
+
+ if (!requiredProperty || !instanceProperty)
+ return NULL;
+
+ /* Check that it is a Protocol object before casting it to (struct
+ objc_protocol *). */
+ if (protocol->class_pointer != objc_lookupClass ("Protocol"))
+ return NULL;
+
+ /* TODO: New ABI. */
+ /* The current ABI does not have any information on protocol properties. */
+ return NULL;
+}
+
+Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties)
+{
+ unsigned int count = 0;
+ Property *returnValue = NULL;
+
+ /* Check that it is a Protocol object before casting it to (struct
+ objc_protocol *). */
+ if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
+ {
+ if (numberOfReturnedProperties)
+ *numberOfReturnedProperties = 0;
+
+ return NULL;
+ }
+
+ /* We do not acquire any lock because protocols are currently
+ immutable. We can freely iterate over a protocol structure. */
+
+ /* TODO: New ABI. */
+ /* The current ABI does not have any information on protocol properties. */
+ if (numberOfReturnedProperties)
+ *numberOfReturnedProperties = count;
+
+ return returnValue;
+}
+
+Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols)
+{
+ unsigned int count = 0;
+ Protocol **returnValue = NULL;
+ struct objc_protocol_list* proto_list;
+
+ /* Check that it is a Protocol object before casting it to (struct
+ objc_protocol *). */
+ if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
+ {
+ if (numberOfReturnedProtocols)
+ *numberOfReturnedProtocols = 0;
+
+ return NULL;
+ }
+
+ /* We do not acquire any lock because protocols are currently
+ immutable. We can freely iterate over a protocol structure. */
+
+ /* Count how many protocols we have. */
+ proto_list = ((struct objc_protocol *)protocol)->protocol_list;
+
+ while (proto_list)
+ {
+ count = count + proto_list->count;
+ proto_list = proto_list->next;
+ }
+
+ if (count != 0)
+ {
+ unsigned int i = 0;
+
+ /* Allocate enough memory to hold them. */
+ returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
+
+ /* Copy the protocols. */
+ proto_list = ((struct objc_protocol *)protocol)->protocol_list;
+
+ while (proto_list)
+ {
+ size_t j;
+ for (j = 0; j < proto_list->count; j++)
+ {
+ returnValue[i] = proto_list->list[j];
+ i++;
+ }
+ proto_list = proto_list->next;
+ }
+
+ returnValue[i] = NULL;
+ }
+
+ if (numberOfReturnedProtocols)
+ *numberOfReturnedProtocols = count;
+
+ return returnValue;
+}
diff --git a/libobjc/sarray.c b/libobjc/sarray.c
index 8d5303701e0..9dd160e51eb 100644
--- a/libobjc/sarray.c
+++ b/libobjc/sarray.c
@@ -24,9 +24,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "objc-private/common.h"
#include "objc-private/sarray.h"
-#include "objc/objc.h"
-#include "objc/objc-api.h"
-#include "objc/thr.h"
+#include "objc/runtime.h" /* For objc_malloc */
+#include "objc/thr.h" /* For objc_mutex_lock */
#include "objc-private/runtime.h"
#include <stdio.h>
#include <string.h> /* For memset */
diff --git a/libobjc/selector.c b/libobjc/selector.c
index 93952fd3834..1d4bc7e69d7 100644
--- a/libobjc/selector.c
+++ b/libobjc/selector.c
@@ -23,7 +23,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "objc-private/common.h"
-#include "objc/objc.h"
#include "objc/objc-api.h"
#include "objc/thr.h"
#include "objc-private/hash.h"
@@ -163,6 +162,14 @@ void __objc_register_instance_methods_to_class (Class class)
__objc_update_dispatch_table_for_class (class->class_pointer);
}
+BOOL
+sel_isEqual (SEL s1, SEL s2)
+{
+ if (s1 == 0 || s2 == 0)
+ return s1 == s2;
+ else
+ return s1->sel_id == s2->sel_id;
+}
/* Returns YES iff t1 and t2 have same method types, but we ignore
the argframe layout */
@@ -293,6 +300,9 @@ const char *sel_getName (SEL selector)
{
const char *ret;
+ if (selector == NULL)
+ return "<null selector>";
+
objc_mutex_lock (__objc_runtime_mutex);
if ((soffset_decode ((sidx)selector->sel_id) > 0)
&& (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
@@ -306,6 +316,9 @@ const char *sel_getName (SEL selector)
/* Traditional GNU Objective-C Runtime API. */
const char *sel_get_name (SEL selector)
{
+ if (selector == NULL)
+ return 0;
+
return sel_getName (selector);
}
diff --git a/libobjc/sendmsg.c b/libobjc/sendmsg.c
index a822af4a31a..02be39c5b05 100644
--- a/libobjc/sendmsg.c
+++ b/libobjc/sendmsg.c
@@ -33,7 +33,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tconfig.h"
#include "coretypes.h"
#include "tm.h"
-#include "objc/objc.h"
#include "objc/objc-api.h"
#include "objc/thr.h"
#include "objc-private/runtime.h"
diff --git a/libobjc/thr.c b/libobjc/thr.c
index 50196e81c58..609872d3d17 100644
--- a/libobjc/thr.c
+++ b/libobjc/thr.c
@@ -38,8 +38,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tm.h"
#include "defaults.h"
#include "objc/thr.h"
-#include "objc/objc.h"
-#include "objc/objc-api.h"
+#include "objc/runtime.h"
#include "objc-private/runtime.h"
#include <gthr.h>