]> gcc.gnu.org Git - gcc.git/blame - libobjc/class.c
New objc tests
[gcc.git] / libobjc / class.c
CommitLineData
88e17b57
BE
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.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify it under the
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 2, or (at your option) any later version.
10
11GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14details.
15
16You should have received a copy of the GNU General Public License along with
17GNU CC; see the file COPYING. If not, write to the Free Software
18Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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 */
27#include "sarray.h"
28
29/* The table of classname->class. Used for objc_lookup_class and friends */
30static cache_ptr __objc_class_hash = 0; /* !T:MUTEX */
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 */
35Class (*_objc_lookup_class)(const char* name) = 0; /* !T:SAFE */
36
37
38/* True when class links has been resolved */
39BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */
40
41
42/* Initial number of buckets size of class hash table. */
43#define CLASS_HASH_SIZE 32
44
45void __objc_init_class_tables()
46{
47 /* Allocate the class hash table */
48
49 if(__objc_class_hash)
50 return;
51
52 objc_mutex_lock(__objc_runtime_mutex);
53
54 __objc_class_hash
55 = hash_new (CLASS_HASH_SIZE,
56 (hash_func_type) hash_string,
57 (compare_func_type) compare_strings);
58
59 objc_mutex_unlock(__objc_runtime_mutex);
60}
61
62/* This function adds a class to the class hash table, and assigns the
63 class a number, unless it's already known */
64void
65__objc_add_class_to_hash(Class class)
66{
67 Class h_class;
68
69 objc_mutex_lock(__objc_runtime_mutex);
70
71 /* make sure the table is there */
72 assert(__objc_class_hash);
73
74 /* make sure it's not a meta class */
75 assert(CLS_ISCLASS(class));
76
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)
80 {
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;
84
85 CLS_SETNUMBER(class, class_number);
86 CLS_SETNUMBER(class->class_pointer, class_number);
87
88 ++class_number;
89 hash_add (&__objc_class_hash, class->name, class);
90 }
91
92 objc_mutex_unlock(__objc_runtime_mutex);
93}
94
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 */
98Class objc_lookup_class (const char* name)
99{
100 Class class;
101
102 objc_mutex_lock(__objc_runtime_mutex);
103
104 /* Make sure the class hash table exists. */
105 assert (__objc_class_hash);
106
107 class = hash_value_for_key (__objc_class_hash, name);
108
109 objc_mutex_unlock(__objc_runtime_mutex);
110
111 if (class)
112 return class;
113
114 if (_objc_lookup_class)
115 return (*_objc_lookup_class)(name);
116 else
117 return 0;
118}
119
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 */
123Class
124objc_get_class (const char *name)
125{
126 Class class;
127
128 objc_mutex_lock(__objc_runtime_mutex);
129
130 /* Make sure the class hash table exists. */
131 assert (__objc_class_hash);
132
133 class = hash_value_for_key (__objc_class_hash, name);
134
135 objc_mutex_unlock(__objc_runtime_mutex);
136
137 if (class)
138 return class;
139
140 if (_objc_lookup_class)
141 class = (*_objc_lookup_class)(name);
142
143 if(class)
144 return class;
145
146 objc_error(nil, OBJC_ERR_BAD_CLASS,
147 "objc runtime: cannot find class %s\n", name);
148 return 0;
149}
150
151MetaClass
152objc_get_meta_class(const char *name)
153{
154 return objc_get_class(name)->class_pointer;
155}
156
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;
165*/
166Class
167objc_next_class(void **enum_state)
168{
169 objc_mutex_lock(__objc_runtime_mutex);
170
171 /* make sure the table is there */
172 assert(__objc_class_hash);
173
174 *(node_ptr*)enum_state =
175 hash_next(__objc_class_hash, *(node_ptr*)enum_state);
176
177 objc_mutex_unlock(__objc_runtime_mutex);
178
179 if (*(node_ptr*)enum_state)
180 return (*(node_ptr*)enum_state)->value;
181 return (Class)0;
182}
183
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 */
187void __objc_resolve_class_links()
188{
189 node_ptr node;
190 Class object_class = objc_get_class ("Object");
191
192 assert(object_class);
193
194 objc_mutex_lock(__objc_runtime_mutex);
195
196 /* Assign subclass links */
197 for (node = hash_next (__objc_class_hash, NULL); node;
198 node = hash_next (__objc_class_hash, node))
199 {
200 Class class1 = node->value;
201
202 /* Make sure we have what we think we have. */
203 assert (CLS_ISCLASS(class1));
204 assert (CLS_ISMETA(class1->class_pointer));
205
206 /* The class_pointer of all meta classes point to Object's meta class. */
207 class1->class_pointer->class_pointer = object_class->class_pointer;
208
209 if (!(CLS_ISRESOLV(class1)))
210 {
211 CLS_SETRESOLV(class1);
212 CLS_SETRESOLV(class1->class_pointer);
213
214 if(class1->super_class)
215 {
216 Class a_super_class
217 = objc_get_class ((char *) class1->super_class);
218
219 assert (a_super_class);
220
221 DEBUG_PRINTF ("making class connections for: %s\n",
222 class1->name);
223
224 /* assign subclass links for superclass */
225 class1->sibling_class = a_super_class->subclass_list;
226 a_super_class->subclass_list = class1;
227
228 /* Assign subclass links for meta class of superclass */
229 if (a_super_class->class_pointer)
230 {
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;
235 }
236 }
237 else /* a root class, make its meta object */
238 /* be a subclass of Object */
239 {
240 class1->class_pointer->sibling_class
241 = object_class->subclass_list;
242 object_class->subclass_list = class1->class_pointer;
243 }
244 }
245 }
246
247 /* Assign superclass links */
248 for (node = hash_next (__objc_class_hash, NULL); node;
249 node = hash_next (__objc_class_hash, node))
250 {
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)
255 {
256 sub_class->super_class = class1;
257 if(CLS_ISCLASS(sub_class))
258 sub_class->class_pointer->super_class = class1->class_pointer;
259 }
260 }
261
262 objc_mutex_unlock(__objc_runtime_mutex);
263}
264
265
266
267#define CLASSOF(c) ((c)->class_pointer)
268
269Class
270class_pose_as (Class impostor, Class super_class)
271{
272 node_ptr node;
273 Class class1;
274
275 if (!CLS_ISRESOLV (impostor))
276 __objc_resolve_class_links ();
277
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);
285
286 {
287 Class *subclass = &(super_class->subclass_list);
288
289 /* move subclasses of super_class to impostor */
290 while (*subclass)
291 {
292 Class nextSub = (*subclass)->sibling_class;
293
294 if (*subclass != impostor)
295 {
296 Class sub = *subclass;
297
298 /* classes */
299 sub->sibling_class = impostor->subclass_list;
300 sub->super_class = impostor;
301 impostor->subclass_list = sub;
302
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))
308 {
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);
314 }
315 }
316
317 *subclass = nextSub;
318 }
319
320 /* set subclasses of superclass to be impostor only */
321 super_class->subclass_list = impostor;
322 CLASSOF (super_class)->subclass_list = CLASSOF (impostor);
323
324 /* set impostor to have no sibling classes */
325 impostor->sibling_class = 0;
326 CLASSOF (impostor)->sibling_class = 0;
327 }
328
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));
332
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. */
336
337 objc_mutex_lock(__objc_runtime_mutex);
338
339 for (node = hash_next (__objc_class_hash, NULL); node;
340 node = hash_next (__objc_class_hash, node))
341 {
342 class1 = (Class)node->value;
343 if (class1 == super_class)
344 {
345 node->value = impostor; /* change hash table value */
346 }
347 }
348
349 objc_mutex_unlock(__objc_runtime_mutex);
350
351 /* next, we update the dispatch tables... */
352 __objc_update_dispatch_table_for_class (CLASSOF (impostor));
353 __objc_update_dispatch_table_for_class (impostor);
354
355 return impostor;
356}
357
358
This page took 0.239825 seconds and 5 git commands to generate.