OSDN Git Service

Changes to support ObjC as a front-end language.
[pf3gnuchains/gcc-fork.git] / gcc / objc / class.c
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
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
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.
10
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.
15
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.  */
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 */
30 static 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 */
35 Class (*_objc_lookup_class)(const char* name) = 0;      /* !T:SAFE */
36
37
38 /* True when class links has been resolved */     
39 BOOL __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
45 void __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 */
64 void
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 */
98 Class 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 */
123 Class
124 objc_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 }
149
150 MetaClass
151 objc_get_meta_class(const char *name)
152 {
153   return objc_get_class(name)->class_pointer;
154 }
155
156 /* This function provides a way to enumerate all the classes in the
157    executable.  Pass *ENUM_STATE == NULL to start the enumeration.  The
158    function will return 0 when there are no more classes.  
159    For example: 
160        id class; 
161        void *es = NULL;
162        while ((class = objc_next_class(&es)))
163          ... do something with class; 
164 */
165 Class
166 objc_next_class(void **enum_state)
167 {
168   objc_mutex_lock(__objc_runtime_mutex);
169
170   /* make sure the table is there */
171   assert(__objc_class_hash);
172
173   *(node_ptr*)enum_state = 
174     hash_next(__objc_class_hash, *(node_ptr*)enum_state);
175
176   objc_mutex_unlock(__objc_runtime_mutex);
177
178   if (*(node_ptr*)enum_state)
179     return (*(node_ptr*)enum_state)->value;
180   return (Class)0;
181 }
182
183 /* Resolve super/subclass links for all classes.  The only thing we 
184    can be sure of is that the class_pointer for class objects point 
185    to the right meta class objects */
186 void __objc_resolve_class_links()
187 {
188   node_ptr node;
189   Class object_class = objc_get_class ("Object");
190
191   assert(object_class);
192
193   objc_mutex_lock(__objc_runtime_mutex);
194
195   /* Assign subclass links */
196   for (node = hash_next (__objc_class_hash, NULL); node;
197        node = hash_next (__objc_class_hash, node))
198     {
199       Class class1 = node->value;
200
201       /* Make sure we have what we think we have.  */
202       assert (CLS_ISCLASS(class1));
203       assert (CLS_ISMETA(class1->class_pointer));
204
205       /* The class_pointer of all meta classes point to Object's meta class. */
206       class1->class_pointer->class_pointer = object_class->class_pointer;
207
208       if (!(CLS_ISRESOLV(class1)))
209         {
210           CLS_SETRESOLV(class1);
211           CLS_SETRESOLV(class1->class_pointer);
212               
213           if(class1->super_class)
214             {   
215               Class a_super_class 
216                 = objc_get_class ((char *) class1->super_class);
217               
218               assert (a_super_class);
219               
220               DEBUG_PRINTF ("making class connections for: %s\n",
221                             class1->name);
222               
223               /* assign subclass links for superclass */
224               class1->sibling_class = a_super_class->subclass_list;
225               a_super_class->subclass_list = class1;
226               
227               /* Assign subclass links for meta class of superclass */
228               if (a_super_class->class_pointer)
229                 {
230                   class1->class_pointer->sibling_class
231                     = a_super_class->class_pointer->subclass_list;
232                   a_super_class->class_pointer->subclass_list 
233                     = class1->class_pointer;
234                 }
235             }
236           else                  /* a root class, make its meta object */
237                                 /* be a subclass of Object */
238             {
239               class1->class_pointer->sibling_class 
240                 = object_class->subclass_list;
241               object_class->subclass_list = class1->class_pointer;
242             }
243         }
244     }
245
246   /* Assign superclass links */
247   for (node = hash_next (__objc_class_hash, NULL); node;
248        node = hash_next (__objc_class_hash, node))
249     {
250       Class class1 = node->value;
251       Class sub_class;
252       for (sub_class = class1->subclass_list; sub_class;
253            sub_class = sub_class->sibling_class)
254         {
255           sub_class->super_class = class1;
256           if(CLS_ISCLASS(sub_class))
257             sub_class->class_pointer->super_class = class1->class_pointer;
258         }
259     }
260
261   objc_mutex_unlock(__objc_runtime_mutex);
262 }
263
264
265
266 #define CLASSOF(c) ((c)->class_pointer)
267
268 Class
269 class_pose_as (Class impostor, Class super_class)
270 {
271   node_ptr node;
272   Class class1;
273
274   if (!CLS_ISRESOLV (impostor))
275     __objc_resolve_class_links ();
276
277   /* preconditions */
278   assert (impostor);
279   assert (super_class);
280   assert (impostor->super_class == super_class);
281   assert (CLS_ISCLASS (impostor));
282   assert (CLS_ISCLASS (super_class));
283   assert (impostor->instance_size == super_class->instance_size);
284
285   {
286     Class *subclass = &(super_class->subclass_list);
287
288     /* move subclasses of super_class to impostor */
289     while (*subclass)
290       {
291         Class nextSub = (*subclass)->sibling_class;
292
293         if (*subclass != impostor)
294           {
295             Class sub = *subclass;
296
297             /* classes */
298             sub->sibling_class = impostor->subclass_list;
299             sub->super_class = impostor;
300             impostor->subclass_list = sub;
301
302             /* It will happen that SUB is not a class object if it is 
303                the top of the meta class hierarchy chain.  (root
304                meta-class objects inherit their class object)  If that is
305                the case... don't mess with the meta-meta class. */ 
306             if (CLS_ISCLASS (sub))
307               {
308                 /* meta classes */
309                 CLASSOF (sub)->sibling_class = 
310                   CLASSOF (impostor)->subclass_list;
311                 CLASSOF (sub)->super_class = CLASSOF (impostor);
312                 CLASSOF (impostor)->subclass_list = CLASSOF (sub);
313               }
314           }
315
316         *subclass = nextSub;
317       }
318
319     /* set subclasses of superclass to be impostor only */
320     super_class->subclass_list = impostor;
321     CLASSOF (super_class)->subclass_list = CLASSOF (impostor);
322     
323     /* set impostor to have no sibling classes */
324     impostor->sibling_class = 0;
325     CLASSOF (impostor)->sibling_class = 0;
326   }
327   
328   /* check relationship of impostor and super_class is kept. */
329   assert (impostor->super_class == super_class);
330   assert (CLASSOF (impostor)->super_class == CLASSOF (super_class));
331
332   /* This is how to update the lookup table. Regardless of
333      what the keys of the hashtable is, change all values that are
334      superclass into impostor. */
335
336   objc_mutex_lock(__objc_runtime_mutex);
337
338   for (node = hash_next (__objc_class_hash, NULL); node;
339        node = hash_next (__objc_class_hash, node))
340     {
341       class1 = (Class)node->value;
342       if (class1 == super_class)
343         {
344           node->value = impostor; /* change hash table value */
345         }
346     }      
347
348   objc_mutex_unlock(__objc_runtime_mutex);
349
350   /* next, we update the dispatch tables... */
351   __objc_update_dispatch_table_for_class (CLASSOF (impostor));
352   __objc_update_dispatch_table_for_class (impostor);
353
354   return impostor;
355 }
356   
357