/* GNU Objective C Runtime selector related functions
- Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1993-2019 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
This file is part of GCC.
#include "objc-private/runtime.h"
#include "objc-private/sarray.h"
#include "objc-private/selector.h"
+#include <stdlib.h> /* For malloc. */
/* Initial selector hash table size. Value doesn't matter much. */
#define SELECTOR_HASH_SIZE 128
/* Return YES iff t1 and t2 have same method types. Ignore the
argframe layout. */
-BOOL
+static BOOL
sel_types_match (const char *t1, const char *t2)
{
if (! t1 || ! t2)
/* Return selector representing name. */
SEL
-sel_get_typed_uid (const char *name, const char *types)
+sel_get_any_uid (const char *name)
{
struct objc_list *l;
sidx i;
objc_mutex_lock (__objc_runtime_mutex);
i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
- if (i == 0)
+ if (soffset_decode (i) == 0)
{
objc_mutex_unlock (__objc_runtime_mutex);
return 0;
}
- for (l = (struct objc_list *) sarray_get_safe (__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)
- {
- objc_mutex_unlock (__objc_runtime_mutex);
- return s;
- }
- }
- else if (sel_types_match (s->sel_types, types))
- {
- objc_mutex_unlock (__objc_runtime_mutex);
- return s;
- }
- }
-
+ l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
objc_mutex_unlock (__objc_runtime_mutex);
- return 0;
+
+ if (l == 0)
+ return 0;
+
+ return (SEL) l->head;
}
-/* Return selector representing name; prefer a selector with non-NULL
- type. */
SEL
-sel_get_any_typed_uid (const char *name)
+sel_getTypedSelector (const char *name)
{
- struct objc_list *l;
sidx i;
- SEL s = NULL;
+ if (name == NULL)
+ return NULL;
+
objc_mutex_lock (__objc_runtime_mutex);
-
+
+ /* Look for a typed selector. */
i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
- if (i == 0)
+ if (i != 0)
{
- objc_mutex_unlock (__objc_runtime_mutex);
- return 0;
- }
+ struct objc_list *l;
+ SEL returnValue = NULL;
- for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
- l; l = l->tail)
- {
- s = (SEL) l->head;
- if (s->sel_types)
+ for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
+ l; l = l->tail)
+ {
+ SEL s = (SEL) l->head;
+ if (s->sel_types)
+ {
+ if (returnValue == NULL)
+ {
+ /* First typed selector that we find. Keep it in
+ returnValue, but keep checking as we want to
+ detect conflicts. */
+ returnValue = s;
+ }
+ else
+ {
+ /* We had already found a typed selectors, so we
+ have multiple ones. Double-check that they have
+ different types, just in case for some reason we
+ got duplicates with the same types. If so, it's
+ OK, we'll ignore the duplicate. */
+ if (returnValue->sel_types == s->sel_types)
+ continue;
+ else if (sel_types_match (returnValue->sel_types, s->sel_types))
+ continue;
+ else
+ {
+ /* The types of the two selectors are different;
+ it's a conflict. Too bad. Return NULL. */
+ objc_mutex_unlock (__objc_runtime_mutex);
+ return NULL;
+ }
+ }
+ }
+ }
+
+ if (returnValue != NULL)
{
objc_mutex_unlock (__objc_runtime_mutex);
- return s;
+ return returnValue;
}
}
+ /* No typed selector found. Return NULL. */
objc_mutex_unlock (__objc_runtime_mutex);
- return s;
+ return 0;
}
-/* Return selector representing name. */
-SEL
-sel_get_any_uid (const char *name)
+SEL *
+sel_copyTypedSelectorList (const char *name, unsigned int *numberOfReturnedSelectors)
{
- struct objc_list *l;
+ unsigned int count = 0;
+ SEL *returnValue = NULL;
sidx i;
+
+ if (name == NULL)
+ {
+ if (numberOfReturnedSelectors)
+ *numberOfReturnedSelectors = 0;
+ return NULL;
+ }
objc_mutex_lock (__objc_runtime_mutex);
+ /* Count how many selectors we have. */
i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
- if (soffset_decode (i) == 0)
+ if (i != 0)
{
- objc_mutex_unlock (__objc_runtime_mutex);
- return 0;
- }
+ struct objc_list *selector_list = NULL;
+ selector_list = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
- l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
- objc_mutex_unlock (__objc_runtime_mutex);
+ /* Count how many selectors we have. */
+ {
+ struct objc_list *l;
+ for (l = selector_list; l; l = l->tail)
+ count++;
+ }
- if (l == 0)
- return 0;
+ if (count != 0)
+ {
+ /* Allocate enough memory to hold them. */
+ returnValue = (SEL *)(malloc (sizeof (SEL) * (count + 1)));
+
+ /* Copy the selectors. */
+ {
+ unsigned int j;
+ for (j = 0; j < count; j++)
+ {
+ returnValue[j] = (SEL)(selector_list->head);
+ selector_list = selector_list->tail;
+ }
+ returnValue[j] = NULL;
+ }
+ }
+ }
- return (SEL) l->head;
+ objc_mutex_unlock (__objc_runtime_mutex);
+
+ if (numberOfReturnedSelectors)
+ *numberOfReturnedSelectors = count;
+
+ return returnValue;
}
/* Get the name of a selector. If the selector is unknown, the empty
return ret;
}
-/* Traditional GNU Objective-C Runtime API. */
-const char *sel_get_name (SEL selector)
-{
- if (selector == NULL)
- return 0;
-
- return sel_getName (selector);
-}
-
BOOL
sel_is_mapped (SEL selector)
{
return ((idx > 0) && (idx <= __objc_selector_max_index));
}
-const char *sel_getType (SEL selector)
+const char *sel_getTypeEncoding (SEL selector)
{
if (selector)
return selector->sel_types;
return 0;
}
-/* Traditional GNU Objective-C Runtime API. */
-const char *sel_get_type (SEL selector)
-{
- return sel_getType (selector);
-}
-
/* The uninstalled dispatch table. */
extern struct sarray *__objc_uninstalled_dtable;
i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
if (soffset_decode (i) != 0)
{
- for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
+ /* There are already selectors with that name. Examine them to
+ see if the one we're registering already exists. */
+ for (l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
l; l = l->tail)
{
- SEL s = (SEL) l->head;
+ SEL s = (SEL)l->head;
if (types == 0 || s->sel_types == 0)
{
if (s->sel_types == types)
{
if (orig)
{
- orig->sel_id = (void *) i;
+ orig->sel_id = (void *)i;
return orig;
}
else
return s;
}
}
- else if (! strcmp (s->sel_types, types))
+ else if (sel_types_match (s->sel_types, types))
{
if (orig)
{
- orig->sel_id = (void *) i;
+ orig->sel_id = (void *)i;
return orig;
}
else
return s;
}
}
+ /* A selector with this specific name/type combination does not
+ exist yet. We need to register it. */
if (orig)
j = orig;
else
j = pool_alloc_selector ();
- j->sel_id = (void *) i;
- /* Can we use the pointer or must copy types? Don't copy if
+ j->sel_id = (void *)i;
+ /* Can we use the pointer or must we copy types ? Don't copy if
NULL. */
if ((is_const) || (types == 0))
- j->sel_types = (const char *) types;
+ j->sel_types = types;
else
{
- j->sel_types = (char *) objc_malloc (strlen (types) + 1);
- strcpy ((char *) j->sel_types, types);
+ j->sel_types = (char *)objc_malloc (strlen (types) + 1);
+ strcpy ((char *)j->sel_types, types);
}
- l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
+ l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
}
else
{
+ /* There are no other selectors with this name registered in the
+ runtime tables. */
+ const char *new_name;
+
+ /* Determine i. */
__objc_selector_max_index += 1;
i = soffset_encode (__objc_selector_max_index);
+
+ /* Prepare the selector. */
if (orig)
j = orig;
else
j = pool_alloc_selector ();
- j->sel_id = (void *) i;
- /* Can we use the pointer or must copy types? Don't copy if
+ j->sel_id = (void *)i;
+ /* Can we use the pointer or must we copy types ? Don't copy if
NULL. */
- if ((is_const) || (types == 0))
- j->sel_types = (const char *) types;
+ if (is_const || (types == 0))
+ j->sel_types = types;
else
{
- j->sel_types = (char *) objc_malloc (strlen (types) + 1);
- strcpy ((char *) j->sel_types, types);
+ j->sel_types = (char *)objc_malloc (strlen (types) + 1);
+ strcpy ((char *)j->sel_types, types);
}
+
+ /* Since this is the first selector with this name, we need to
+ register the correspondence between 'i' (the sel_id) and
+ 'name' (the actual string) in __objc_selector_names and
+ __objc_selector_hash. */
+
+ /* Can we use the pointer or must we copy name ? Don't copy if
+ NULL. (FIXME: Can the name really be NULL here ?) */
+ if (is_const || (name == 0))
+ new_name = name;
+ else
+ {
+ new_name = (char *)objc_malloc (strlen (name) + 1);
+ strcpy ((char *)new_name, name);
+ }
+
+ /* This maps the sel_id to the name. */
+ sarray_at_put_safe (__objc_selector_names, i, (void *)new_name);
+
+ /* This maps the name to the sel_id. */
+ objc_hash_add (&__objc_selector_hash, (void *)new_name, (void *)i);
+
l = 0;
}
DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
- (long) soffset_decode (i));
-
- {
- int is_new = (l == 0);
- const char *new_name;
-
- /* Can we use the pointer or must copy name? Don't copy if
- NULL. */
- if ((is_const) || (name == 0))
- new_name = name;
- else
- {
- new_name = (char *) objc_malloc (strlen (name) + 1);
- strcpy ((char *) new_name, name);
- }
-
- l = list_cons ((void *) j, l);
- sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
- sarray_at_put_safe (__objc_selector_array, i, (void *) l);
- if (is_new)
- objc_hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
- }
-
+ (long)soffset_decode (i));
+
+ /* Now add the selector to the list of selectors with that id. */
+ l = list_cons ((void *)j, l);
+ sarray_at_put_safe (__objc_selector_array, i, (void *)l);
+
sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
- return (SEL) j;
+ return (SEL)j;
}
SEL
sel_registerName (const char *name)
{
SEL ret;
+
+ if (name == NULL)
+ return NULL;
objc_mutex_lock (__objc_runtime_mutex);
/* Assume that name is not constant static memory and needs to be
return ret;
}
-/* Traditional GNU Objective-C Runtime API. */
-SEL
-sel_register_name (const char *name)
-{
- return sel_registerName (name);
-}
-
SEL
sel_registerTypedName (const char *name, const char *type)
{
SEL ret;
+ if (name == NULL)
+ return NULL;
+
objc_mutex_lock (__objc_runtime_mutex);
/* Assume that name and type are not constant static memory and need
to be copied before put into a runtime structure. is_const ==
return ret;
}
-SEL
-sel_register_typed_name (const char *name, const char *type)
-{
- return sel_registerTypedName (name, type);
-}
-
/* Return the selector representing name. */
SEL
sel_getUid (const char *name)
{
return sel_registerTypedName (name, 0);
}
-
-/* Traditional GNU Objective-C Runtime API. */
-SEL
-sel_get_uid (const char *name)
-{
- return sel_getUid (name);
-}