source: trunk/third/gcc/objc/class.c @ 8834

Revision 8834, 9.7 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8833, which included commits to RCS files with non-trunk default branches.
Line 
1/* GNU Objective C Runtime class related functions
2   Copyright (C) 1993, 1995 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;
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;
36
37
38/* True when class links has been resolved */     
39BOOL __objc_class_links_resolved = NO;
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_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 */
60void
61__objc_add_class_to_hash(Class class)
62{
63  Class h_class;
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 */
90Class objc_lookup_class (const char* name)
91{
92  Class class;
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 */
111Class
112objc_get_class (const char *name)
113{
114  Class class;
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
134MetaClass
135objc_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*/
149Class
150objc_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;
159  return (Class)0;
160}
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 */
165void __objc_resolve_class_links()
166{
167  node_ptr node;
168  Class object_class = objc_get_class ("Object");
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    {
176      Class class1 = node->value;
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            {   
192              Class a_super_class
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    {
227      Class class1 = node->value;
228      Class sub_class;
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
240
241#define CLASSOF(c) ((c)->class_pointer)
242
243Class
244class_pose_as (Class impostor, Class super_class)
245{
246  node_ptr node;
247  Class class1;
248
249  if (!CLS_ISRESOLV (impostor))
250    __objc_resolve_class_links ();
251
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));
258  assert (impostor->instance_size == super_class->instance_size);
259
260  {
261    Class *subclass = &(super_class->subclass_list);
262
263    /* move subclasses of super_class to impostor */
264    while (*subclass)
265      {
266        Class nextSub = (*subclass)->sibling_class;
267
268        if (*subclass != impostor)
269          {
270            Class sub = *subclass;
271
272            /* classes */
273            sub->sibling_class = impostor->subclass_list;
274            sub->super_class = impostor;
275            impostor->subclass_list = sub;
276
277            /* It will happen that SUB is not a class object if it is
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. */
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              }
288          }
289
290        *subclass = nextSub;
291      }
292
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 
302  /* check relationship of impostor and super_class is kept. */
303  assert (impostor->super_class == super_class);
304  assert (CLASSOF (impostor)->super_class == CLASSOF (super_class));
305
306  /* This is how to update the lookup table. Regardless of
307     what the keys of the hashtable is, change all values that are
308     superclass into impostor. */
309
310  for (node = hash_next (__objc_class_hash, NULL); node;
311       node = hash_next (__objc_class_hash, node))
312    {
313      class1 = (Class)node->value;
314      if (class1 == super_class)
315        {
316          node->value = impostor; /* change hash table value */
317        }
318    }     
319
320  /* next, we update the dispatch tables... */
321  __objc_update_dispatch_table_for_class (CLASSOF (impostor));
322  __objc_update_dispatch_table_for_class (impostor);
323
324  return impostor;
325}
326 
327
Note: See TracBrowser for help on using the repository browser.