|
|
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: ! 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: /* This is a incomplete implementation of posing. This function does the ! 215: bulk of the work but does not initialize the class method caches. That is ! 216: a run-time specific operation. ! 217: ! 218: I implement posing by hiding SUPER_CLASS, creating new class and meta class ! 219: structures, initializing it with IMPOSTOR, and changing it such that it is ! 220: identified as SUPER_CLASS. SUPER_CLASS remains in the hierarchy but is ! 221: inaccessible by the means. The class hierarchy is then re arranged such ! 222: that all of the subclasses of SUPER_CLASS now inherit from the new class ! 223: structures -- except the impostor itself. The only dramatic effect on the ! 224: application is that subclasses of SUPER_CLASS cannot do a [ .... ! 225: super_class ] and expect their real super class. */ ! 226: Class* ! 227: class_pose_as (Class* impostor, Class* super_class) ! 228: { ! 229: Class* new_class = (Class*) __objc_xcalloc (1, sizeof (Class)); ! 230: MetaClass* new_meta_class = ! 231: (MetaClass*) __objc_xmalloc(sizeof (MetaClass)); ! 232: char *new_name = (char *)__objc_xmalloc ((size_t)strlen ((char*)super_class->name) + 12); ! 233: ! 234: /* We must know the state of the hierachy. Do initial setup if needed */ ! 235: if(!CLS_ISRESOLV(impostor)) ! 236: __objc_resolve_class_links(); ! 237: ! 238: assert (new_class); ! 239: assert (new_meta_class); ! 240: assert (new_name); ! 241: ! 242: assert (CLS_ISCLASS(impostor)); ! 243: assert (CLS_ISCLASS(super_class)); ! 244: ! 245: assert (impostor->instance_size == super_class->instance_size); ! 246: ! 247: /* Create the impostor class. */ ! 248: new_class->class_pointer = new_meta_class; ! 249: new_class->super_class = super_class; ! 250: new_class->name = super_class->name; ! 251: new_class->version = super_class->version; ! 252: new_class->info = super_class->info; ! 253: new_class->instance_size = super_class->instance_size; ! 254: new_class->ivars = super_class->ivars; ! 255: new_class->methods = impostor->methods; ! 256: new_class->dtable = impostor->dtable; ! 257: ! 258: /* Create the impostor meta class. */ ! 259: new_meta_class->class_pointer = super_class->class_pointer->class_pointer; ! 260: new_meta_class->super_class = super_class->class_pointer->super_class; ! 261: new_meta_class->name = super_class->class_pointer->name; ! 262: new_meta_class->version = super_class->class_pointer->version; ! 263: new_meta_class->info = super_class->class_pointer->info; ! 264: new_meta_class->instance_size = super_class->class_pointer->instance_size; ! 265: new_meta_class->ivars = super_class->class_pointer->ivars; ! 266: new_meta_class->methods = impostor->class_pointer->methods; ! 267: new_meta_class->dtable = impostor->class_pointer->dtable; ! 268: ! 269: /* Now change super/subclass links of all related classes. This is rather ! 270: complex, since we have both super_class link, and subclass_list for the ! 271: involved classes. */ ! 272: { ! 273: Class* *classpp; ! 274: MetaClass* *metaclasspp; ! 275: ! 276: /* Remove impostor from subclass list of super_class */ ! 277: for (classpp = &(super_class->subclass_list); ! 278: *classpp; ! 279: classpp = &((*classpp)->sibling_class)) ! 280: { ! 281: if (*classpp == impostor) ! 282: *classpp = (*classpp)->sibling_class; ! 283: if (*classpp == 0) ! 284: break; ! 285: } ! 286: ! 287: /* Do the same for the meta classes */ ! 288: ! 289: for (metaclasspp = &(super_class->class_pointer->subclass_list); ! 290: *metaclasspp; ! 291: metaclasspp = &((*metaclasspp)->sibling_class)) ! 292: { ! 293: if (*metaclasspp == impostor->class_pointer) ! 294: *metaclasspp = (*metaclasspp)->sibling_class; ! 295: if (*metaclasspp == 0) ! 296: break; ! 297: } ! 298: ! 299: /* From the loop above, classpp now points to the sibling_class entry */ ! 300: /* of the last element in the list of subclasses for super_class */ ! 301: ! 302: /* Append the subclass list of impostor to the subclass list of */ ! 303: /* superclass, and excange those two and set subclass of */ ! 304: /* super_class to be impostor only */ ! 305: ! 306: *classpp = impostor->subclass_list; ! 307: new_class->subclass_list = super_class->subclass_list; ! 308: super_class->subclass_list = new_class; ! 309: new_class->sibling_class = 0; ! 310: ! 311: /* Do the same thing for the meta classes */ ! 312: *metaclasspp = impostor->class_pointer->subclass_list; ! 313: new_meta_class->subclass_list = super_class->class_pointer->subclass_list; ! 314: super_class->class_pointer->subclass_list = new_meta_class; ! 315: new_meta_class->sibling_class = 0; ! 316: ! 317: /* Update superclass links for all subclasses of new_class */ ! 318: for (classpp = &(new_class->subclass_list); *classpp; ! 319: classpp = &((*classpp)->sibling_class)) ! 320: (*classpp)->super_class = new_class; ! 321: ! 322: for (metaclasspp = &(new_meta_class->subclass_list); *metaclasspp; ! 323: metaclasspp = &((*metaclasspp)->sibling_class)) ! 324: (*metaclasspp)->super_class = new_meta_class; ! 325: ! 326: } ! 327: ! 328: /* Delete the class from the hash table, change its name so that it can no ! 329: longer be found, then place it back into the hash table using its new ! 330: name. ! 331: ! 332: Don't worry about the class number. It is already assigned. ! 333: memory is lost with the hash key.) */ ! 334: hash_remove (__objc_class_hash, super_class->name); ! 335: sprintf (new_name, "%s*", super_class->name); ! 336: super_class->name = new_name; ! 337: super_class->class_pointer->name = new_name; ! 338: hash_add (&__objc_class_hash, super_class->name, super_class); ! 339: ! 340: /* Place the impostor class in class hash table and assign it a class ! 341: number. */ ! 342: __objc_add_class_to_hash (new_class); ! 343: ! 344: /* Now update dispatch tables for new_class and it's subclasses */ ! 345: __objc_update_dispatch_table_for_class ((Class*) new_meta_class); ! 346: __objc_update_dispatch_table_for_class (new_class); ! 347: ! 348: return new_class; ! 349: } ! 350:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.