2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libobjc / init.c
blob33a933875b0e6ac7f706ecca012cd7da8d8de4d5
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>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2, or (at your option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 details.
17 You should have received a copy of the GNU General Public License along with
18 GCC; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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. */
27 #include "runtime.h"
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
34 /* This list contains all modules currently loaded into the runtime. */
35 static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
37 /* This list contains all proto_list's not yet assigned class links. */
38 static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */
40 /* List of unresolved static instances. */
41 static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
43 /* Global runtime "write" mutex. */
44 objc_mutex_t __objc_runtime_mutex = 0;
46 /* Number of threads that are alive. */
47 int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
49 /* Check compiler vs runtime version. */
50 static void init_check_module_version (Module_t);
52 /* Assign isa links to protos. */
53 static void __objc_init_protocols (struct objc_protocol_list *protos);
55 /* Add protocol to class. */
56 static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
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 */
64 /* Is all categories/classes resolved? */
65 BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
67 extern SEL
68 __sel_register_typed_name (const char *name, const char *types,
69 struct objc_selector *orig, BOOL is_const);
71 /* Sends +load to all classes and categories in certain situations. */
72 static void objc_send_load (void);
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);
82 static void __objc_call_callback (Module_t module);
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);
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;
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;
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;
102 /* This function is used when building the class tree used to send
103 ordinately the +load message to all classes needing it. The tree
104 is really needed so that superclasses will get the message before
105 subclasses.
107 This tree will contain classes which are being loaded (or have just
108 being loaded), and whose super_class pointers have not yet been
109 resolved. This implies that their super_class pointers point to a
110 string with the name of the superclass; when the first message is
111 sent to the class (/an object of that class) the class links will
112 be resolved, which will replace the super_class pointers with
113 pointers to the actual superclasses.
115 Unfortunately, the tree might also contain classes which had been
116 loaded previously, and whose class links have already been
117 resolved.
119 This function returns the superclass of a class in both cases, and
120 can be used to build the determine the class relationships while
121 building the tree.
123 static Class class_superclass_of_class (Class class)
125 char *super_class_name;
127 /* If the class links have been resolved, use the resolved
128 * links. */
129 if (CLS_ISRESOLV (class))
130 return class->super_class;
132 /* Else, 'class' has not yet been resolved. This means that its
133 * super_class pointer is really the name of the super class (rather
134 * than a pointer to the actual superclass). */
135 super_class_name = (char *)class->super_class;
137 /* Return Nil for a root class. */
138 if (super_class_name == NULL)
139 return Nil;
141 /* Lookup the superclass of non-root classes. */
142 return objc_lookup_class (super_class_name);
146 /* Creates a tree of classes whose topmost class is directly inherited
147 from `upper' and the bottom class in this tree is
148 `bottom_class'. The classes in this tree are super classes of
149 `bottom_class'. `subclasses' member of each tree node point to the
150 next subclass tree node. */
152 static objc_class_tree *
153 create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
155 Class superclass = bottom_class->super_class ?
156 objc_lookup_class ((char *) bottom_class->super_class)
157 : Nil;
159 objc_class_tree *tree, *prev;
161 DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
162 DEBUG_PRINTF ("bottom_class = %s, upper = %s\n",
163 (bottom_class ? bottom_class->name : NULL),
164 (upper ? upper->name : NULL));
166 tree = prev = objc_calloc (1, sizeof (objc_class_tree));
167 prev->class = bottom_class;
169 while (superclass != upper)
171 tree = objc_calloc (1, sizeof (objc_class_tree));
172 tree->class = superclass;
173 tree->subclasses = list_cons (prev, tree->subclasses);
174 superclass = class_superclass_of_class (superclass);
175 prev = tree;
178 return tree;
181 /* Insert the `class' into the proper place in the `tree' class
182 hierarchy. This function returns a new tree if the class has been
183 successfully inserted into the tree or NULL if the class is not
184 part of the classes hierarchy described by `tree'. This function is
185 private to objc_tree_insert_class (), you should not call it
186 directly. */
188 static objc_class_tree *
189 __objc_tree_insert_class (objc_class_tree *tree, Class class)
191 DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
192 tree, class->name);
194 if (tree == NULL)
195 return create_tree_of_subclasses_inherited_from (class, NULL);
196 else if (class == tree->class)
198 /* `class' has been already inserted */
199 DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
200 return tree;
202 else if (class_superclass_of_class (class) == tree->class)
204 /* If class is a direct subclass of tree->class then add class to the
205 list of subclasses. First check to see if it wasn't already
206 inserted. */
207 struct objc_list *list = tree->subclasses;
208 objc_class_tree *node;
210 while (list)
212 /* Class has been already inserted; do nothing just return
213 the tree. */
214 if (((objc_class_tree *) list->head)->class == class)
216 DEBUG_PRINTF ("2. class %s was previously inserted\n",
217 class->name);
218 return tree;
220 list = list->tail;
223 /* Create a new node class and insert it into the list of subclasses */
224 node = objc_calloc (1, sizeof (objc_class_tree));
225 node->class = class;
226 tree->subclasses = list_cons (node, tree->subclasses);
227 DEBUG_PRINTF ("3. class %s inserted\n", class->name);
228 return tree;
230 else
232 /* The class is not a direct subclass of tree->class. Search for
233 class's superclasses in the list of subclasses. */
234 struct objc_list *subclasses = tree->subclasses;
236 /* Precondition: the class must be a subclass of tree->class;
237 otherwise return NULL to indicate our caller that it must
238 take the next tree. */
239 if (! class_is_subclass_of_class (class, tree->class))
240 return NULL;
242 for (; subclasses != NULL; subclasses = subclasses->tail)
244 Class aClass = ((objc_class_tree *) (subclasses->head))->class;
246 if (class_is_subclass_of_class (class, aClass))
248 /* If we found one of class's superclasses we insert the
249 class into its subtree and return the original tree
250 since nothing has been changed. */
251 subclasses->head
252 = __objc_tree_insert_class (subclasses->head, class);
253 DEBUG_PRINTF ("4. class %s inserted\n", class->name);
254 return tree;
258 /* We haven't found a subclass of `class' in the `subclasses'
259 list. Create a new tree of classes whose topmost class is a
260 direct subclass of tree->class. */
262 objc_class_tree *new_tree
263 = create_tree_of_subclasses_inherited_from (class, tree->class);
264 tree->subclasses = list_cons (new_tree, tree->subclasses);
265 DEBUG_PRINTF ("5. class %s inserted\n", class->name);
266 return tree;
271 /* This function inserts `class' in the right tree hierarchy classes. */
273 static void
274 objc_tree_insert_class (Class class)
276 struct objc_list *list_node;
277 objc_class_tree *tree;
279 list_node = __objc_class_tree_list;
280 while (list_node)
282 tree = __objc_tree_insert_class (list_node->head, class);
283 if (tree)
285 list_node->head = tree;
286 break;
288 else
289 list_node = list_node->tail;
292 /* If the list was finished but the class hasn't been inserted,
293 insert it here. */
294 if (! list_node)
296 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
297 __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
301 /* Traverse tree in preorder. Used to send +load. */
303 static void
304 objc_preorder_traverse (objc_class_tree *tree,
305 int level,
306 void (*function) (objc_class_tree *, int))
308 struct objc_list *node;
310 (*function) (tree, level);
311 for (node = tree->subclasses; node; node = node->tail)
312 objc_preorder_traverse (node->head, level + 1, function);
315 /* Traverse tree in postorder. Used to destroy a tree. */
317 static void
318 objc_postorder_traverse (objc_class_tree *tree,
319 int level,
320 void (*function) (objc_class_tree *, int))
322 struct objc_list *node;
324 for (node = tree->subclasses; node; node = node->tail)
325 objc_postorder_traverse (node->head, level + 1, function);
326 (*function) (tree, level);
329 /* Used to print a tree class hierarchy. */
331 #ifdef DEBUG
332 static void
333 __objc_tree_print (objc_class_tree *tree, int level)
335 int i;
337 for (i = 0; i < level; i++)
338 printf (" ");
339 printf ("%s\n", tree->class->name);
341 #endif
343 /* Walks on a linked list of methods in the reverse order and executes
344 all the methods corresponding to `op' selector. Walking in the
345 reverse order assures the +load of class is executed first and then
346 +load of categories because of the way in which categories are
347 added to the class methods. */
349 static void
350 __objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
352 int i;
354 if (! method_list)
355 return;
357 /* First execute the `op' message in the following method lists */
358 __objc_send_message_in_list (method_list->method_next, class, op);
360 /* Search the method list. */
361 for (i = 0; i < method_list->method_count; i++)
363 Method_t mth = &method_list->method_list[i];
365 if (mth->method_name && sel_eq (mth->method_name, op)
366 && ! hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
368 /* Add this method into the +load hash table */
369 hash_add (&__objc_load_methods, mth->method_imp, mth->method_imp);
371 DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
373 /* The method was found and wasn't previously executed. */
374 (*mth->method_imp) ((id)class, mth->method_name);
376 break;
381 static void
382 __objc_send_load (objc_class_tree *tree,
383 int level __attribute__ ((__unused__)))
385 static SEL load_sel = 0;
386 Class class = tree->class;
387 MethodList_t method_list = class->class_pointer->methods;
389 if (! load_sel)
390 load_sel = sel_register_name ("load");
392 __objc_send_message_in_list (method_list, class, load_sel);
395 static void
396 __objc_destroy_class_tree_node (objc_class_tree *tree,
397 int level __attribute__ ((__unused__)))
399 objc_free (tree);
402 /* This is used to check if the relationship between two classes
403 before the runtime completely installs the classes. */
405 static BOOL
406 class_is_subclass_of_class (Class class, Class superclass)
408 for (; class != Nil;)
410 if (class == superclass)
411 return YES;
412 class = class_superclass_of_class (class);
415 return NO;
418 /* This list contains all the classes in the runtime system for whom
419 their superclasses are not yet known to the runtime. */
420 static struct objc_list *unresolved_classes = 0;
422 /* Extern function used to reference the Object and NXConstantString
423 classes. */
425 extern void __objc_force_linking (void);
427 void
428 __objc_force_linking (void)
430 extern void __objc_linking (void);
431 __objc_linking ();
434 /* Run through the statics list, removing modules as soon as all its
435 statics have been initialized. */
437 static void
438 objc_init_statics (void)
440 struct objc_list **cell = &uninitialized_statics;
441 struct objc_static_instances **statics_in_module;
443 objc_mutex_lock (__objc_runtime_mutex);
445 while (*cell)
447 int module_initialized = 1;
449 for (statics_in_module = (*cell)->head;
450 *statics_in_module; statics_in_module++)
452 struct objc_static_instances *statics = *statics_in_module;
453 Class class = objc_lookup_class (statics->class_name);
455 if (! class)
456 module_initialized = 0;
457 /* Actually, the static's class_pointer will be NULL when we
458 haven't been here before. However, the comparison is to be
459 reminded of taking into account class posing and to think about
460 possible semantics... */
461 else if (class != statics->instances[0]->class_pointer)
463 id *inst;
465 for (inst = &statics->instances[0]; *inst; inst++)
467 (*inst)->class_pointer = class;
469 /* ??? Make sure the object will not be freed. With
470 refcounting, invoke `-retain'. Without refcounting, do
471 nothing and hope that `-free' will never be invoked. */
473 /* ??? Send the object an `-initStatic' or something to
474 that effect now or later on? What are the semantics of
475 statically allocated instances, besides the trivial
476 NXConstantString, anyway? */
480 if (module_initialized)
482 /* Remove this module from the uninitialized list. */
483 struct objc_list *this = *cell;
484 *cell = this->tail;
485 objc_free (this);
487 else
488 cell = &(*cell)->tail;
491 objc_mutex_unlock (__objc_runtime_mutex);
492 } /* objc_init_statics */
494 /* This function is called by constructor functions generated for each
495 module compiled. (_GLOBAL_$I$...) The purpose of this function is
496 to gather the module pointers so that they may be processed by the
497 initialization routines as soon as possible. */
499 void
500 __objc_exec_class (Module_t module)
502 /* Have we processed any constructors previously? This flag is used to
503 indicate that some global data structures need to be built. */
504 static BOOL previous_constructors = 0;
506 static struct objc_list *unclaimed_categories = 0;
508 /* The symbol table (defined in objc-api.h) generated by gcc */
509 Symtab_t symtab = module->symtab;
511 /* The statics in this module */
512 struct objc_static_instances **statics
513 = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
515 /* Entry used to traverse hash lists */
516 struct objc_list **cell;
518 /* The table of selector references for this module */
519 SEL selectors = symtab->refs;
521 /* dummy counter */
522 int i;
524 DEBUG_PRINTF ("received module: %s\n", module->name);
526 /* check gcc version */
527 init_check_module_version (module);
529 /* On the first call of this routine, initialize some data structures. */
530 if (! previous_constructors)
532 /* Initialize thread-safe system */
533 __objc_init_thread_system ();
534 __objc_runtime_threads_alive = 1;
535 __objc_runtime_mutex = objc_mutex_allocate ();
537 __objc_init_selector_tables ();
538 __objc_init_class_tables ();
539 __objc_init_dispatch_tables ();
540 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
541 __objc_load_methods
542 = hash_new (128, (hash_func_type)hash_ptr, compare_ptrs);
543 previous_constructors = 1;
546 /* Save the module pointer for later processing. (not currently used) */
547 objc_mutex_lock (__objc_runtime_mutex);
548 __objc_module_list = list_cons (module, __objc_module_list);
550 /* Replace referenced selectors from names to SEL's. */
551 if (selectors)
553 for (i = 0; selectors[i].sel_id; ++i)
555 const char *name, *type;
556 name = (char *) selectors[i].sel_id;
557 type = (char *) selectors[i].sel_types;
558 /* Constructors are constant static data so we can safely store
559 pointers to them in the runtime structures. is_const == YES */
560 __sel_register_typed_name (name, type,
561 (struct objc_selector *) &(selectors[i]),
562 YES);
566 /* Parse the classes in the load module and gather selector information. */
567 DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
568 for (i = 0; i < symtab->cls_def_cnt; ++i)
570 Class class = (Class) symtab->defs[i];
571 const char *superclass = (char *) class->super_class;
573 /* Make sure we have what we think. */
574 assert (CLS_ISCLASS (class));
575 assert (CLS_ISMETA (class->class_pointer));
576 DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
578 /* Initialize the subclass list to be NULL.
579 In some cases it isn't and this crashes the program. */
580 class->subclass_list = NULL;
582 /* Store the class in the class table and assign class numbers. */
583 __objc_add_class_to_hash (class);
585 /* Register all of the selectors in the class and meta class. */
586 __objc_register_selectors_from_class (class);
587 __objc_register_selectors_from_class ((Class) class->class_pointer);
589 /* Install the fake dispatch tables */
590 __objc_install_premature_dtable (class);
591 __objc_install_premature_dtable (class->class_pointer);
593 /* Register the instance methods as class methods, this is
594 only done for root classes. */
595 __objc_register_instance_methods_to_class (class);
597 if (class->protocols)
598 __objc_init_protocols (class->protocols);
600 /* Check to see if the superclass is known in this point. If it's not
601 add the class to the unresolved_classes list. */
602 if (superclass && ! objc_lookup_class (superclass))
603 unresolved_classes = list_cons (class, unresolved_classes);
606 /* Process category information from the module. */
607 for (i = 0; i < symtab->cat_def_cnt; ++i)
609 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
610 Class class = objc_lookup_class (category->class_name);
612 /* If the class for the category exists then append its methods. */
613 if (class)
616 DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
617 module->name,
618 class->name);
620 /* Do instance methods. */
621 if (category->instance_methods)
622 class_add_method_list (class, category->instance_methods);
624 /* Do class methods. */
625 if (category->class_methods)
626 class_add_method_list ((Class) class->class_pointer,
627 category->class_methods);
629 if (category->protocols)
631 __objc_init_protocols (category->protocols);
632 __objc_class_add_protocols (class, category->protocols);
635 /* Register the instance methods as class methods, this is
636 only done for root classes. */
637 __objc_register_instance_methods_to_class (class);
639 else
641 /* The object to which the category methods belong can't be found.
642 Save the information. */
643 unclaimed_categories = list_cons (category, unclaimed_categories);
647 if (statics)
648 uninitialized_statics = list_cons (statics, uninitialized_statics);
649 if (uninitialized_statics)
650 objc_init_statics ();
652 /* Scan the unclaimed category hash. Attempt to attach any unclaimed
653 categories to objects. */
654 for (cell = &unclaimed_categories; *cell; )
656 Category_t category = (*cell)->head;
657 Class class = objc_lookup_class (category->class_name);
659 if (class)
661 DEBUG_PRINTF ("attaching stored categories to object: %s\n",
662 class->name);
664 list_remove_head (cell);
666 if (category->instance_methods)
667 class_add_method_list (class, category->instance_methods);
669 if (category->class_methods)
670 class_add_method_list ((Class) class->class_pointer,
671 category->class_methods);
673 if (category->protocols)
675 __objc_init_protocols (category->protocols);
676 __objc_class_add_protocols (class, category->protocols);
679 /* Register the instance methods as class methods, this is
680 only done for root classes. */
681 __objc_register_instance_methods_to_class (class);
683 else
684 cell = &(*cell)->tail;
687 if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
689 list_mapcar (unclaimed_proto_list,
690 (void (*) (void *))__objc_init_protocols);
691 list_free (unclaimed_proto_list);
692 unclaimed_proto_list = 0;
695 objc_send_load ();
697 objc_mutex_unlock (__objc_runtime_mutex);
700 static void
701 objc_send_load (void)
703 if (! __objc_module_list)
704 return;
706 /* Try to find out if all the classes loaded so far also have their
707 superclasses known to the runtime. We suppose that the objects
708 that are allocated in the +load method are in general of a class
709 declared in the same module. */
710 if (unresolved_classes)
712 Class class = unresolved_classes->head;
714 while (objc_lookup_class ((char *) class->super_class))
716 list_remove_head (&unresolved_classes);
717 if (unresolved_classes)
718 class = unresolved_classes->head;
719 else
720 break;
723 /* If we still have classes for whom we don't have yet their
724 super classes known to the runtime we don't send the +load
725 messages. */
726 if (unresolved_classes)
727 return;
730 /* Special check to allow creating and sending messages to constant
731 strings in +load methods. If these classes are not yet known,
732 even if all the other classes are known, delay sending of +load. */
733 if (! objc_lookup_class ("NXConstantString") ||
734 ! objc_lookup_class ("Object"))
735 return;
737 /* Iterate over all modules in the __objc_module_list and call on
738 them the __objc_create_classes_tree function. This function
739 creates a tree of classes that resembles the class hierarchy. */
740 list_mapcar (__objc_module_list,
741 (void (*) (void *)) __objc_create_classes_tree);
743 while (__objc_class_tree_list)
745 #ifdef DEBUG
746 objc_preorder_traverse (__objc_class_tree_list->head,
747 0, __objc_tree_print);
748 #endif
749 objc_preorder_traverse (__objc_class_tree_list->head,
750 0, __objc_send_load);
751 objc_postorder_traverse (__objc_class_tree_list->head,
752 0, __objc_destroy_class_tree_node);
753 list_remove_head (&__objc_class_tree_list);
756 list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
757 list_free (__objc_module_list);
758 __objc_module_list = NULL;
761 static void
762 __objc_create_classes_tree (Module_t module)
764 /* The runtime mutex is locked in this point */
766 Symtab_t symtab = module->symtab;
767 int i;
769 /* Iterate thru classes defined in this module and insert them in
770 the classes tree hierarchy. */
771 for (i = 0; i < symtab->cls_def_cnt; i++)
773 Class class = (Class) symtab->defs[i];
775 objc_tree_insert_class (class);
779 static void
780 __objc_call_callback (Module_t module)
782 /* The runtime mutex is locked in this point. */
784 Symtab_t symtab = module->symtab;
785 int i;
787 /* Iterate thru classes defined in this module and call the callback
788 for each one. */
789 for (i = 0; i < symtab->cls_def_cnt; i++)
791 Class class = (Class) symtab->defs[i];
793 /* Call the _objc_load_callback for this class. */
794 if (_objc_load_callback)
795 _objc_load_callback (class, 0);
798 /* Call the _objc_load_callback for categories. Don't register the
799 instance methods as class methods for categories to root classes
800 since they were already added in the class. */
801 for (i = 0; i < symtab->cat_def_cnt; i++)
803 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
804 Class class = objc_lookup_class (category->class_name);
806 if (_objc_load_callback)
807 _objc_load_callback (class, category);
811 /* Sanity check the version of gcc used to compile `module'. */
813 static void
814 init_check_module_version (Module_t module)
816 if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
818 int code;
820 if (module->version > OBJC_VERSION)
821 code = OBJC_ERR_OBJC_VERSION;
822 else if (module->version < OBJC_VERSION)
823 code = OBJC_ERR_GCC_VERSION;
824 else
825 code = OBJC_ERR_MODULE_SIZE;
827 objc_error (nil, code, "Module %s version %d doesn't match runtime %d\n",
828 module->name, (int)module->version, OBJC_VERSION);
832 static void
833 __objc_init_protocols (struct objc_protocol_list *protos)
835 size_t i;
836 static Class proto_class = 0;
838 if (! protos)
839 return;
841 objc_mutex_lock (__objc_runtime_mutex);
843 if (! proto_class)
844 proto_class = objc_lookup_class ("Protocol");
846 if (! proto_class)
848 unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
849 objc_mutex_unlock (__objc_runtime_mutex);
850 return;
853 #if 0
854 assert (protos->next == 0); /* only single ones allowed */
855 #endif
857 for (i = 0; i < protos->count; i++)
859 struct objc_protocol *aProto = protos->list[i];
860 if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
862 /* assign class pointer */
863 aProto->class_pointer = proto_class;
865 /* init super protocols */
866 __objc_init_protocols (aProto->protocol_list);
868 else if (protos->list[i]->class_pointer != proto_class)
870 objc_error (nil, OBJC_ERR_PROTOCOL_VERSION,
871 "Version %d doesn't match runtime protocol version %d\n",
872 (int) ((char *) protos->list[i]->class_pointer
873 - (char *) 0),
874 PROTOCOL_VERSION);
878 objc_mutex_unlock (__objc_runtime_mutex);
881 static void
882 __objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
884 /* Well... */
885 if (! protos)
886 return;
888 /* Add it... */
889 protos->next = class->protocols;
890 class->protocols = protos;