OSDN Git Service

2005-06-07 David Ayers <d.ayers@inode.at>
[pf3gnuchains/gcc-fork.git] / libobjc / init.c
1 /* GNU Objective C Runtime initialization 
2    Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
3    Contributed by Kresten Krab Thorup
4    +load support contributed by Ovidiu Predescu <ovidiu@net-community.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2, or (at your option) any later version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15 details.
16
17 You should have received a copy of the GNU General Public License along with
18 GCC; see the file COPYING.  If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 /* As a special exception, if you link this library with files compiled with
22    GCC to produce an executable, this does not cause the resulting executable
23    to be covered by the GNU General Public License. This exception does not
24    however invalidate any other reasons why the executable file might be
25    covered by the GNU General Public License.  */
26
27 #include "objc/runtime.h"
28
29 /* The version number of this runtime.  This must match the number 
30    defined in gcc (objc-act.c).  */
31 #define OBJC_VERSION 8
32 #define PROTOCOL_VERSION 2
33
34 /* This list contains all modules currently loaded into the runtime.  */
35 static struct objc_list *__objc_module_list = 0;        /* !T:MUTEX */
36
37 /* This list contains all proto_list's not yet assigned class links.  */
38 static struct objc_list *unclaimed_proto_list = 0;      /* !T:MUTEX */
39
40 /* List of unresolved static instances.  */
41 static struct objc_list *uninitialized_statics = 0;     /* !T:MUTEX */
42
43 /* Global runtime "write" mutex.  */
44 objc_mutex_t __objc_runtime_mutex = 0;
45
46 /* Number of threads that are alive.  */
47 int __objc_runtime_threads_alive = 1;                   /* !T:MUTEX */
48
49 /* Check compiler vs runtime version.  */
50 static void init_check_module_version (Module_t);
51
52 /* Assign isa links to protos.  */
53 static void __objc_init_protocols (struct objc_protocol_list *protos);
54
55 /* Add protocol to class.  */
56 static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
57
58 /* This is a hook which is called by __objc_exec_class every time a
59    class or a category is loaded into the runtime.  This may e.g. help
60    a dynamic loader determine the classes that have been loaded when
61    an object file is dynamically linked in.  */
62 void (*_objc_load_callback) (Class class, Category *category); /* !T:SAFE */
63
64 /* Is all categories/classes resolved?  */
65 BOOL __objc_dangling_categories = NO;           /* !T:UNUSED */
66
67 extern SEL
68 __sel_register_typed_name (const char *name, const char *types, 
69                            struct objc_selector *orig, BOOL is_const);
70
71 /* Sends +load to all classes and categories in certain situations.  */
72 static void objc_send_load (void);
73
74 /* Inserts all the classes defined in module in a tree of classes that
75    resembles the class hierarchy. This tree is traversed in preorder
76    and the classes in its nodes receive the +load message if these
77    methods were not executed before. The algorithm ensures that when
78    the +load method of a class is executed all the superclasses have
79    been already received the +load message.  */
80 static void __objc_create_classes_tree (Module_t module);
81
82 static void __objc_call_callback (Module_t module);
83
84 /* A special version that works only before the classes are completely
85    installed in the runtime.  */
86 static BOOL class_is_subclass_of_class (Class class, Class superclass);
87
88 typedef struct objc_class_tree {
89   Class class;
90   struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */
91 } objc_class_tree;
92
93 /* This is a linked list of objc_class_tree trees. The head of these
94    trees are root classes (their super class is Nil). These different
95    trees represent different class hierarchies.  */
96 static struct objc_list *__objc_class_tree_list = NULL;
97
98 /* Keeps the +load methods who have been already executed. This hash
99    should not be destroyed during the execution of the program.  */
100 static cache_ptr __objc_load_methods = NULL;
101
102 /* This function is used when building the class tree used to send
103    ordinately the +load message to all classes needing it.  The tree
104    is really needed so that superclasses will get the message before
105    subclasses.
106
107    This tree will contain classes which are being loaded (or have just
108    being loaded), and whose super_class pointers have not yet been
109    resolved.  This implies that their super_class pointers point to a
110    string with the name of the superclass; when the first message is
111    sent to the class (/an object of that class) the class links will
112    be resolved, which will replace the super_class pointers with
113    pointers to the actual superclasses.
114
115    Unfortunately, the tree might also contain classes which had been
116    loaded previously, and whose class links have already been
117    resolved.
118
119    This function returns the superclass of a class in both cases, and
120    can be used to build the determine the class relationships while
121    building the tree.
122 */
123 static Class  class_superclass_of_class (Class class)
124 {
125   char *super_class_name;
126
127   /* If the class links have been resolved, use the resolved
128    * links.  */
129   if (CLS_ISRESOLV (class))
130     return class->super_class;
131   
132   /* Else, 'class' has not yet been resolved.  This means that its
133    * super_class pointer is really the name of the super class (rather
134    * than a pointer to the actual superclass).  */
135   super_class_name = (char *)class->super_class;
136
137   /* Return Nil for a root class.  */
138   if (super_class_name == NULL)
139     return Nil;
140
141   /* Lookup the superclass of non-root classes.  */
142   return objc_lookup_class (super_class_name);
143 }
144
145
146 /* Creates a tree of classes whose topmost class is directly inherited
147    from `upper' and the bottom class in this tree is
148    `bottom_class'. The classes in this tree are super classes of
149    `bottom_class'. `subclasses' member of each tree node point to the
150    next subclass tree node.  */
151
152 static objc_class_tree *
153 create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
154 {
155   Class superclass = bottom_class->super_class ?
156                         objc_lookup_class ((char *) bottom_class->super_class)
157                       : Nil;
158                                         
159   objc_class_tree *tree, *prev;
160
161   DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
162   DEBUG_PRINTF ("bottom_class = %s, upper = %s\n",
163                 (bottom_class ? bottom_class->name : NULL),
164                 (upper ? upper->name : NULL));
165
166   tree = prev = objc_calloc (1, sizeof (objc_class_tree));
167   prev->class = bottom_class;
168
169   while (superclass != upper)
170     {
171       tree = objc_calloc (1, sizeof (objc_class_tree));
172       tree->class = superclass;
173       tree->subclasses = list_cons (prev, tree->subclasses);
174       superclass = class_superclass_of_class (superclass);
175       prev = tree;
176     }
177
178   return tree;
179 }
180
181 /* Insert the `class' into the proper place in the `tree' class
182    hierarchy. This function returns a new tree if the class has been
183    successfully inserted into the tree or NULL if the class is not
184    part of the classes hierarchy described by `tree'. This function is
185    private to objc_tree_insert_class (), you should not call it
186    directly.  */
187
188 static objc_class_tree *
189 __objc_tree_insert_class (objc_class_tree *tree, Class class)
190 {
191   DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
192                 tree, class->name);
193
194   if (tree == NULL)
195     return create_tree_of_subclasses_inherited_from (class, NULL);
196   else if (class == tree->class)
197     {
198       /* `class' has been already inserted */
199       DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
200       return tree;
201     }
202   else if (class_superclass_of_class (class) == tree->class)
203     {
204       /* If class is a direct subclass of tree->class then add class to the
205          list of subclasses. First check to see if it wasn't already
206          inserted.  */
207       struct objc_list *list = tree->subclasses;
208       objc_class_tree *node;
209
210       while (list)
211         {
212           /* Class has been already inserted; do nothing just return
213              the tree.  */
214           if (((objc_class_tree *) list->head)->class == class)
215             {
216               DEBUG_PRINTF ("2. class %s was previously inserted\n",
217                             class->name);
218               return tree;
219             }
220           list = list->tail;
221         }
222
223       /* Create a new node class and insert it into the list of subclasses */
224       node = objc_calloc (1, sizeof (objc_class_tree));
225       node->class = class;
226       tree->subclasses = list_cons (node, tree->subclasses);
227       DEBUG_PRINTF ("3. class %s inserted\n", class->name);
228       return tree;
229     }
230   else
231     {
232       /* The class is not a direct subclass of tree->class. Search for
233          class's superclasses in the list of subclasses.  */
234       struct objc_list *subclasses = tree->subclasses;
235
236       /* Precondition: the class must be a subclass of tree->class;
237          otherwise return NULL to indicate our caller that it must
238          take the next tree.  */
239       if (! class_is_subclass_of_class (class, tree->class))
240         return NULL;
241
242       for (; subclasses != NULL; subclasses = subclasses->tail)
243         {
244           Class aClass = ((objc_class_tree *) (subclasses->head))->class;
245
246           if (class_is_subclass_of_class (class, aClass))
247             {
248               /* If we found one of class's superclasses we insert the
249                  class into its subtree and return the original tree
250                  since nothing has been changed.  */
251               subclasses->head
252                   = __objc_tree_insert_class (subclasses->head, class);
253               DEBUG_PRINTF ("4. class %s inserted\n", class->name);
254               return tree;
255             }
256         }
257
258       /* We haven't found a subclass of `class' in the `subclasses'
259          list.  Create a new tree of classes whose topmost class is a
260          direct subclass of tree->class.  */
261       {
262         objc_class_tree *new_tree
263           = create_tree_of_subclasses_inherited_from (class, tree->class);
264         tree->subclasses = list_cons (new_tree, tree->subclasses);
265         DEBUG_PRINTF ("5. class %s inserted\n", class->name);
266         return tree;
267       }
268     }
269 }
270
271 /* This function inserts `class' in the right tree hierarchy classes.  */
272
273 static void
274 objc_tree_insert_class (Class class)
275 {
276   struct objc_list *list_node;
277   objc_class_tree *tree;
278
279   list_node = __objc_class_tree_list;
280   while (list_node)
281     {
282       tree = __objc_tree_insert_class (list_node->head, class);
283       if (tree)
284         {
285           list_node->head = tree;
286           break;
287         }
288       else
289         list_node = list_node->tail;
290     }
291
292   /* If the list was finished but the class hasn't been inserted,
293      insert it here.  */
294   if (! list_node)
295     {
296       __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
297       __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
298     }
299 }
300
301 /* Traverse tree in preorder. Used to send +load.  */
302
303 static void
304 objc_preorder_traverse (objc_class_tree *tree,
305                         int level,
306                         void (*function) (objc_class_tree *, int))
307 {
308   struct objc_list *node;
309
310   (*function) (tree, level);
311   for (node = tree->subclasses; node; node = node->tail)
312     objc_preorder_traverse (node->head, level + 1, function);
313 }
314
315 /* Traverse tree in postorder. Used to destroy a tree.  */
316
317 static void
318 objc_postorder_traverse (objc_class_tree *tree,
319                          int level,
320                          void (*function) (objc_class_tree *, int))
321 {
322   struct objc_list *node;
323
324   for (node = tree->subclasses; node; node = node->tail)
325     objc_postorder_traverse (node->head, level + 1, function);
326   (*function) (tree, level);
327 }
328
329 /* Used to print a tree class hierarchy.  */
330
331 #ifdef DEBUG
332 static void
333 __objc_tree_print (objc_class_tree *tree, int level)
334 {
335   int i;
336
337   for (i = 0; i < level; i++)
338     printf ("  ");
339   printf ("%s\n", tree->class->name);
340 }
341 #endif
342
343 /* Walks on a linked list of methods in the reverse order and executes
344    all the methods corresponding to `op' selector. Walking in the
345    reverse order assures the +load of class is executed first and then
346    +load of categories because of the way in which categories are
347    added to the class methods.  */
348
349 static void
350 __objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
351 {
352   int i;
353
354   if (! method_list)
355     return;
356
357   /* First execute the `op' message in the following method lists */
358   __objc_send_message_in_list (method_list->method_next, class, op);
359
360   /* Search the method list.  */
361   for (i = 0; i < method_list->method_count; i++)
362     {
363       Method_t mth = &method_list->method_list[i];
364
365       if (mth->method_name && sel_eq (mth->method_name, op)
366           && ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
367         {
368           /* Add this method into the +load hash table */
369           objc_hash_add (&__objc_load_methods,
370                          mth->method_imp,
371                          mth->method_imp);
372
373           DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
374
375           /* The method was found and wasn't previously executed.  */
376           (*mth->method_imp) ((id)class, mth->method_name);
377
378           break;
379         }
380     }
381 }
382
383 static void
384 __objc_send_load (objc_class_tree *tree,
385                   int level __attribute__ ((__unused__)))
386 {
387   static SEL load_sel = 0;
388   Class class = tree->class;
389   MethodList_t method_list = class->class_pointer->methods;
390
391   if (! load_sel)
392     load_sel = sel_register_name ("load");
393
394   __objc_send_message_in_list (method_list, class, load_sel);
395 }
396
397 static void
398 __objc_destroy_class_tree_node (objc_class_tree *tree,
399                                 int level __attribute__ ((__unused__)))
400 {
401   objc_free (tree);
402 }
403
404 /* This is used to check if the relationship between two classes
405    before the runtime completely installs the classes.  */
406
407 static BOOL
408 class_is_subclass_of_class (Class class, Class superclass)
409 {
410   for (; class != Nil;)
411     {
412       if (class == superclass)
413         return YES;
414       class = class_superclass_of_class (class);
415     }
416
417   return NO;
418 }
419
420 /* This list contains all the classes in the runtime system for whom
421    their superclasses are not yet known to the runtime.  */
422 static struct objc_list *unresolved_classes = 0;
423
424 /* Extern function used to reference the Object and NXConstantString
425    classes.  */
426
427 extern void __objc_force_linking (void);
428
429 void
430 __objc_force_linking (void)
431 {
432   extern void __objc_linking (void);
433   __objc_linking ();
434 }
435
436 /* Run through the statics list, removing modules as soon as all its
437    statics have been initialized.  */
438
439 static void
440 objc_init_statics (void)
441 {
442   struct objc_list **cell = &uninitialized_statics;
443   struct objc_static_instances **statics_in_module;
444
445   objc_mutex_lock (__objc_runtime_mutex);
446
447   while (*cell)
448     {
449       int module_initialized = 1;
450
451       for (statics_in_module = (*cell)->head;
452            *statics_in_module; statics_in_module++)
453         {
454           struct objc_static_instances *statics = *statics_in_module;
455           Class class = objc_lookup_class (statics->class_name);
456
457           if (! class)
458             module_initialized = 0;
459           /* Actually, the static's class_pointer will be NULL when we
460              haven't been here before.  However, the comparison is to be
461              reminded of taking into account class posing and to think about
462              possible semantics...  */
463           else if (class != statics->instances[0]->class_pointer)
464             {
465               id *inst;
466
467               for (inst = &statics->instances[0]; *inst; inst++)
468                 {
469                   (*inst)->class_pointer = class;
470
471                   /* ??? Make sure the object will not be freed.  With
472                      refcounting, invoke `-retain'.  Without refcounting, do
473                      nothing and hope that `-free' will never be invoked.  */
474
475                   /* ??? Send the object an `-initStatic' or something to
476                      that effect now or later on?  What are the semantics of
477                      statically allocated instances, besides the trivial
478                      NXConstantString, anyway?  */
479                 }
480             }
481         }
482       if (module_initialized)
483         {
484           /* Remove this module from the uninitialized list.  */
485           struct objc_list *this = *cell;
486           *cell = this->tail;
487           objc_free (this);
488         }
489       else
490         cell = &(*cell)->tail;
491     }
492
493   objc_mutex_unlock (__objc_runtime_mutex);
494 } /* objc_init_statics */
495
496 /* This function is called by constructor functions generated for each
497    module compiled.  (_GLOBAL_$I$...) The purpose of this function is
498    to gather the module pointers so that they may be processed by the
499    initialization routines as soon as possible.  */
500
501 void
502 __objc_exec_class (Module_t module)
503 {
504   /* Have we processed any constructors previously?  This flag is used to
505      indicate that some global data structures need to be built.  */
506   static BOOL previous_constructors = 0;
507
508   static struct objc_list *unclaimed_categories = 0;
509
510   /* The symbol table (defined in objc-api.h) generated by gcc */
511   Symtab_t symtab = module->symtab;
512
513   /* The statics in this module */
514   struct objc_static_instances **statics
515     = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
516
517   /* Entry used to traverse hash lists */
518   struct objc_list **cell;
519
520   /* The table of selector references for this module */
521   SEL selectors = symtab->refs; 
522
523   /* dummy counter */
524   int i;
525
526   DEBUG_PRINTF ("received module: %s\n", module->name);
527
528   /* check gcc version */
529   init_check_module_version (module);
530
531   /* On the first call of this routine, initialize some data structures.  */
532   if (! previous_constructors)
533     {
534         /* Initialize thread-safe system */
535       __objc_init_thread_system ();
536       __objc_runtime_threads_alive = 1;
537       __objc_runtime_mutex = objc_mutex_allocate ();
538
539       __objc_init_selector_tables ();
540       __objc_init_class_tables ();
541       __objc_init_dispatch_tables ();
542       __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
543       __objc_load_methods = objc_hash_new (128, 
544                                            (hash_func_type)objc_hash_ptr,
545                                            objc_compare_ptrs);
546       previous_constructors = 1;
547     }
548
549   /* Save the module pointer for later processing. (not currently used) */
550   objc_mutex_lock (__objc_runtime_mutex);
551   __objc_module_list = list_cons (module, __objc_module_list);
552
553   /* Replace referenced selectors from names to SEL's.  */
554   if (selectors)
555     {
556       for (i = 0; selectors[i].sel_id; ++i)
557         {
558           const char *name, *type;
559           name = (char *) selectors[i].sel_id;
560           type = (char *) selectors[i].sel_types;
561           /* Constructors are constant static data so we can safely store
562              pointers to them in the runtime structures. is_const == YES */
563           __sel_register_typed_name (name, type, 
564                                      (struct objc_selector *) &(selectors[i]),
565                                      YES);
566         }
567     }
568
569   /* Parse the classes in the load module and gather selector information.  */
570   DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
571   for (i = 0; i < symtab->cls_def_cnt; ++i)
572     {
573       Class class = (Class) symtab->defs[i];
574       const char *superclass = (char *) class->super_class;
575
576       /* Make sure we have what we think.  */
577       assert (CLS_ISCLASS (class));
578       assert (CLS_ISMETA (class->class_pointer));
579       DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
580
581       /* Initialize the subclass list to be NULL.
582          In some cases it isn't and this crashes the program.  */
583       class->subclass_list = NULL;
584
585       /* Store the class in the class table and assign class numbers.  */
586       __objc_add_class_to_hash (class);
587
588       /* Register all of the selectors in the class and meta class.  */
589       __objc_register_selectors_from_class (class);
590       __objc_register_selectors_from_class ((Class) class->class_pointer);
591
592       /* Install the fake dispatch tables */
593       __objc_install_premature_dtable (class);
594       __objc_install_premature_dtable (class->class_pointer);
595
596       /* Register the instance methods as class methods, this is
597          only done for root classes.  */
598       __objc_register_instance_methods_to_class (class);
599
600       if (class->protocols)
601         __objc_init_protocols (class->protocols);
602
603       /* Check to see if the superclass is known in this point. If it's not
604          add the class to the unresolved_classes list.  */
605       if (superclass && ! objc_lookup_class (superclass))
606         unresolved_classes = list_cons (class, unresolved_classes);
607    }
608
609   /* Process category information from the module.  */
610   for (i = 0; i < symtab->cat_def_cnt; ++i)
611     {
612       Category_t category = symtab->defs[i + symtab->cls_def_cnt];
613       Class class = objc_lookup_class (category->class_name);
614       
615       /* If the class for the category exists then append its methods.  */
616       if (class)
617         {
618
619           DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
620                         module->name,
621                         class->name);
622
623           /* Do instance methods.  */
624           if (category->instance_methods)
625             class_add_method_list (class, category->instance_methods);
626
627           /* Do class methods.  */
628           if (category->class_methods)
629             class_add_method_list ((Class) class->class_pointer, 
630                                    category->class_methods);
631
632           if (category->protocols)
633             {
634               __objc_init_protocols (category->protocols);
635               __objc_class_add_protocols (class, category->protocols);
636             }
637
638           /* Register the instance methods as class methods, this is
639              only done for root classes.  */
640           __objc_register_instance_methods_to_class (class);
641         }
642       else
643         {
644           /* The object to which the category methods belong can't be found.
645              Save the information.  */
646           unclaimed_categories = list_cons (category, unclaimed_categories);
647         }
648     }
649
650   if (statics)
651     uninitialized_statics = list_cons (statics, uninitialized_statics);
652   if (uninitialized_statics)
653     objc_init_statics ();
654
655   /* Scan the unclaimed category hash.  Attempt to attach any unclaimed
656      categories to objects.  */
657   for (cell = &unclaimed_categories; *cell; )
658     {
659       Category_t category = (*cell)->head;
660       Class class = objc_lookup_class (category->class_name);
661       
662       if (class)
663         {
664           DEBUG_PRINTF ("attaching stored categories to object: %s\n",
665                         class->name);
666           
667           list_remove_head (cell);
668           
669           if (category->instance_methods)
670             class_add_method_list (class, category->instance_methods);
671           
672           if (category->class_methods)
673             class_add_method_list ((Class) class->class_pointer,
674                                    category->class_methods);
675
676           if (category->protocols)
677             {
678               __objc_init_protocols (category->protocols);
679               __objc_class_add_protocols (class, category->protocols);
680             }
681
682           /* Register the instance methods as class methods, this is
683              only done for root classes.  */
684           __objc_register_instance_methods_to_class (class);
685         }
686       else
687         cell = &(*cell)->tail;
688     }
689   
690   if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
691     {
692       list_mapcar (unclaimed_proto_list,
693                    (void (*) (void *))__objc_init_protocols);
694       list_free (unclaimed_proto_list);
695       unclaimed_proto_list = 0;
696     }
697
698   objc_send_load ();
699
700   objc_mutex_unlock (__objc_runtime_mutex);
701 }
702
703 static void
704 objc_send_load (void)
705 {
706   if (! __objc_module_list)
707     return;
708  
709   /* Try to find out if all the classes loaded so far also have their
710      superclasses known to the runtime. We suppose that the objects
711      that are allocated in the +load method are in general of a class
712      declared in the same module.  */
713   if (unresolved_classes)
714     {
715       Class class = unresolved_classes->head;
716
717       while (objc_lookup_class ((char *) class->super_class))
718         {
719           list_remove_head (&unresolved_classes);
720           if (unresolved_classes)
721             class = unresolved_classes->head;
722           else
723             break;
724         }
725
726       /* If we still have classes for whom we don't have yet their
727          super classes known to the runtime we don't send the +load
728          messages.  */
729       if (unresolved_classes)
730         return;
731     }
732
733   /* Special check to allow creating and sending messages to constant
734      strings in +load methods. If these classes are not yet known,
735      even if all the other classes are known, delay sending of +load.  */
736   if (! objc_lookup_class ("NXConstantString") ||
737       ! objc_lookup_class ("Object"))
738     return;
739
740   /* Iterate over all modules in the __objc_module_list and call on
741      them the __objc_create_classes_tree function. This function
742      creates a tree of classes that resembles the class hierarchy.  */
743   list_mapcar (__objc_module_list,
744                (void (*) (void *)) __objc_create_classes_tree);
745
746   while (__objc_class_tree_list)
747     {
748 #ifdef DEBUG
749       objc_preorder_traverse (__objc_class_tree_list->head,
750                               0, __objc_tree_print);
751 #endif
752       objc_preorder_traverse (__objc_class_tree_list->head,
753                               0, __objc_send_load);
754       objc_postorder_traverse (__objc_class_tree_list->head,
755                               0, __objc_destroy_class_tree_node);
756       list_remove_head (&__objc_class_tree_list);
757     }
758
759   list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
760   list_free (__objc_module_list);
761   __objc_module_list = NULL;
762 }
763
764 static void
765 __objc_create_classes_tree (Module_t module)
766 {
767   /* The runtime mutex is locked in this point */
768
769   Symtab_t symtab = module->symtab;
770   int i;
771
772   /* Iterate thru classes defined in this module and insert them in
773      the classes tree hierarchy.  */
774   for (i = 0; i < symtab->cls_def_cnt; i++)
775     {
776       Class class = (Class) symtab->defs[i];
777
778       objc_tree_insert_class (class);
779     }
780 }
781
782 static void
783 __objc_call_callback (Module_t module)
784 {
785   /* The runtime mutex is locked in this point.  */
786
787   Symtab_t symtab = module->symtab;
788   int i;
789
790   /* Iterate thru classes defined in this module and call the callback
791      for each one.  */
792   for (i = 0; i < symtab->cls_def_cnt; i++)
793     {
794       Class class = (Class) symtab->defs[i];
795
796       /* Call the _objc_load_callback for this class.  */
797       if (_objc_load_callback)
798         _objc_load_callback (class, 0);
799     }
800
801   /* Call the _objc_load_callback for categories. Don't register the
802      instance methods as class methods for categories to root classes
803      since they were already added in the class.  */
804   for (i = 0; i < symtab->cat_def_cnt; i++)
805     {
806       Category_t category = symtab->defs[i + symtab->cls_def_cnt];
807       Class class = objc_lookup_class (category->class_name);
808       
809       if (_objc_load_callback)
810         _objc_load_callback (class, category);
811     }
812 }
813
814 /* Sanity check the version of gcc used to compile `module'.  */
815
816 static void
817 init_check_module_version (Module_t module)
818 {
819   if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
820     {
821       int code;
822
823       if (module->version > OBJC_VERSION)
824         code = OBJC_ERR_OBJC_VERSION;
825       else if (module->version < OBJC_VERSION)
826         code = OBJC_ERR_GCC_VERSION;
827       else
828         code = OBJC_ERR_MODULE_SIZE;
829
830       objc_error (nil, code, "Module %s version %d doesn't match runtime %d\n",
831                   module->name, (int)module->version, OBJC_VERSION);
832     }
833 }
834
835 static void
836 __objc_init_protocols (struct objc_protocol_list *protos)
837 {
838   size_t i;
839   static Class proto_class = 0;
840
841   if (! protos)
842     return;
843
844   objc_mutex_lock (__objc_runtime_mutex);
845
846   if (! proto_class)
847     proto_class = objc_lookup_class ("Protocol");
848
849   if (! proto_class)
850     {
851       unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
852       objc_mutex_unlock (__objc_runtime_mutex);
853       return;
854     }
855
856 #if 0
857   assert (protos->next == 0);   /* only single ones allowed */
858 #endif
859
860   for (i = 0; i < protos->count; i++)
861     {
862       struct objc_protocol *aProto = protos->list[i];
863       if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
864         {
865           /* assign class pointer */
866           aProto->class_pointer = proto_class;
867
868           /* init super protocols */
869           __objc_init_protocols (aProto->protocol_list);
870         }
871       else if (protos->list[i]->class_pointer != proto_class)
872         {
873           objc_error (nil, OBJC_ERR_PROTOCOL_VERSION,
874                      "Version %d doesn't match runtime protocol version %d\n",
875                      (int) ((char *) protos->list[i]->class_pointer
876                             - (char *) 0),
877                      PROTOCOL_VERSION);
878         }
879     }
880
881   objc_mutex_unlock (__objc_runtime_mutex);
882 }
883
884 static void
885 __objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
886 {
887   /* Well...  */
888   if (! protos)
889     return;
890
891   /* Add it...  */
892   protos->next = class->protocols;
893   class->protocols = protos;
894 }