|
|
1.1 root 1: /* GNU Objective C Runtime class related functions 1.1.1.4 ! root 2: Copyright (C) 1993, 1995 Free Software Foundation, Inc. ! 3: Contributed by Kresten Krab Thorup and Dennis Glatting. 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.4 ! 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.4 ! 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.4 ! 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" /* the kitchen sink */ 1.1.1.2 root 27: #include "sarray.h" 1.1 root 28: 29: /* The table of classname->class. Used for objc_lookup_class and friends */ 30: static cache_ptr __objc_class_hash = 0; 31: 32: /* This is a hook which is called by objc_get_class and 33: objc_lookup_class if the runtime is not able to find the class. 34: This may e.g. try to load in the class using dynamic loading */ 1.1.1.4 ! root 35: Class (*_objc_lookup_class)(const char* name) = 0; 1.1 root 36: 37: 38: /* True when class links has been resolved */ 39: BOOL __objc_class_links_resolved = NO; 40: 41: 42: /* Initial number of buckets size of class hash table. */ 43: #define CLASS_HASH_SIZE 32 44: 45: void __objc_init_class_tables() 46: { 47: /* Allocate the class hash table */ 48: 49: if(__objc_class_hash) 50: return; 51: 52: __objc_class_hash 53: = hash_new (CLASS_HASH_SIZE, 54: (hash_func_type) hash_string, 55: (compare_func_type) compare_strings); 56: } 57: 58: /* This function adds a class to the class hash table, and assigns the 59: class a number, unless it's already known */ 60: void 1.1.1.4 ! root 61: __objc_add_class_to_hash(Class class) 1.1 root 62: { 1.1.1.4 ! root 63: Class h_class; 1.1 root 64: 65: /* make sure the table is there */ 66: assert(__objc_class_hash); 67: 68: /* make sure it's not a meta class */ 69: assert(CLS_ISCLASS(class)); 70: 71: /* Check to see if the class is already in the hash table. */ 72: h_class = hash_value_for_key (__objc_class_hash, class->name); 73: if (!h_class) 74: { 75: /* The class isn't in the hash table. Add the class and assign a class 76: number. */ 77: static unsigned int class_number = 1; 78: 79: CLS_SETNUMBER(class, class_number); 80: CLS_SETNUMBER(class->class_pointer, class_number); 81: 82: ++class_number; 83: hash_add (&__objc_class_hash, class->name, class); 84: } 85: } 86: 87: /* Get the class object for the class named NAME. If NAME does not 88: identify a known class, the hook _objc_lookup_class is called. If 89: this fails, nil is returned */ 1.1.1.4 ! root 90: Class objc_lookup_class (const char* name) 1.1 root 91: { 1.1.1.4 ! root 92: Class class; 1.1 root 93: 94: /* Make sure the class hash table exists. */ 95: assert (__objc_class_hash); 96: 97: class = hash_value_for_key (__objc_class_hash, name); 98: 99: if (class) 100: return class; 101: 102: if (_objc_lookup_class) 103: return (*_objc_lookup_class)(name); 104: else 105: return 0; 106: } 107: 108: /* Get the class object for the class named NAME. If NAME does not 109: identify a known class, the hook _objc_lookup_class is called. If 110: this fails, an error message is issued and the system aborts */ 1.1.1.4 ! root 111: Class 1.1 root 112: objc_get_class (const char *name) 113: { 1.1.1.4 ! root 114: Class class; 1.1 root 115: 116: /* Make sure the class hash table exists. */ 117: assert (__objc_class_hash); 118: 119: class = hash_value_for_key (__objc_class_hash, name); 120: 121: if (class) 122: return class; 123: 124: if (_objc_lookup_class) 125: class = (*_objc_lookup_class)(name); 126: 127: if(class) 128: return class; 129: 130: fprintf(stderr, "objc runtime: cannot find class %s\n", name); 131: abort(); 132: } 133: 1.1.1.4 ! root 134: MetaClass 1.1.1.3 root 135: objc_get_meta_class(const char *name) 136: { 137: return objc_get_class(name)->class_pointer; 138: } 139: 140: /* This function provides a way to enumerate all the classes in the 141: executable. Pass *ENUM_STATE == NULL to start the enumeration. The 142: function will return 0 when there are no more classes. 143: For example: 144: id class; 145: void *es = NULL; 146: while ((class = objc_next_class(&es))) 147: ... do something with class; 148: */ 1.1.1.4 ! root 149: Class 1.1.1.3 root 150: objc_next_class(void **enum_state) 151: { 152: /* make sure the table is there */ 153: assert(__objc_class_hash); 154: 155: *(node_ptr*)enum_state = 156: hash_next(__objc_class_hash, *(node_ptr*)enum_state); 157: if (*(node_ptr*)enum_state) 158: return (*(node_ptr*)enum_state)->value; 1.1.1.4 ! root 159: return (Class)0; 1.1.1.3 root 160: } 1.1 root 161: 162: /* Resolve super/subclass links for all classes. The only thing we 163: can be sure of is that the class_pointer for class objects point 164: to the right meta class objects */ 165: void __objc_resolve_class_links() 166: { 167: node_ptr node; 1.1.1.4 ! root 168: Class object_class = objc_get_class ("Object"); 1.1 root 169: 170: assert(object_class); 171: 172: /* Assign subclass links */ 173: for (node = hash_next (__objc_class_hash, NULL); node; 174: node = hash_next (__objc_class_hash, node)) 175: { 1.1.1.4 ! root 176: Class class1 = node->value; 1.1 root 177: 178: /* Make sure we have what we think we have. */ 179: assert (CLS_ISCLASS(class1)); 180: assert (CLS_ISMETA(class1->class_pointer)); 181: 182: /* The class_pointer of all meta classes point to Object's meta class. */ 183: class1->class_pointer->class_pointer = object_class->class_pointer; 184: 185: if (!(CLS_ISRESOLV(class1))) 186: { 187: CLS_SETRESOLV(class1); 188: CLS_SETRESOLV(class1->class_pointer); 189: 190: if(class1->super_class) 191: { 1.1.1.4 ! root 192: Class a_super_class 1.1 root 193: = objc_get_class ((char *) class1->super_class); 194: 195: assert (a_super_class); 196: 197: DEBUG_PRINTF ("making class connections for: %s\n", 198: class1->name); 199: 200: /* assign subclass links for superclass */ 201: class1->sibling_class = a_super_class->subclass_list; 202: a_super_class->subclass_list = class1; 203: 204: /* Assign subclass links for meta class of superclass */ 205: if (a_super_class->class_pointer) 206: { 207: class1->class_pointer->sibling_class 208: = a_super_class->class_pointer->subclass_list; 209: a_super_class->class_pointer->subclass_list 210: = class1->class_pointer; 211: } 212: } 213: else /* a root class, make its meta object */ 214: /* be a subclass of Object */ 215: { 216: class1->class_pointer->sibling_class 217: = object_class->subclass_list; 218: object_class->subclass_list = class1->class_pointer; 219: } 220: } 221: } 222: 223: /* Assign superclass links */ 224: for (node = hash_next (__objc_class_hash, NULL); node; 225: node = hash_next (__objc_class_hash, node)) 226: { 1.1.1.4 ! root 227: Class class1 = node->value; ! 228: Class sub_class; 1.1 root 229: for (sub_class = class1->subclass_list; sub_class; 230: sub_class = sub_class->sibling_class) 231: { 232: sub_class->super_class = class1; 233: if(CLS_ISCLASS(sub_class)) 234: sub_class->class_pointer->super_class = class1->class_pointer; 235: } 236: } 237: } 238: 239: 1.1.1.2 root 240: 241: #define CLASSOF(c) ((c)->class_pointer) 242: 1.1.1.4 ! root 243: Class ! 244: class_pose_as (Class impostor, Class super_class) 1.1 root 245: { 1.1.1.3 root 246: node_ptr node; 1.1.1.4 ! root 247: Class class1; 1.1.1.3 root 248: 1.1.1.2 root 249: if (!CLS_ISRESOLV (impostor)) 250: __objc_resolve_class_links (); 1.1 root 251: 1.1.1.2 root 252: /* preconditions */ 253: assert (impostor); 254: assert (super_class); 255: assert (impostor->super_class == super_class); 256: assert (CLS_ISCLASS (impostor)); 257: assert (CLS_ISCLASS (super_class)); 1.1 root 258: assert (impostor->instance_size == super_class->instance_size); 259: 260: { 1.1.1.4 ! root 261: Class *subclass = &(super_class->subclass_list); 1.1 root 262: 1.1.1.2 root 263: /* move subclasses of super_class to impostor */ 264: while (*subclass) 1.1 root 265: { 1.1.1.4 ! root 266: Class nextSub = (*subclass)->sibling_class; 1.1.1.2 root 267: 1.1.1.3 root 268: if (*subclass != impostor) 1.1.1.2 root 269: { 1.1.1.4 ! root 270: Class sub = *subclass; 1.1.1.2 root 271: 272: /* classes */ 273: sub->sibling_class = impostor->subclass_list; 274: sub->super_class = impostor; 275: impostor->subclass_list = sub; 1.1.1.3 root 276: 277: /* It will happen that SUB is not a class object if it is 1.1.1.4 ! root 278: the top of the meta class hierarchy chain. (root ! 279: meta-class objects inherit their class object) If that is ! 280: the case... don't mess with the meta-meta class. */ 1.1.1.3 root 281: if (CLS_ISCLASS (sub)) 282: { 283: /* meta classes */ 284: CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list; 285: CLASSOF (sub)->super_class = CLASSOF (impostor); 286: CLASSOF (impostor)->subclass_list = CLASSOF (sub); 287: } 1.1.1.2 root 288: } 289: 290: *subclass = nextSub; 1.1 root 291: } 292: 1.1.1.2 root 293: /* set subclasses of superclass to be impostor only */ 294: super_class->subclass_list = impostor; 295: CLASSOF (super_class)->subclass_list = CLASSOF (impostor); 296: 297: /* set impostor to have no sibling classes */ 298: impostor->sibling_class = 0; 299: CLASSOF (impostor)->sibling_class = 0; 300: } 301: 1.1.1.3 root 302: /* check relationship of impostor and super_class is kept. */ 1.1.1.2 root 303: assert (impostor->super_class == super_class); 304: assert (CLASSOF (impostor)->super_class == CLASSOF (super_class)); 305: 1.1.1.3 root 306: /* This is how to update the lookup table. Regardless of 307: what the keys of the hashtable is, change all values that are 1.1.1.4 ! root 308: superclass into impostor. */ 1.1.1.2 root 309: 1.1.1.3 root 310: for (node = hash_next (__objc_class_hash, NULL); node; 311: node = hash_next (__objc_class_hash, node)) 312: { 1.1.1.4 ! root 313: class1 = (Class)node->value; 1.1.1.3 root 314: if (class1 == super_class) 315: { 316: node->value = impostor; /* change hash table value */ 317: } 318: } 1.1 root 319: 1.1.1.2 root 320: /* next, we update the dispatch tables... */ 1.1.1.3 root 321: __objc_update_dispatch_table_for_class (CLASSOF (impostor)); 322: __objc_update_dispatch_table_for_class (impostor); 1.1.1.2 root 323: 324: return impostor; 325: } 326: 1.1.1.3 root 327:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.