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