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