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