|
|
1.1 root 1: /* GNU Objective C Runtime selector related functions 1.1.1.3 ! root 2: Copyright (C) 1993, 1995 Free Software Foundation, Inc. ! 3: Contributed by Kresten Krab Thorup 1.1 root 4: 5: This file is part of GNU CC. 6: 7: GNU CC is free software; you can redistribute it and/or modify it under the 1.1.1.3 ! root 8: terms of the GNU General Public License as published by the Free Software ! 9: Foundation; either version 2, or (at your option) any later version. 1.1 root 10: 11: GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY 1.1.1.3 ! root 12: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ! 13: FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ! 14: details. 1.1 root 15: 16: You should have received a copy of the GNU General Public License along with 1.1.1.3 ! root 17: GNU CC; see the file COPYING. If not, write to the Free Software ! 18: Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 1.1 root 19: 20: /* As a special exception, if you link this library with files compiled with 21: GCC to produce an executable, this does not cause the resulting executable 22: to be covered by the GNU General Public License. This exception does not 23: however invalidate any other reasons why the executable file might be 24: covered by the GNU General Public License. */ 25: 26: #include "runtime.h" 27: #include "objc/sarray.h" 1.1.1.2 root 28: #include "encoding.h" 1.1 root 29: 1.1.1.3 ! root 30: /* Initial selector hash table size. Value doesn't matter much */ 1.1 root 31: #define SELECTOR_HASH_SIZE 128 32: 33: /* Tables mapping selector names to uid and opposite */ 1.1.1.2 root 34: static struct sarray* __objc_selector_array = 0; /* uid -> sel */ 35: static struct sarray* __objc_selector_names = 0; /* uid -> name */ 1.1 root 36: static cache_ptr __objc_selector_hash = 0; /* name -> uid */ 37: 38: static void register_selectors_from_list(MethodList_t); 39: 40: /* Number of selectors stored in each of the above tables */ 41: int __objc_selector_max_index = 0; 42: 43: void __objc_init_selector_tables() 44: { 45: __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0); 1.1.1.2 root 46: __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0); 1.1 root 47: __objc_selector_hash 48: = hash_new (SELECTOR_HASH_SIZE, 49: (hash_func_type) hash_string, 50: (compare_func_type) compare_strings); 51: } 52: 53: /* This routine is given a class and records all of the methods in its class 54: structure in the record table. */ 55: void 1.1.1.3 ! root 56: __objc_register_selectors_from_class (Class class) 1.1 root 57: { 58: MethodList_t method_list; 59: 60: method_list = class->methods; 61: while (method_list) 62: { 63: register_selectors_from_list (method_list); 64: method_list = method_list->method_next; 65: } 66: } 67: 68: 69: /* This routine is given a list of methods and records each of the methods in 70: the record table. This is the routine that does the actual recording 71: work. 72: 73: This one is only called for Class objects. For categories, 74: class_add_method_list is called. 75: */ 76: static void 77: register_selectors_from_list (MethodList_t method_list) 78: { 79: int i = 0; 80: while (i < method_list->method_count) 81: { 82: Method_t method = &method_list->method_list[i]; 1.1.1.2 root 83: method->method_name 84: = sel_register_typed_name ((const char*)method->method_name, 85: method->method_types); 1.1 root 86: i += 1; 87: } 88: } 89: 1.1.1.2 root 90: 91: /* Returns YES iff t1 and t2 have same method types, but we ignore 92: the argframe layout */ 93: BOOL 94: sel_types_match (const char* t1, const char* t2) 95: { 96: if (!t1 || !t2) 97: return NO; 98: while (*t1 && *t2) 99: { 100: if (*t1 == '+') t1++; 101: if (*t2 == '+') t2++; 102: while (isdigit(*t1)) t1++; 103: while (isdigit(*t2)) t2++; 104: /* xxx Remove these next two lines when qualifiers are put in 105: all selectors, not just Protocol selectors. */ 106: t1 = objc_skip_type_qualifiers(t1); 107: t2 = objc_skip_type_qualifiers(t2); 108: if (!*t1 && !*t2) 109: return YES; 110: if (*t1 != *t2) 111: return NO; 112: t1++; 113: t2++; 114: } 115: return NO; 116: } 117: 118: /* return selector representing name */ 119: SEL 120: sel_get_typed_uid (const char *name, const char *types) 121: { 122: struct objc_list *l; 123: sidx i; 124: 125: i = (sidx) hash_value_for_key (__objc_selector_hash, name); 126: if (i == 0) 127: return 0; 128: 129: for (l = (struct objc_list*)sarray_get (__objc_selector_array, i); 130: l; l = l->tail) 131: { 132: SEL s = (SEL)l->head; 133: if (types == 0 || s->sel_types == 0) 134: { 135: if (s->sel_types == types) 136: { 137: return s; 138: } 139: } 140: else if (sel_types_match (s->sel_types, types)) 141: { 142: return s; 143: } 144: } 145: 146: return 0; 147: } 148: 1.1.1.3 ! root 149: /* Return selector representing name; prefer a selector with non-NULL type */ ! 150: SEL ! 151: sel_get_any_typed_uid (const char *name) ! 152: { ! 153: struct objc_list *l; ! 154: sidx i; ! 155: SEL s; ! 156: ! 157: i = (sidx) hash_value_for_key (__objc_selector_hash, name); ! 158: if (i == 0) ! 159: return 0; ! 160: ! 161: for (l = (struct objc_list*)sarray_get (__objc_selector_array, i); ! 162: l; l = l->tail) ! 163: { ! 164: s = (SEL) l->head; ! 165: if (s->sel_types) ! 166: return s; ! 167: } ! 168: ! 169: return s; ! 170: } ! 171: 1.1.1.2 root 172: /* return selector representing name */ 173: SEL 174: sel_get_any_uid (const char *name) 175: { 176: struct objc_list *l; 177: sidx i; 178: 179: i = (sidx) hash_value_for_key (__objc_selector_hash, name); 180: if (soffset_decode (i) == 0) 181: return 0; 182: 183: l = (struct objc_list*)sarray_get (__objc_selector_array, i); 184: if (l == 0) 185: return 0; 186: 187: return (SEL)l->head; 188: } 189: 1.1 root 190: /* return selector representing name */ 191: SEL 192: sel_get_uid (const char *name) 193: { 1.1.1.2 root 194: return sel_register_typed_name (name, 0); 1.1 root 195: } 196: 197: /* Get name of selector. If selector is unknown, the empty string "" 198: is returned */ 199: const char* 200: sel_get_name (SEL selector) 201: { 1.1.1.2 root 202: if ((soffset_decode((sidx)selector->sel_id) > 0) 203: && (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index)) 204: return sarray_get (__objc_selector_names, (sidx) selector->sel_id); 1.1 root 205: else 1.1.1.2 root 206: return 0; 1.1 root 207: } 208: 209: BOOL 210: sel_is_mapped (SEL selector) 211: { 1.1.1.2 root 212: unsigned int idx = soffset_decode ((sidx)selector->sel_id); 1.1 root 213: return ((idx > 0) && (idx <= __objc_selector_max_index)); 214: } 215: 1.1.1.2 root 216: 217: const char* 218: sel_get_type (SEL selector) 219: { 220: if (selector) 221: return selector->sel_types; 222: else 223: return 0; 224: } 225: 1.1 root 226: /* The uninstalled dispatch table */ 227: extern struct sarray* __objc_uninstalled_dtable; 228: 229: /* Store the passed selector name in the selector record and return its 230: selector value (value returned by sel_get_uid). */ 231: SEL 1.1.1.2 root 232: __sel_register_typed_name (const char *name, const char *types, 233: struct objc_selector *orig) 1.1 root 234: { 1.1.1.2 root 235: struct objc_selector* j; 1.1 root 236: sidx i; 1.1.1.2 root 237: struct objc_list *l; 1.1 root 238: 1.1.1.2 root 239: i = (sidx) hash_value_for_key (__objc_selector_hash, name); 240: if (soffset_decode (i) != 0) 241: { 242: for (l = (struct objc_list*)sarray_get (__objc_selector_array, i); 243: l; l = l->tail) 244: { 245: SEL s = (SEL)l->head; 246: if (types == 0 || s->sel_types == 0) 247: { 248: if (s->sel_types == types) 249: { 250: if (orig) 251: { 252: orig->sel_id = (void*)i; 253: return orig; 254: } 255: else 256: return s; 257: } 258: } 259: else if (!strcmp (s->sel_types, types)) 260: { 261: if (orig) 262: { 263: orig->sel_id = (void*)i; 264: return orig; 265: } 266: else 267: return s; 268: } 269: } 270: if (orig) 271: j = orig; 272: else 273: j = __objc_xmalloc (sizeof (struct objc_selector)); 274: 275: j->sel_id = (void*)i; 276: j->sel_types = (const char*)types; 277: l = (struct objc_list*)sarray_get (__objc_selector_array, i); 278: } 279: else 280: { 281: __objc_selector_max_index += 1; 282: i = soffset_encode(__objc_selector_max_index); 283: if (orig) 284: j = orig; 285: else 286: j = __objc_xmalloc (sizeof (struct objc_selector)); 287: 288: j->sel_id = (void*)i; 289: j->sel_types = (const char*)types; 290: l = 0; 291: } 1.1 root 292: 1.1.1.2 root 293: DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types, 294: soffset_decode (i)); 295: 296: { 297: int is_new = (l == 0); 298: l = list_cons ((void*)j, l); 299: sarray_at_put_safe (__objc_selector_names, i, (void *) name); 300: sarray_at_put_safe (__objc_selector_array, i, (void *) l); 301: if (is_new) 302: hash_add (&__objc_selector_hash, (void *) name, (void *) i); 303: } 1.1 root 304: 1.1.1.2 root 305: sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1); 1.1 root 306: 1.1.1.2 root 307: return (SEL) j; 308: } 1.1 root 309: 1.1.1.2 root 310: SEL 311: sel_register_name (const char *name) 312: { 313: return __sel_register_typed_name (name, 0, 0); 314: } 1.1 root 315: 1.1.1.2 root 316: SEL 317: sel_register_typed_name (const char *name, const char *type) 318: { 319: return __sel_register_typed_name (name, type, 0); 1.1 root 320: } 321:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.