Merge from mainline (163495:164578).
[official-gcc/graphite-test-results.git] / libobjc / init.c
blobdeb089d7e16a83b5a7e02e2806f334eb11dc2d89
1 /* GNU Objective C Runtime initialization
2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2009
3 Free Software Foundation, Inc.
4 Contributed by Kresten Krab Thorup
5 +load support contributed by Ovidiu Predescu <ovidiu@net-community.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under the
10 terms of the GNU General Public License as published by the Free Software
11 Foundation; either version 3, or (at your option) any later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
27 #include "objc-private/common.h"
28 #include "objc-private/error.h"
29 #include "objc/objc.h"
30 #include "objc/objc-api.h"
31 #include "objc/thr.h"
32 #include "objc-private/hash.h"
33 #include "objc-private/objc-list.h"
34 #include "objc-private/runtime.h"
35 #include "objc-private/objc-sync.h" /* For __objc_sync_init() */
37 /* The version number of this runtime. This must match the number
38 defined in gcc (objc-act.c). */
39 #define OBJC_VERSION 8
40 #define PROTOCOL_VERSION 2
42 /* This list contains all modules currently loaded into the runtime. */
43 static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
45 /* This list contains all proto_list's not yet assigned class links. */
46 static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */
48 /* List of unresolved static instances. */
49 static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
51 /* Global runtime "write" mutex. */
52 objc_mutex_t __objc_runtime_mutex = 0;
54 /* Number of threads that are alive. */
55 int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
57 /* Check compiler vs runtime version. */
58 static void init_check_module_version (Module_t);
60 /* Assign isa links to protos. */
61 static void __objc_init_protocols (struct objc_protocol_list *protos);
63 /* Add protocol to class. */
64 static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
66 /* This is a hook which is called by __objc_exec_class every time a
67 class or a category is loaded into the runtime. This may e.g. help
68 a dynamic loader determine the classes that have been loaded when
69 an object file is dynamically linked in. */
70 void (*_objc_load_callback) (Class class, Category *category); /* !T:SAFE */
72 /* Is all categories/classes resolved? */
73 BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
75 extern SEL
76 __sel_register_typed_name (const char *name, const char *types,
77 struct objc_selector *orig, BOOL is_const);
79 /* Sends +load to all classes and categories in certain situations. */
80 static void objc_send_load (void);
82 /* Inserts all the classes defined in module in a tree of classes that
83 resembles the class hierarchy. This tree is traversed in preorder
84 and the classes in its nodes receive the +load message if these
85 methods were not executed before. The algorithm ensures that when
86 the +load method of a class is executed all the superclasses have
87 been already received the +load message. */
88 static void __objc_create_classes_tree (Module_t module);
90 static void __objc_call_callback (Module_t module);
92 /* A special version that works only before the classes are completely
93 installed in the runtime. */
94 static BOOL class_is_subclass_of_class (Class class, Class superclass);
96 typedef struct objc_class_tree {
97 Class class;
98 struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */
99 } objc_class_tree;
101 /* This is a linked list of objc_class_tree trees. The head of these
102 trees are root classes (their super class is Nil). These different
103 trees represent different class hierarchies. */
104 static struct objc_list *__objc_class_tree_list = NULL;
106 /* Keeps the +load methods who have been already executed. This hash
107 should not be destroyed during the execution of the program. */
108 static cache_ptr __objc_load_methods = NULL;
110 /* This function is used when building the class tree used to send
111 ordinately the +load message to all classes needing it. The tree
112 is really needed so that superclasses will get the message before
113 subclasses.
115 This tree will contain classes which are being loaded (or have just
116 being loaded), and whose super_class pointers have not yet been
117 resolved. This implies that their super_class pointers point to a
118 string with the name of the superclass; when the first message is
119 sent to the class (/an object of that class) the class links will
120 be resolved, which will replace the super_class pointers with
121 pointers to the actual superclasses.
123 Unfortunately, the tree might also contain classes which had been
124 loaded previously, and whose class links have already been
125 resolved.
127 This function returns the superclass of a class in both cases, and
128 can be used to build the determine the class relationships while
129 building the tree.
131 static Class class_superclass_of_class (Class class)
133 char *super_class_name;
135 /* If the class links have been resolved, use the resolved
136 * links. */
137 if (CLS_ISRESOLV (class))
138 return class->super_class;
140 /* Else, 'class' has not yet been resolved. This means that its
141 * super_class pointer is really the name of the super class (rather
142 * than a pointer to the actual superclass). */
143 super_class_name = (char *)class->super_class;
145 /* Return Nil for a root class. */
146 if (super_class_name == NULL)
147 return Nil;
149 /* Lookup the superclass of non-root classes. */
150 return objc_lookup_class (super_class_name);
154 /* Creates a tree of classes whose topmost class is directly inherited
155 from `upper' and the bottom class in this tree is
156 `bottom_class'. The classes in this tree are super classes of
157 `bottom_class'. `subclasses' member of each tree node point to the
158 next subclass tree node. */
160 static objc_class_tree *
161 create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
163 Class superclass = bottom_class->super_class ?
164 objc_lookup_class ((char *) bottom_class->super_class)
165 : Nil;
167 objc_class_tree *tree, *prev;
169 DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
170 DEBUG_PRINTF ("bottom_class = %s, upper = %s\n",
171 (bottom_class ? bottom_class->name : NULL),
172 (upper ? upper->name : NULL));
174 tree = prev = objc_calloc (1, sizeof (objc_class_tree));
175 prev->class = bottom_class;
177 while (superclass != upper)
179 tree = objc_calloc (1, sizeof (objc_class_tree));
180 tree->class = superclass;
181 tree->subclasses = list_cons (prev, tree->subclasses);
182 superclass = class_superclass_of_class (superclass);
183 prev = tree;
186 return tree;
189 /* Insert the `class' into the proper place in the `tree' class
190 hierarchy. This function returns a new tree if the class has been
191 successfully inserted into the tree or NULL if the class is not
192 part of the classes hierarchy described by `tree'. This function is
193 private to objc_tree_insert_class (), you should not call it
194 directly. */
196 static objc_class_tree *
197 __objc_tree_insert_class (objc_class_tree *tree, Class class)
199 DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
200 tree, class->name);
202 if (tree == NULL)
203 return create_tree_of_subclasses_inherited_from (class, NULL);
204 else if (class == tree->class)
206 /* `class' has been already inserted */
207 DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
208 return tree;
210 else if (class_superclass_of_class (class) == tree->class)
212 /* If class is a direct subclass of tree->class then add class to the
213 list of subclasses. First check to see if it wasn't already
214 inserted. */
215 struct objc_list *list = tree->subclasses;
216 objc_class_tree *node;
218 while (list)
220 /* Class has been already inserted; do nothing just return
221 the tree. */
222 if (((objc_class_tree *) list->head)->class == class)
224 DEBUG_PRINTF ("2. class %s was previously inserted\n",
225 class->name);
226 return tree;
228 list = list->tail;
231 /* Create a new node class and insert it into the list of subclasses */
232 node = objc_calloc (1, sizeof (objc_class_tree));
233 node->class = class;
234 tree->subclasses = list_cons (node, tree->subclasses);
235 DEBUG_PRINTF ("3. class %s inserted\n", class->name);
236 return tree;
238 else
240 /* The class is not a direct subclass of tree->class. Search for
241 class's superclasses in the list of subclasses. */
242 struct objc_list *subclasses = tree->subclasses;
244 /* Precondition: the class must be a subclass of tree->class;
245 otherwise return NULL to indicate our caller that it must
246 take the next tree. */
247 if (! class_is_subclass_of_class (class, tree->class))
248 return NULL;
250 for (; subclasses != NULL; subclasses = subclasses->tail)
252 Class aClass = ((objc_class_tree *) (subclasses->head))->class;
254 if (class_is_subclass_of_class (class, aClass))
256 /* If we found one of class's superclasses we insert the
257 class into its subtree and return the original tree
258 since nothing has been changed. */
259 subclasses->head
260 = __objc_tree_insert_class (subclasses->head, class);
261 DEBUG_PRINTF ("4. class %s inserted\n", class->name);
262 return tree;
266 /* We haven't found a subclass of `class' in the `subclasses'
267 list. Create a new tree of classes whose topmost class is a
268 direct subclass of tree->class. */
270 objc_class_tree *new_tree
271 = create_tree_of_subclasses_inherited_from (class, tree->class);
272 tree->subclasses = list_cons (new_tree, tree->subclasses);
273 DEBUG_PRINTF ("5. class %s inserted\n", class->name);
274 return tree;
279 /* This function inserts `class' in the right tree hierarchy classes. */
281 static void
282 objc_tree_insert_class (Class class)
284 struct objc_list *list_node;
285 objc_class_tree *tree;
287 list_node = __objc_class_tree_list;
288 while (list_node)
290 tree = __objc_tree_insert_class (list_node->head, class);
291 if (tree)
293 list_node->head = tree;
294 break;
296 else
297 list_node = list_node->tail;
300 /* If the list was finished but the class hasn't been inserted,
301 insert it here. */
302 if (! list_node)
304 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
305 __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
309 /* Traverse tree in preorder. Used to send +load. */
311 static void
312 objc_preorder_traverse (objc_class_tree *tree,
313 int level,
314 void (*function) (objc_class_tree *, int))
316 struct objc_list *node;
318 (*function) (tree, level);
319 for (node = tree->subclasses; node; node = node->tail)
320 objc_preorder_traverse (node->head, level + 1, function);
323 /* Traverse tree in postorder. Used to destroy a tree. */
325 static void
326 objc_postorder_traverse (objc_class_tree *tree,
327 int level,
328 void (*function) (objc_class_tree *, int))
330 struct objc_list *node;
332 for (node = tree->subclasses; node; node = node->tail)
333 objc_postorder_traverse (node->head, level + 1, function);
334 (*function) (tree, level);
337 /* Used to print a tree class hierarchy. */
339 #ifdef DEBUG
340 static void
341 __objc_tree_print (objc_class_tree *tree, int level)
343 int i;
345 for (i = 0; i < level; i++)
346 printf (" ");
347 printf ("%s\n", tree->class->name);
349 #endif
351 /* Walks on a linked list of methods in the reverse order and executes
352 all the methods corresponding to `op' selector. Walking in the
353 reverse order assures the +load of class is executed first and then
354 +load of categories because of the way in which categories are
355 added to the class methods. */
357 static void
358 __objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
360 int i;
362 if (! method_list)
363 return;
365 /* First execute the `op' message in the following method lists */
366 __objc_send_message_in_list (method_list->method_next, class, op);
368 /* Search the method list. */
369 for (i = 0; i < method_list->method_count; i++)
371 Method_t mth = &method_list->method_list[i];
373 if (mth->method_name && sel_eq (mth->method_name, op)
374 && ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
376 /* Add this method into the +load hash table */
377 objc_hash_add (&__objc_load_methods,
378 mth->method_imp,
379 mth->method_imp);
381 DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
383 /* The method was found and wasn't previously executed. */
384 (*mth->method_imp) ((id)class, mth->method_name);
386 break;
391 static void
392 __objc_send_load (objc_class_tree *tree,
393 int level __attribute__ ((__unused__)))
395 static SEL load_sel = 0;
396 Class class = tree->class;
397 MethodList_t method_list = class->class_pointer->methods;
399 if (! load_sel)
400 load_sel = sel_register_name ("load");
402 __objc_send_message_in_list (method_list, class, load_sel);
405 static void
406 __objc_destroy_class_tree_node (objc_class_tree *tree,
407 int level __attribute__ ((__unused__)))
409 objc_free (tree);
412 /* This is used to check if the relationship between two classes
413 before the runtime completely installs the classes. */
415 static BOOL
416 class_is_subclass_of_class (Class class, Class superclass)
418 for (; class != Nil;)
420 if (class == superclass)
421 return YES;
422 class = class_superclass_of_class (class);
425 return NO;
428 /* This list contains all the classes in the runtime system for whom
429 their superclasses are not yet known to the runtime. */
430 static struct objc_list *unresolved_classes = 0;
432 /* Extern function used to reference the Object and NXConstantString
433 classes. */
435 extern void __objc_force_linking (void);
437 void
438 __objc_force_linking (void)
440 extern void __objc_linking (void);
441 __objc_linking ();
444 /* Run through the statics list, removing modules as soon as all its
445 statics have been initialized. */
447 static void
448 objc_init_statics (void)
450 struct objc_list **cell = &uninitialized_statics;
451 struct objc_static_instances **statics_in_module;
453 objc_mutex_lock (__objc_runtime_mutex);
455 while (*cell)
457 int module_initialized = 1;
459 for (statics_in_module = (*cell)->head;
460 *statics_in_module; statics_in_module++)
462 struct objc_static_instances *statics = *statics_in_module;
463 Class class = objc_lookup_class (statics->class_name);
465 if (! class)
466 module_initialized = 0;
467 /* Actually, the static's class_pointer will be NULL when we
468 haven't been here before. However, the comparison is to be
469 reminded of taking into account class posing and to think about
470 possible semantics... */
471 else if (class != statics->instances[0]->class_pointer)
473 id *inst;
475 for (inst = &statics->instances[0]; *inst; inst++)
477 (*inst)->class_pointer = class;
479 /* ??? Make sure the object will not be freed. With
480 refcounting, invoke `-retain'. Without refcounting, do
481 nothing and hope that `-free' will never be invoked. */
483 /* ??? Send the object an `-initStatic' or something to
484 that effect now or later on? What are the semantics of
485 statically allocated instances, besides the trivial
486 NXConstantString, anyway? */
490 if (module_initialized)
492 /* Remove this module from the uninitialized list. */
493 struct objc_list *this = *cell;
494 *cell = this->tail;
495 objc_free (this);
497 else
498 cell = &(*cell)->tail;
501 objc_mutex_unlock (__objc_runtime_mutex);
502 } /* objc_init_statics */
504 /* This function is called by constructor functions generated for each
505 module compiled. (_GLOBAL_$I$...) The purpose of this function is
506 to gather the module pointers so that they may be processed by the
507 initialization routines as soon as possible. */
509 void
510 __objc_exec_class (Module_t module)
512 /* Have we processed any constructors previously? This flag is used to
513 indicate that some global data structures need to be built. */
514 static BOOL previous_constructors = 0;
516 static struct objc_list *unclaimed_categories = 0;
518 /* The symbol table (defined in objc-api.h) generated by gcc */
519 Symtab_t symtab = module->symtab;
521 /* The statics in this module */
522 struct objc_static_instances **statics
523 = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
525 /* Entry used to traverse hash lists */
526 struct objc_list **cell;
528 /* The table of selector references for this module */
529 SEL selectors = symtab->refs;
531 /* dummy counter */
532 int i;
534 DEBUG_PRINTF ("received module: %s\n", module->name);
536 /* check gcc version */
537 init_check_module_version (module);
539 /* On the first call of this routine, initialize some data structures. */
540 if (! previous_constructors)
542 /* Initialize thread-safe system */
543 __objc_init_thread_system ();
544 __objc_runtime_threads_alive = 1;
545 __objc_runtime_mutex = objc_mutex_allocate ();
547 __objc_init_selector_tables ();
548 __objc_init_class_tables ();
549 __objc_init_dispatch_tables ();
550 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
551 __objc_load_methods = objc_hash_new (128,
552 (hash_func_type)objc_hash_ptr,
553 objc_compare_ptrs);
554 __objc_sync_init ();
555 previous_constructors = 1;
558 /* Save the module pointer for later processing. (not currently used) */
559 objc_mutex_lock (__objc_runtime_mutex);
560 __objc_module_list = list_cons (module, __objc_module_list);
562 /* Replace referenced selectors from names to SEL's. */
563 if (selectors)
565 for (i = 0; selectors[i].sel_id; ++i)
567 const char *name, *type;
568 name = (char *) selectors[i].sel_id;
569 type = (char *) selectors[i].sel_types;
570 /* Constructors are constant static data so we can safely store
571 pointers to them in the runtime structures. is_const == YES */
572 __sel_register_typed_name (name, type,
573 (struct objc_selector *) &(selectors[i]),
574 YES);
578 /* Parse the classes in the load module and gather selector information. */
579 DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
580 for (i = 0; i < symtab->cls_def_cnt; ++i)
582 Class class = (Class) symtab->defs[i];
583 const char *superclass = (char *) class->super_class;
585 /* Make sure we have what we think. */
586 assert (CLS_ISCLASS (class));
587 assert (CLS_ISMETA (class->class_pointer));
588 DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
590 /* Initialize the subclass list to be NULL.
591 In some cases it isn't and this crashes the program. */
592 class->subclass_list = NULL;
594 /* Store the class in the class table and assign class numbers. */
595 __objc_add_class_to_hash (class);
597 /* Register all of the selectors in the class and meta class. */
598 __objc_register_selectors_from_class (class);
599 __objc_register_selectors_from_class ((Class) class->class_pointer);
601 /* Install the fake dispatch tables */
602 __objc_install_premature_dtable (class);
603 __objc_install_premature_dtable (class->class_pointer);
605 /* Register the instance methods as class methods, this is
606 only done for root classes. */
607 __objc_register_instance_methods_to_class (class);
609 if (class->protocols)
610 __objc_init_protocols (class->protocols);
612 /* Check to see if the superclass is known in this point. If it's not
613 add the class to the unresolved_classes list. */
614 if (superclass && ! objc_lookup_class (superclass))
615 unresolved_classes = list_cons (class, unresolved_classes);
618 /* Process category information from the module. */
619 for (i = 0; i < symtab->cat_def_cnt; ++i)
621 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
622 Class class = objc_lookup_class (category->class_name);
624 /* If the class for the category exists then append its methods. */
625 if (class)
628 DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
629 module->name,
630 class->name);
632 /* Do instance methods. */
633 if (category->instance_methods)
634 class_add_method_list (class, category->instance_methods);
636 /* Do class methods. */
637 if (category->class_methods)
638 class_add_method_list ((Class) class->class_pointer,
639 category->class_methods);
641 if (category->protocols)
643 __objc_init_protocols (category->protocols);
644 __objc_class_add_protocols (class, category->protocols);
647 /* Register the instance methods as class methods, this is
648 only done for root classes. */
649 __objc_register_instance_methods_to_class (class);
651 else
653 /* The object to which the category methods belong can't be found.
654 Save the information. */
655 unclaimed_categories = list_cons (category, unclaimed_categories);
659 if (statics)
660 uninitialized_statics = list_cons (statics, uninitialized_statics);
661 if (uninitialized_statics)
662 objc_init_statics ();
664 /* Scan the unclaimed category hash. Attempt to attach any unclaimed
665 categories to objects. */
666 for (cell = &unclaimed_categories; *cell; )
668 Category_t category = (*cell)->head;
669 Class class = objc_lookup_class (category->class_name);
671 if (class)
673 DEBUG_PRINTF ("attaching stored categories to object: %s\n",
674 class->name);
676 list_remove_head (cell);
678 if (category->instance_methods)
679 class_add_method_list (class, category->instance_methods);
681 if (category->class_methods)
682 class_add_method_list ((Class) class->class_pointer,
683 category->class_methods);
685 if (category->protocols)
687 __objc_init_protocols (category->protocols);
688 __objc_class_add_protocols (class, category->protocols);
691 /* Register the instance methods as class methods, this is
692 only done for root classes. */
693 __objc_register_instance_methods_to_class (class);
695 else
696 cell = &(*cell)->tail;
699 if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
701 list_mapcar (unclaimed_proto_list,
702 (void (*) (void *))__objc_init_protocols);
703 list_free (unclaimed_proto_list);
704 unclaimed_proto_list = 0;
707 objc_send_load ();
709 objc_mutex_unlock (__objc_runtime_mutex);
712 static void
713 objc_send_load (void)
715 if (! __objc_module_list)
716 return;
718 /* Try to find out if all the classes loaded so far also have their
719 superclasses known to the runtime. We suppose that the objects
720 that are allocated in the +load method are in general of a class
721 declared in the same module. */
722 if (unresolved_classes)
724 Class class = unresolved_classes->head;
726 while (objc_lookup_class ((char *) class->super_class))
728 list_remove_head (&unresolved_classes);
729 if (unresolved_classes)
730 class = unresolved_classes->head;
731 else
732 break;
735 /* If we still have classes for whom we don't have yet their
736 super classes known to the runtime we don't send the +load
737 messages. */
738 if (unresolved_classes)
739 return;
742 /* Special check to allow creating and sending messages to constant
743 strings in +load methods. If these classes are not yet known,
744 even if all the other classes are known, delay sending of +load. */
745 if (! objc_lookup_class ("NXConstantString") ||
746 ! objc_lookup_class ("Object"))
747 return;
749 /* Iterate over all modules in the __objc_module_list and call on
750 them the __objc_create_classes_tree function. This function
751 creates a tree of classes that resembles the class hierarchy. */
752 list_mapcar (__objc_module_list,
753 (void (*) (void *)) __objc_create_classes_tree);
755 while (__objc_class_tree_list)
757 #ifdef DEBUG
758 objc_preorder_traverse (__objc_class_tree_list->head,
759 0, __objc_tree_print);
760 #endif
761 objc_preorder_traverse (__objc_class_tree_list->head,
762 0, __objc_send_load);
763 objc_postorder_traverse (__objc_class_tree_list->head,
764 0, __objc_destroy_class_tree_node);
765 list_remove_head (&__objc_class_tree_list);
768 list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
769 list_free (__objc_module_list);
770 __objc_module_list = NULL;
773 static void
774 __objc_create_classes_tree (Module_t module)
776 /* The runtime mutex is locked in this point */
778 Symtab_t symtab = module->symtab;
779 int i;
781 /* Iterate thru classes defined in this module and insert them in
782 the classes tree hierarchy. */
783 for (i = 0; i < symtab->cls_def_cnt; i++)
785 Class class = (Class) symtab->defs[i];
787 objc_tree_insert_class (class);
791 static void
792 __objc_call_callback (Module_t module)
794 /* The runtime mutex is locked in this point. */
796 Symtab_t symtab = module->symtab;
797 int i;
799 /* Iterate thru classes defined in this module and call the callback
800 for each one. */
801 for (i = 0; i < symtab->cls_def_cnt; i++)
803 Class class = (Class) symtab->defs[i];
805 /* Call the _objc_load_callback for this class. */
806 if (_objc_load_callback)
807 _objc_load_callback (class, 0);
810 /* Call the _objc_load_callback for categories. Don't register the
811 instance methods as class methods for categories to root classes
812 since they were already added in the class. */
813 for (i = 0; i < symtab->cat_def_cnt; i++)
815 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
816 Class class = objc_lookup_class (category->class_name);
818 if (_objc_load_callback)
819 _objc_load_callback (class, category);
823 /* Sanity check the version of gcc used to compile `module'. */
825 static void
826 init_check_module_version (Module_t module)
828 if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
830 _objc_abort ("Module %s version %d doesn't match runtime %d\n",
831 module->name, (int)module->version, OBJC_VERSION);
835 static void
836 __objc_init_protocols (struct objc_protocol_list *protos)
838 size_t i;
839 static Class proto_class = 0;
841 if (! protos)
842 return;
844 objc_mutex_lock (__objc_runtime_mutex);
846 if (! proto_class)
847 proto_class = objc_lookup_class ("Protocol");
849 if (! proto_class)
851 unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
852 objc_mutex_unlock (__objc_runtime_mutex);
853 return;
856 #if 0
857 assert (protos->next == 0); /* only single ones allowed */
858 #endif
860 for (i = 0; i < protos->count; i++)
862 struct objc_protocol *aProto = protos->list[i];
863 if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
865 /* assign class pointer */
866 aProto->class_pointer = proto_class;
868 /* init super protocols */
869 __objc_init_protocols (aProto->protocol_list);
871 else if (protos->list[i]->class_pointer != proto_class)
873 _objc_abort ("Version %d doesn't match runtime protocol version %d\n",
874 (int) ((char *) protos->list[i]->class_pointer
875 - (char *) 0),
876 PROTOCOL_VERSION);
880 objc_mutex_unlock (__objc_runtime_mutex);
883 static void
884 __objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
886 /* Well... */
887 if (! protos)
888 return;
890 /* Add it... */
891 protos->next = class->protocols;
892 class->protocols = protos;