OSDN Git Service

2002-07-02 Rodney Brown <rbrown64@csc.com.au>
[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 GNU CC.
7
8 GNU CC 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 GNU CC 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 GNU CC; 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 "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 /* Creates a tree of classes whose topmost class is directly inherited
103    from `upper' and the bottom class in this tree is
104    `bottom_class'. The classes in this tree are super classes of
105    `bottom_class'. `subclasses' member of each tree node point to the
106    next subclass tree node.  */
107
108 static objc_class_tree *
109 create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
110 {
111   Class superclass = bottom_class->super_class ?
112                         objc_lookup_class ((char *) bottom_class->super_class)
113                       : Nil;
114                                         
115   objc_class_tree *tree, *prev;
116
117   DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
118   DEBUG_PRINTF ("bottom_class = %s, upper = %s\n",
119                 (bottom_class ? bottom_class->name : NULL),
120                 (upper ? upper->name : NULL));
121
122   tree = prev = objc_calloc (1, sizeof (objc_class_tree));
123   prev->class = bottom_class;
124
125   while (superclass != upper)
126     {
127       tree = objc_calloc (1, sizeof (objc_class_tree));
128       tree->class = superclass;
129       tree->subclasses = list_cons (prev, tree->subclasses);
130       superclass = (superclass->super_class ?
131                         objc_lookup_class ((char *) superclass->super_class)
132                       : Nil);
133       prev = tree;
134     }
135
136   return tree;
137 }
138
139 /* Insert the `class' into the proper place in the `tree' class
140    hierarchy. This function returns a new tree if the class has been
141    successfully inserted into the tree or NULL if the class is not
142    part of the classes hierarchy described by `tree'. This function is
143    private to objc_tree_insert_class (), you should not call it
144    directly.  */
145
146 static objc_class_tree *
147 __objc_tree_insert_class (objc_class_tree *tree, Class class)
148 {
149   DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
150                 tree, class->name);
151
152   if (tree == NULL)
153     return create_tree_of_subclasses_inherited_from (class, NULL);
154   else if (class == tree->class)
155     {
156       /* `class' has been already inserted */
157       DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
158       return tree;
159     }
160   else if ((class->super_class ?
161                     objc_lookup_class ((char *) class->super_class)
162                   : Nil)
163             == tree->class)
164     {
165       /* If class is a direct subclass of tree->class then add class to the
166          list of subclasses. First check to see if it wasn't already
167          inserted.  */
168       struct objc_list *list = tree->subclasses;
169       objc_class_tree *node;
170
171       while (list)
172         {
173           /* Class has been already inserted; do nothing just return
174              the tree.  */
175           if (((objc_class_tree *) list->head)->class == class)
176             {
177               DEBUG_PRINTF ("2. class %s was previously inserted\n",
178                             class->name);
179               return tree;
180             }
181           list = list->tail;
182         }
183
184       /* Create a new node class and insert it into the list of subclasses */
185       node = objc_calloc (1, sizeof (objc_class_tree));
186       node->class = class;
187       tree->subclasses = list_cons (node, tree->subclasses);
188       DEBUG_PRINTF ("3. class %s inserted\n", class->name);
189       return tree;
190     }
191   else
192     {
193       /* The class is not a direct subclass of tree->class. Search for
194          class's superclasses in the list of subclasses.  */
195       struct objc_list *subclasses = tree->subclasses;
196
197       /* Precondition: the class must be a subclass of tree->class;
198          otherwise return NULL to indicate our caller that it must
199          take the next tree.  */
200       if (! class_is_subclass_of_class (class, tree->class))
201         return NULL;
202
203       for (; subclasses != NULL; subclasses = subclasses->tail)
204         {
205           Class aClass = ((objc_class_tree *) (subclasses->head))->class;
206
207           if (class_is_subclass_of_class (class, aClass))
208             {
209               /* If we found one of class's superclasses we insert the
210                  class into its subtree and return the original tree
211                  since nothing has been changed.  */
212               subclasses->head
213                   = __objc_tree_insert_class (subclasses->head, class);
214               DEBUG_PRINTF ("4. class %s inserted\n", class->name);
215               return tree;
216             }
217         }
218
219       /* We haven't found a subclass of `class' in the `subclasses'
220          list.  Create a new tree of classes whose topmost class is a
221          direct subclass of tree->class.  */
222       {
223         objc_class_tree *new_tree
224           = create_tree_of_subclasses_inherited_from (class, tree->class);
225         tree->subclasses = list_cons (new_tree, tree->subclasses);
226         DEBUG_PRINTF ("5. class %s inserted\n", class->name);
227         return tree;
228       }
229     }
230 }
231
232 /* This function inserts `class' in the right tree hierarchy classes.  */
233
234 static void
235 objc_tree_insert_class (Class class)
236 {
237   struct objc_list *list_node;
238   objc_class_tree *tree;
239
240   list_node = __objc_class_tree_list;
241   while (list_node)
242     {
243       tree = __objc_tree_insert_class (list_node->head, class);
244       if (tree)
245         {
246           list_node->head = tree;
247           break;
248         }
249       else
250         list_node = list_node->tail;
251     }
252
253   /* If the list was finished but the class hasn't been inserted,
254      insert it here.  */
255   if (! list_node)
256     {
257       __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
258       __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
259     }
260 }
261
262 /* Traverse tree in preorder. Used to send +load.  */
263
264 static void
265 objc_preorder_traverse (objc_class_tree *tree,
266                         int level,
267                         void (*function) (objc_class_tree *, int))
268 {
269   struct objc_list *node;
270
271   (*function) (tree, level);
272   for (node = tree->subclasses; node; node = node->tail)
273     objc_preorder_traverse (node->head, level + 1, function);
274 }
275
276 /* Traverse tree in postorder. Used to destroy a tree.  */
277
278 static void
279 objc_postorder_traverse (objc_class_tree *tree,
280                          int level,
281                          void (*function) (objc_class_tree *, int))
282 {
283   struct objc_list *node;
284
285   for (node = tree->subclasses; node; node = node->tail)
286     objc_postorder_traverse (node->head, level + 1, function);
287   (*function) (tree, level);
288 }
289
290 /* Used to print a tree class hierarchy.  */
291
292 #ifdef DEBUG
293 static void
294 __objc_tree_print (objc_class_tree *tree, int level)
295 {
296   int i;
297
298   for (i = 0; i < level; i++)
299     printf ("  ");
300   printf ("%s\n", tree->class->name);
301 }
302 #endif
303
304 /* Walks on a linked list of methods in the reverse order and executes
305    all the methods corresponding to `op' selector. Walking in the
306    reverse order assures the +load of class is executed first and then
307    +load of categories because of the way in which categories are
308    added to the class methods.  */
309
310 static void
311 __objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
312 {
313   int i;
314
315   if (! method_list)
316     return;
317
318   /* First execute the `op' message in the following method lists */
319   __objc_send_message_in_list (method_list->method_next, class, op);
320
321   /* Search the method list.  */
322   for (i = 0; i < method_list->method_count; i++)
323     {
324       Method_t mth = &method_list->method_list[i];
325
326       if (mth->method_name && sel_eq (mth->method_name, op)
327           && ! hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
328         {
329           /* Add this method into the +load hash table */
330           hash_add (&__objc_load_methods, mth->method_imp, mth->method_imp);
331
332           DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
333
334           /* The method was found and wasn't previously executed.  */
335           (*mth->method_imp) ((id)class, mth->method_name);
336
337           break;
338         }
339     }
340 }
341
342 static void
343 __objc_send_load (objc_class_tree *tree,
344                   int level __attribute__ ((__unused__)))
345 {
346   static SEL load_sel = 0;
347   Class class = tree->class;
348   MethodList_t method_list = class->class_pointer->methods;
349
350   if (! load_sel)
351     load_sel = sel_register_name ("load");
352
353   __objc_send_message_in_list (method_list, class, load_sel);
354 }
355
356 static void
357 __objc_destroy_class_tree_node (objc_class_tree *tree,
358                                 int level __attribute__ ((__unused__)))
359 {
360   objc_free (tree);
361 }
362
363 /* This is used to check if the relationship between two classes
364    before the runtime completely installs the classes.  */
365
366 static BOOL
367 class_is_subclass_of_class (Class class, Class superclass)
368 {
369   for (; class != Nil;)
370     {
371       if (class == superclass)
372         return YES;
373       class = (class->super_class ?
374                   objc_lookup_class ((char *) class->super_class)
375                 : Nil);
376     }
377
378   return NO;
379 }
380
381 /* This list contains all the classes in the runtime system for whom
382    their superclasses are not yet known to the runtime.  */
383 static struct objc_list *unresolved_classes = 0;
384
385 /* Extern function used to reference the Object and NXConstantString
386    classes.  */
387
388 extern void __objc_force_linking (void);
389
390 void
391 __objc_force_linking (void)
392 {
393   extern void __objc_linking (void);
394   __objc_linking ();
395 }
396
397 /* Run through the statics list, removing modules as soon as all its
398    statics have been initialized.  */
399
400 static void
401 objc_init_statics (void)
402 {
403   struct objc_list **cell = &uninitialized_statics;
404   struct objc_static_instances **statics_in_module;
405
406   objc_mutex_lock (__objc_runtime_mutex);
407
408   while (*cell)
409     {
410       int module_initialized = 1;
411
412       for (statics_in_module = (*cell)->head;
413            *statics_in_module; statics_in_module++)
414         {
415           struct objc_static_instances *statics = *statics_in_module;
416           Class class = objc_lookup_class (statics->class_name);
417
418           if (! class)
419             module_initialized = 0;
420           /* Actually, the static's class_pointer will be NULL when we
421              haven't been here before.  However, the comparison is to be
422              reminded of taking into account class posing and to think about
423              possible semantics...  */
424           else if (class != statics->instances[0]->class_pointer)
425             {
426               id *inst;
427
428               for (inst = &statics->instances[0]; *inst; inst++)
429                 {
430                   (*inst)->class_pointer = class;
431
432                   /* ??? Make sure the object will not be freed.  With
433                      refcounting, invoke `-retain'.  Without refcounting, do
434                      nothing and hope that `-free' will never be invoked.  */
435
436                   /* ??? Send the object an `-initStatic' or something to
437                      that effect now or later on?  What are the semantics of
438                      statically allocated instances, besides the trivial
439                      NXConstantString, anyway?  */
440                 }
441             }
442         }
443       if (module_initialized)
444         {
445           /* Remove this module from the uninitialized list.  */
446           struct objc_list *this = *cell;
447           *cell = this->tail;
448           objc_free (this);
449         }
450       else
451         cell = &(*cell)->tail;
452     }
453
454   objc_mutex_unlock (__objc_runtime_mutex);
455 } /* objc_init_statics */
456
457 /* This function is called by constructor functions generated for each
458    module compiled.  (_GLOBAL_$I$...) The purpose of this function is
459    to gather the module pointers so that they may be processed by the
460    initialization routines as soon as possible.  */
461
462 void
463 __objc_exec_class (Module_t module)
464 {
465   /* Have we processed any constructors previously?  This flag is used to
466      indicate that some global data structures need to be built.  */
467   static BOOL previous_constructors = 0;
468
469   static struct objc_list *unclaimed_categories = 0;
470
471   /* The symbol table (defined in objc-api.h) generated by gcc */
472   Symtab_t symtab = module->symtab;
473
474   /* The statics in this module */
475   struct objc_static_instances **statics
476     = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
477
478   /* Entry used to traverse hash lists */
479   struct objc_list **cell;
480
481   /* The table of selector references for this module */
482   SEL selectors = symtab->refs; 
483
484   /* dummy counter */
485   int i;
486
487   DEBUG_PRINTF ("received module: %s\n", module->name);
488
489   /* check gcc version */
490   init_check_module_version (module);
491
492   /* On the first call of this routine, initialize some data structures.  */
493   if (! previous_constructors)
494     {
495         /* Initialize thread-safe system */
496       __objc_init_thread_system ();
497       __objc_runtime_threads_alive = 1;
498       __objc_runtime_mutex = objc_mutex_allocate ();
499
500       __objc_init_selector_tables ();
501       __objc_init_class_tables ();
502       __objc_init_dispatch_tables ();
503       __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
504       __objc_load_methods
505           = hash_new (128, (hash_func_type)hash_ptr, compare_ptrs);
506       previous_constructors = 1;
507     }
508
509   /* Save the module pointer for later processing. (not currently used) */
510   objc_mutex_lock (__objc_runtime_mutex);
511   __objc_module_list = list_cons (module, __objc_module_list);
512
513   /* Replace referenced selectors from names to SEL's.  */
514   if (selectors)
515     {
516       for (i = 0; selectors[i].sel_id; ++i)
517         {
518           const char *name, *type;
519           name = (char *) selectors[i].sel_id;
520           type = (char *) selectors[i].sel_types;
521           /* Constructors are constant static data so we can safely store
522              pointers to them in the runtime structures. is_const == YES */
523           __sel_register_typed_name (name, type, 
524                                      (struct objc_selector *) &(selectors[i]),
525                                      YES);
526         }
527     }
528
529   /* Parse the classes in the load module and gather selector information.  */
530   DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
531   for (i = 0; i < symtab->cls_def_cnt; ++i)
532     {
533       Class class = (Class) symtab->defs[i];
534       const char *superclass = (char *) class->super_class;
535
536       /* Make sure we have what we think.  */
537       assert (CLS_ISCLASS (class));
538       assert (CLS_ISMETA (class->class_pointer));
539       DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
540
541       /* Initialize the subclass list to be NULL.
542          In some cases it isn't and this crashes the program.  */
543       class->subclass_list = NULL;
544
545       /* Store the class in the class table and assign class numbers.  */
546       __objc_add_class_to_hash (class);
547
548       /* Register all of the selectors in the class and meta class.  */
549       __objc_register_selectors_from_class (class);
550       __objc_register_selectors_from_class ((Class) class->class_pointer);
551
552       /* Install the fake dispatch tables */
553       __objc_install_premature_dtable (class);
554       __objc_install_premature_dtable (class->class_pointer);
555
556       /* Register the instance methods as class methods, this is
557          only done for root classes.  */
558       __objc_register_instance_methods_to_class (class);
559
560       if (class->protocols)
561         __objc_init_protocols (class->protocols);
562
563       /* Check to see if the superclass is known in this point. If it's not
564          add the class to the unresolved_classes list.  */
565       if (superclass && ! objc_lookup_class (superclass))
566         unresolved_classes = list_cons (class, unresolved_classes);
567    }
568
569   /* Process category information from the module.  */
570   for (i = 0; i < symtab->cat_def_cnt; ++i)
571     {
572       Category_t category = symtab->defs[i + symtab->cls_def_cnt];
573       Class class = objc_lookup_class (category->class_name);
574       
575       /* If the class for the category exists then append its methods.  */
576       if (class)
577         {
578
579           DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
580                         module->name,
581                         class->name);
582
583           /* Do instance methods.  */
584           if (category->instance_methods)
585             class_add_method_list (class, category->instance_methods);
586
587           /* Do class methods.  */
588           if (category->class_methods)
589             class_add_method_list ((Class) class->class_pointer, 
590                                    category->class_methods);
591
592           if (category->protocols)
593             {
594               __objc_init_protocols (category->protocols);
595               __objc_class_add_protocols (class, category->protocols);
596             }
597
598           /* Register the instance methods as class methods, this is
599              only done for root classes.  */
600           __objc_register_instance_methods_to_class (class);
601         }
602       else
603         {
604           /* The object to which the category methods belong can't be found.
605              Save the information.  */
606           unclaimed_categories = list_cons (category, unclaimed_categories);
607         }
608     }
609
610   if (statics)
611     uninitialized_statics = list_cons (statics, uninitialized_statics);
612   if (uninitialized_statics)
613     objc_init_statics ();
614
615   /* Scan the unclaimed category hash.  Attempt to attach any unclaimed
616      categories to objects.  */
617   for (cell = &unclaimed_categories; *cell; )
618     {
619       Category_t category = (*cell)->head;
620       Class class = objc_lookup_class (category->class_name);
621       
622       if (class)
623         {
624           DEBUG_PRINTF ("attaching stored categories to object: %s\n",
625                         class->name);
626           
627           list_remove_head (cell);
628           
629           if (category->instance_methods)
630             class_add_method_list (class, category->instance_methods);
631           
632           if (category->class_methods)
633             class_add_method_list ((Class) class->class_pointer,
634                                    category->class_methods);
635
636           if (category->protocols)
637             {
638               __objc_init_protocols (category->protocols);
639               __objc_class_add_protocols (class, category->protocols);
640             }
641
642           /* Register the instance methods as class methods, this is
643              only done for root classes.  */
644           __objc_register_instance_methods_to_class (class);
645         }
646       else
647         cell = &(*cell)->tail;
648     }
649   
650   if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
651     {
652       list_mapcar (unclaimed_proto_list,
653                    (void (*) (void *))__objc_init_protocols);
654       list_free (unclaimed_proto_list);
655       unclaimed_proto_list = 0;
656     }
657
658   objc_send_load ();
659
660   objc_mutex_unlock (__objc_runtime_mutex);
661 }
662
663 static void
664 objc_send_load (void)
665 {
666   if (! __objc_module_list)
667     return;
668  
669   /* Try to find out if all the classes loaded so far also have their
670      superclasses known to the runtime. We suppose that the objects
671      that are allocated in the +load method are in general of a class
672      declared in the same module.  */
673   if (unresolved_classes)
674     {
675       Class class = unresolved_classes->head;
676
677       while (objc_lookup_class ((char *) class->super_class))
678         {
679           list_remove_head (&unresolved_classes);
680           if (unresolved_classes)
681             class = unresolved_classes->head;
682           else
683             break;
684         }
685
686       /* If we still have classes for whom we don't have yet their
687          super classes known to the runtime we don't send the +load
688          messages.  */
689       if (unresolved_classes)
690         return;
691     }
692
693   /* Special check to allow creating and sending messages to constant
694      strings in +load methods. If these classes are not yet known,
695      even if all the other classes are known, delay sending of +load.  */
696   if (! objc_lookup_class ("NXConstantString") ||
697       ! objc_lookup_class ("Object"))
698     return;
699
700   /* Iterate over all modules in the __objc_module_list and call on
701      them the __objc_create_classes_tree function. This function
702      creates a tree of classes that resembles the class hierarchy.  */
703   list_mapcar (__objc_module_list,
704                (void (*) (void *)) __objc_create_classes_tree);
705
706   while (__objc_class_tree_list)
707     {
708 #ifdef DEBUG
709       objc_preorder_traverse (__objc_class_tree_list->head,
710                               0, __objc_tree_print);
711 #endif
712       objc_preorder_traverse (__objc_class_tree_list->head,
713                               0, __objc_send_load);
714       objc_postorder_traverse (__objc_class_tree_list->head,
715                               0, __objc_destroy_class_tree_node);
716       list_remove_head (&__objc_class_tree_list);
717     }
718
719   list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
720   list_free (__objc_module_list);
721   __objc_module_list = NULL;
722 }
723
724 static void
725 __objc_create_classes_tree (Module_t module)
726 {
727   /* The runtime mutex is locked in this point */
728
729   Symtab_t symtab = module->symtab;
730   int i;
731
732   /* Iterate thru classes defined in this module and insert them in
733      the classes tree hierarchy.  */
734   for (i = 0; i < symtab->cls_def_cnt; i++)
735     {
736       Class class = (Class) symtab->defs[i];
737
738       objc_tree_insert_class (class);
739     }
740 }
741
742 static void
743 __objc_call_callback (Module_t module)
744 {
745   /* The runtime mutex is locked in this point.  */
746
747   Symtab_t symtab = module->symtab;
748   int i;
749
750   /* Iterate thru classes defined in this module and call the callback
751      for each one.  */
752   for (i = 0; i < symtab->cls_def_cnt; i++)
753     {
754       Class class = (Class) symtab->defs[i];
755
756       /* Call the _objc_load_callback for this class.  */
757       if (_objc_load_callback)
758         _objc_load_callback (class, 0);
759     }
760
761   /* Call the _objc_load_callback for categories. Don't register the
762      instance methods as class methods for categories to root classes
763      since they were already added in the class.  */
764   for (i = 0; i < symtab->cat_def_cnt; i++)
765     {
766       Category_t category = symtab->defs[i + symtab->cls_def_cnt];
767       Class class = objc_lookup_class (category->class_name);
768       
769       if (_objc_load_callback)
770         _objc_load_callback (class, category);
771     }
772 }
773
774 /* Sanity check the version of gcc used to compile `module'.  */
775
776 static void
777 init_check_module_version (Module_t module)
778 {
779   if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
780     {
781       int code;
782
783       if (module->version > OBJC_VERSION)
784         code = OBJC_ERR_OBJC_VERSION;
785       else if (module->version < OBJC_VERSION)
786         code = OBJC_ERR_GCC_VERSION;
787       else
788         code = OBJC_ERR_MODULE_SIZE;
789
790       objc_error (nil, code, "Module %s version %d doesn't match runtime %d\n",
791                   module->name, (int)module->version, OBJC_VERSION);
792     }
793 }
794
795 static void
796 __objc_init_protocols (struct objc_protocol_list *protos)
797 {
798   size_t i;
799   static Class proto_class = 0;
800
801   if (! protos)
802     return;
803
804   objc_mutex_lock (__objc_runtime_mutex);
805
806   if (! proto_class)
807     proto_class = objc_lookup_class ("Protocol");
808
809   if (! proto_class)
810     {
811       unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
812       objc_mutex_unlock (__objc_runtime_mutex);
813       return;
814     }
815
816 #if 0
817   assert (protos->next == 0);   /* only single ones allowed */
818 #endif
819
820   for (i = 0; i < protos->count; i++)
821     {
822       struct objc_protocol *aProto = protos->list[i];
823       if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
824         {
825           /* assign class pointer */
826           aProto->class_pointer = proto_class;
827
828           /* init super protocols */
829           __objc_init_protocols (aProto->protocol_list);
830         }
831       else if (protos->list[i]->class_pointer != proto_class)
832         {
833           objc_error (nil, OBJC_ERR_PROTOCOL_VERSION,
834                      "Version %d doesn't match runtime protocol version %d\n",
835                      (int) ((char *) protos->list[i]->class_pointer
836                             - (char *) 0),
837                      PROTOCOL_VERSION);
838         }
839     }
840
841   objc_mutex_unlock (__objc_runtime_mutex);
842 }
843
844 static void
845 __objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
846 {
847   /* Well...  */
848   if (! protos)
849     return;
850
851   /* Add it...  */
852   protos->next = class->protocols;
853   class->protocols = protos;
854 }