|
|
1.1 ! root 1: /* GNU Objective C Runtime class related functions ! 2: Copyright (C) 1993 Free Software Foundation, Inc. ! 3: ! 4: Author: Kresten Krab Thorup, Dennis Glatting ! 5: ! 6: This file is part of GNU CC. ! 7: ! 8: GNU CC is free software; you can redistribute it and/or modify it under the ! 9: terms of the GNU General Public License as published by the Free Software ! 10: Foundation; either version 2, or (at your option) any later version. ! 11: ! 12: GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY ! 13: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ! 14: FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ! 15: details. ! 16: ! 17: You should have received a copy of the GNU General Public License along with ! 18: GNU CC; see the file COPYING. If not, write to the Free Software ! 19: Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 20: ! 21: /* As a special exception, if you link this library with files compiled with ! 22: GCC to produce an executable, this does not cause the resulting executable ! 23: to be covered by the GNU General Public License. This exception does not ! 24: however invalidate any other reasons why the executable file might be ! 25: covered by the GNU General Public License. */ ! 26: ! 27: #include "runtime.h" /* the kitchen sink */ ! 28: #include "sarray.h" ! 29: ! 30: /* The table of classname->class. Used for objc_lookup_class and friends */ ! 31: static cache_ptr __objc_class_hash = 0; ! 32: ! 33: /* This is a hook which is called by objc_get_class and ! 34: objc_lookup_class if the runtime is not able to find the class. ! 35: This may e.g. try to load in the class using dynamic loading */ ! 36: Class* (*_objc_lookup_class)(const char* name) = 0; ! 37: ! 38: ! 39: /* True when class links has been resolved */ ! 40: BOOL __objc_class_links_resolved = NO; ! 41: ! 42: ! 43: /* Initial number of buckets size of class hash table. */ ! 44: #define CLASS_HASH_SIZE 32 ! 45: ! 46: void __objc_init_class_tables() ! 47: { ! 48: /* Allocate the class hash table */ ! 49: ! 50: if(__objc_class_hash) ! 51: return; ! 52: ! 53: __objc_class_hash ! 54: = hash_new (CLASS_HASH_SIZE, ! 55: (hash_func_type) hash_string, ! 56: (compare_func_type) compare_strings); ! 57: } ! 58: ! 59: /* This function adds a class to the class hash table, and assigns the ! 60: class a number, unless it's already known */ ! 61: void ! 62: __objc_add_class_to_hash(Class* class) ! 63: { ! 64: Class* h_class; ! 65: ! 66: /* make sure the table is there */ ! 67: assert(__objc_class_hash); ! 68: ! 69: /* make sure it's not a meta class */ ! 70: assert(CLS_ISCLASS(class)); ! 71: ! 72: /* Check to see if the class is already in the hash table. */ ! 73: h_class = hash_value_for_key (__objc_class_hash, class->name); ! 74: if (!h_class) ! 75: { ! 76: /* The class isn't in the hash table. Add the class and assign a class ! 77: number. */ ! 78: static unsigned int class_number = 1; ! 79: ! 80: CLS_SETNUMBER(class, class_number); ! 81: CLS_SETNUMBER(class->class_pointer, class_number); ! 82: ! 83: ++class_number; ! 84: hash_add (&__objc_class_hash, class->name, class); ! 85: } ! 86: } ! 87: ! 88: /* Get the class object for the class named NAME. If NAME does not ! 89: identify a known class, the hook _objc_lookup_class is called. If ! 90: this fails, nil is returned */ ! 91: Class* objc_lookup_class (const char* name) ! 92: { ! 93: Class* class; ! 94: ! 95: /* Make sure the class hash table exists. */ ! 96: assert (__objc_class_hash); ! 97: ! 98: class = hash_value_for_key (__objc_class_hash, name); ! 99: ! 100: if (class) ! 101: return class; ! 102: ! 103: if (_objc_lookup_class) ! 104: return (*_objc_lookup_class)(name); ! 105: else ! 106: return 0; ! 107: } ! 108: ! 109: /* Get the class object for the class named NAME. If NAME does not ! 110: identify a known class, the hook _objc_lookup_class is called. If ! 111: this fails, an error message is issued and the system aborts */ ! 112: Class* ! 113: objc_get_class (const char *name) ! 114: { ! 115: Class* class; ! 116: ! 117: /* Make sure the class hash table exists. */ ! 118: assert (__objc_class_hash); ! 119: ! 120: class = hash_value_for_key (__objc_class_hash, name); ! 121: ! 122: if (class) ! 123: return class; ! 124: ! 125: if (_objc_lookup_class) ! 126: class = (*_objc_lookup_class)(name); ! 127: ! 128: if(class) ! 129: return class; ! 130: ! 131: fprintf(stderr, "objc runtime: cannot find class %s\n", name); ! 132: abort(); ! 133: } ! 134: ! 135: ! 136: /* Resolve super/subclass links for all classes. The only thing we ! 137: can be sure of is that the class_pointer for class objects point ! 138: to the right meta class objects */ ! 139: void __objc_resolve_class_links() ! 140: { ! 141: node_ptr node; ! 142: Class* object_class = objc_get_class ("Object"); ! 143: ! 144: assert(object_class); ! 145: ! 146: /* Assign subclass links */ ! 147: for (node = hash_next (__objc_class_hash, NULL); node; ! 148: node = hash_next (__objc_class_hash, node)) ! 149: { ! 150: Class* class1 = node->value; ! 151: ! 152: /* Make sure we have what we think we have. */ ! 153: assert (CLS_ISCLASS(class1)); ! 154: assert (CLS_ISMETA(class1->class_pointer)); ! 155: ! 156: /* The class_pointer of all meta classes point to Object's meta class. */ ! 157: class1->class_pointer->class_pointer = object_class->class_pointer; ! 158: ! 159: if (!(CLS_ISRESOLV(class1))) ! 160: { ! 161: CLS_SETRESOLV(class1); ! 162: CLS_SETRESOLV(class1->class_pointer); ! 163: ! 164: if(class1->super_class) ! 165: { ! 166: Class* a_super_class ! 167: = objc_get_class ((char *) class1->super_class); ! 168: ! 169: assert (a_super_class); ! 170: ! 171: DEBUG_PRINTF ("making class connections for: %s\n", ! 172: class1->name); ! 173: ! 174: /* assign subclass links for superclass */ ! 175: class1->sibling_class = a_super_class->subclass_list; ! 176: a_super_class->subclass_list = class1; ! 177: ! 178: /* Assign subclass links for meta class of superclass */ ! 179: if (a_super_class->class_pointer) ! 180: { ! 181: class1->class_pointer->sibling_class ! 182: = a_super_class->class_pointer->subclass_list; ! 183: a_super_class->class_pointer->subclass_list ! 184: = class1->class_pointer; ! 185: } ! 186: } ! 187: else /* a root class, make its meta object */ ! 188: /* be a subclass of Object */ ! 189: { ! 190: class1->class_pointer->sibling_class ! 191: = object_class->subclass_list; ! 192: object_class->subclass_list = class1->class_pointer; ! 193: } ! 194: } ! 195: } ! 196: ! 197: /* Assign superclass links */ ! 198: for (node = hash_next (__objc_class_hash, NULL); node; ! 199: node = hash_next (__objc_class_hash, node)) ! 200: { ! 201: Class* class1 = node->value; ! 202: Class* sub_class; ! 203: for (sub_class = class1->subclass_list; sub_class; ! 204: sub_class = sub_class->sibling_class) ! 205: { ! 206: sub_class->super_class = class1; ! 207: if(CLS_ISCLASS(sub_class)) ! 208: sub_class->class_pointer->super_class = class1->class_pointer; ! 209: } ! 210: } ! 211: } ! 212: ! 213: ! 214: ! 215: #define CLASSOF(c) ((c)->class_pointer) ! 216: ! 217: Class* ! 218: class_pose_as (Class* impostor, Class* super_class) ! 219: { ! 220: node_ptr node; ! 221: Class* class1; ! 222: ! 223: if (!CLS_ISRESOLV (impostor)) ! 224: __objc_resolve_class_links (); ! 225: ! 226: /* preconditions */ ! 227: assert (impostor); ! 228: assert (super_class); ! 229: assert (impostor->super_class == super_class); ! 230: assert (CLS_ISCLASS (impostor)); ! 231: assert (CLS_ISCLASS (super_class)); ! 232: assert (impostor->instance_size == super_class->instance_size); ! 233: ! 234: { ! 235: Class **subclass = &(super_class->subclass_list); ! 236: ! 237: /* move subclasses of super_class to impostor */ ! 238: while (*subclass) ! 239: { ! 240: Class *nextSub = (*subclass)->sibling_class; ! 241: ! 242: if (*subclass != impostor) ! 243: { ! 244: Class *sub = *subclass; ! 245: ! 246: /* classes */ ! 247: sub->sibling_class = impostor->subclass_list; ! 248: sub->super_class = impostor; ! 249: impostor->subclass_list = sub; ! 250: ! 251: /* It will happen that SUB is not a class object if it is ! 252: the top of the meta class hierachy chain. (root ! 253: meta-class objects inherit theit class object) If that is ! 254: the case... dont mess with the meta-meta class. */ ! 255: if (CLS_ISCLASS (sub)) ! 256: { ! 257: /* meta classes */ ! 258: CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list; ! 259: CLASSOF (sub)->super_class = CLASSOF (impostor); ! 260: CLASSOF (impostor)->subclass_list = CLASSOF (sub); ! 261: } ! 262: } ! 263: ! 264: *subclass = nextSub; ! 265: } ! 266: ! 267: /* set subclasses of superclass to be impostor only */ ! 268: super_class->subclass_list = impostor; ! 269: CLASSOF (super_class)->subclass_list = CLASSOF (impostor); ! 270: ! 271: /* set impostor to have no sibling classes */ ! 272: impostor->sibling_class = 0; ! 273: CLASSOF (impostor)->sibling_class = 0; ! 274: } ! 275: ! 276: /* check relationship of impostor and super_class is kept. */ ! 277: assert (impostor->super_class == super_class); ! 278: assert (CLASSOF (impostor)->super_class == CLASSOF (super_class)); ! 279: ! 280: /* This is how to update the lookup table. Regardless of ! 281: what the keys of the hashtable is, change all values that are ! 282: suprecalss into impostor. */ ! 283: ! 284: for (node = hash_next (__objc_class_hash, NULL); node; ! 285: node = hash_next (__objc_class_hash, node)) ! 286: { ! 287: class1 = (Class*)node->value; ! 288: if (class1 == super_class) ! 289: { ! 290: node->value = impostor; /* change hash table value */ ! 291: } ! 292: } ! 293: ! 294: /* next, we update the dispatch tables... */ ! 295: __objc_update_dispatch_table_for_class (CLASSOF (impostor)); ! 296: __objc_update_dispatch_table_for_class (impostor); ! 297: ! 298: return impostor; ! 299: } ! 300: ! 301:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.