1999-04-17 10:15 -0400 Zack Weinberg <zack@rabi.columbia.edu>
[official-gcc.git] / libobjc / class.c
blob44aa1b9f98eb9a85bce985d955073a56fd8636ca
1 /* GNU Objective C Runtime class related functions
2 Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
3 Contributed by Kresten Krab Thorup and Dennis Glatting.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify it under the
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.
11 GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
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.
16 You should have received a copy of the GNU General Public License along with
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. */
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. */
26 #include "runtime.h" /* the kitchen sink */
27 #include "sarray.h"
29 /* The table of classname->class. Used for objc_lookup_class and friends */
30 static cache_ptr __objc_class_hash = 0; /* !T:MUTEX */
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 */
35 Class (*_objc_lookup_class)(const char* name) = 0; /* !T:SAFE */
38 /* True when class links has been resolved */
39 BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */
42 /* Initial number of buckets size of class hash table. */
43 #define CLASS_HASH_SIZE 32
45 void __objc_init_class_tables()
47 /* Allocate the class hash table */
49 if(__objc_class_hash)
50 return;
52 objc_mutex_lock(__objc_runtime_mutex);
54 __objc_class_hash
55 = hash_new (CLASS_HASH_SIZE,
56 (hash_func_type) hash_string,
57 (compare_func_type) compare_strings);
59 objc_mutex_unlock(__objc_runtime_mutex);
62 /* This function adds a class to the class hash table, and assigns the
63 class a number, unless it's already known */
64 void
65 __objc_add_class_to_hash(Class class)
67 Class h_class;
69 objc_mutex_lock(__objc_runtime_mutex);
71 /* make sure the table is there */
72 assert(__objc_class_hash);
74 /* make sure it's not a meta class */
75 assert(CLS_ISCLASS(class));
77 /* Check to see if the class is already in the hash table. */
78 h_class = hash_value_for_key (__objc_class_hash, class->name);
79 if (!h_class)
81 /* The class isn't in the hash table. Add the class and assign a class
82 number. */
83 static unsigned int class_number = 1;
85 CLS_SETNUMBER(class, class_number);
86 CLS_SETNUMBER(class->class_pointer, class_number);
88 ++class_number;
89 hash_add (&__objc_class_hash, class->name, class);
92 objc_mutex_unlock(__objc_runtime_mutex);
95 /* Get the class object for the class named NAME. If NAME does not
96 identify a known class, the hook _objc_lookup_class is called. If
97 this fails, nil is returned */
98 Class objc_lookup_class (const char* name)
100 Class class;
102 objc_mutex_lock(__objc_runtime_mutex);
104 /* Make sure the class hash table exists. */
105 assert (__objc_class_hash);
107 class = hash_value_for_key (__objc_class_hash, name);
109 objc_mutex_unlock(__objc_runtime_mutex);
111 if (class)
112 return class;
114 if (_objc_lookup_class)
115 return (*_objc_lookup_class)(name);
116 else
117 return 0;
120 /* Get the class object for the class named NAME. If NAME does not
121 identify a known class, the hook _objc_lookup_class is called. If
122 this fails, an error message is issued and the system aborts */
123 Class
124 objc_get_class (const char *name)
126 Class class;
128 objc_mutex_lock(__objc_runtime_mutex);
130 /* Make sure the class hash table exists. */
131 assert (__objc_class_hash);
133 class = hash_value_for_key (__objc_class_hash, name);
135 objc_mutex_unlock(__objc_runtime_mutex);
137 if (class)
138 return class;
140 if (_objc_lookup_class)
141 class = (*_objc_lookup_class)(name);
143 if(class)
144 return class;
146 objc_error(nil, OBJC_ERR_BAD_CLASS,
147 "objc runtime: cannot find class %s\n", name);
148 return 0;
151 MetaClass
152 objc_get_meta_class(const char *name)
154 return objc_get_class(name)->class_pointer;
157 /* This function provides a way to enumerate all the classes in the
158 executable. Pass *ENUM_STATE == NULL to start the enumeration. The
159 function will return 0 when there are no more classes.
160 For example:
161 id class;
162 void *es = NULL;
163 while ((class = objc_next_class(&es)))
164 ... do something with class;
166 Class
167 objc_next_class(void **enum_state)
169 objc_mutex_lock(__objc_runtime_mutex);
171 /* make sure the table is there */
172 assert(__objc_class_hash);
174 *(node_ptr*)enum_state =
175 hash_next(__objc_class_hash, *(node_ptr*)enum_state);
177 objc_mutex_unlock(__objc_runtime_mutex);
179 if (*(node_ptr*)enum_state)
180 return (*(node_ptr*)enum_state)->value;
181 return (Class)0;
184 /* Resolve super/subclass links for all classes. The only thing we
185 can be sure of is that the class_pointer for class objects point
186 to the right meta class objects */
187 void __objc_resolve_class_links()
189 node_ptr node;
190 Class object_class = objc_get_class ("Object");
192 assert(object_class);
194 objc_mutex_lock(__objc_runtime_mutex);
196 /* Assign subclass links */
197 for (node = hash_next (__objc_class_hash, NULL); node;
198 node = hash_next (__objc_class_hash, node))
200 Class class1 = node->value;
202 /* Make sure we have what we think we have. */
203 assert (CLS_ISCLASS(class1));
204 assert (CLS_ISMETA(class1->class_pointer));
206 /* The class_pointer of all meta classes point to Object's meta class. */
207 class1->class_pointer->class_pointer = object_class->class_pointer;
209 if (!(CLS_ISRESOLV(class1)))
211 CLS_SETRESOLV(class1);
212 CLS_SETRESOLV(class1->class_pointer);
214 if(class1->super_class)
216 Class a_super_class
217 = objc_get_class ((char *) class1->super_class);
219 assert (a_super_class);
221 DEBUG_PRINTF ("making class connections for: %s\n",
222 class1->name);
224 /* assign subclass links for superclass */
225 class1->sibling_class = a_super_class->subclass_list;
226 a_super_class->subclass_list = class1;
228 /* Assign subclass links for meta class of superclass */
229 if (a_super_class->class_pointer)
231 class1->class_pointer->sibling_class
232 = a_super_class->class_pointer->subclass_list;
233 a_super_class->class_pointer->subclass_list
234 = class1->class_pointer;
237 else /* a root class, make its meta object */
238 /* be a subclass of Object */
240 class1->class_pointer->sibling_class
241 = object_class->subclass_list;
242 object_class->subclass_list = class1->class_pointer;
247 /* Assign superclass links */
248 for (node = hash_next (__objc_class_hash, NULL); node;
249 node = hash_next (__objc_class_hash, node))
251 Class class1 = node->value;
252 Class sub_class;
253 for (sub_class = class1->subclass_list; sub_class;
254 sub_class = sub_class->sibling_class)
256 sub_class->super_class = class1;
257 if(CLS_ISCLASS(sub_class))
258 sub_class->class_pointer->super_class = class1->class_pointer;
262 objc_mutex_unlock(__objc_runtime_mutex);
267 #define CLASSOF(c) ((c)->class_pointer)
269 Class
270 class_pose_as (Class impostor, Class super_class)
272 node_ptr node;
273 Class class1;
275 if (!CLS_ISRESOLV (impostor))
276 __objc_resolve_class_links ();
278 /* preconditions */
279 assert (impostor);
280 assert (super_class);
281 assert (impostor->super_class == super_class);
282 assert (CLS_ISCLASS (impostor));
283 assert (CLS_ISCLASS (super_class));
284 assert (impostor->instance_size == super_class->instance_size);
287 Class *subclass = &(super_class->subclass_list);
289 /* move subclasses of super_class to impostor */
290 while (*subclass)
292 Class nextSub = (*subclass)->sibling_class;
294 if (*subclass != impostor)
296 Class sub = *subclass;
298 /* classes */
299 sub->sibling_class = impostor->subclass_list;
300 sub->super_class = impostor;
301 impostor->subclass_list = sub;
303 /* It will happen that SUB is not a class object if it is
304 the top of the meta class hierarchy chain. (root
305 meta-class objects inherit their class object) If that is
306 the case... don't mess with the meta-meta class. */
307 if (CLS_ISCLASS (sub))
309 /* meta classes */
310 CLASSOF (sub)->sibling_class =
311 CLASSOF (impostor)->subclass_list;
312 CLASSOF (sub)->super_class = CLASSOF (impostor);
313 CLASSOF (impostor)->subclass_list = CLASSOF (sub);
317 *subclass = nextSub;
320 /* set subclasses of superclass to be impostor only */
321 super_class->subclass_list = impostor;
322 CLASSOF (super_class)->subclass_list = CLASSOF (impostor);
324 /* set impostor to have no sibling classes */
325 impostor->sibling_class = 0;
326 CLASSOF (impostor)->sibling_class = 0;
329 /* check relationship of impostor and super_class is kept. */
330 assert (impostor->super_class == super_class);
331 assert (CLASSOF (impostor)->super_class == CLASSOF (super_class));
333 /* This is how to update the lookup table. Regardless of
334 what the keys of the hashtable is, change all values that are
335 superclass into impostor. */
337 objc_mutex_lock(__objc_runtime_mutex);
339 for (node = hash_next (__objc_class_hash, NULL); node;
340 node = hash_next (__objc_class_hash, node))
342 class1 = (Class)node->value;
343 if (class1 == super_class)
345 node->value = impostor; /* change hash table value */
349 objc_mutex_unlock(__objc_runtime_mutex);
351 /* next, we update the dispatch tables... */
352 __objc_update_dispatch_table_for_class (CLASSOF (impostor));
353 __objc_update_dispatch_table_for_class (impostor);
355 return impostor;