source: trunk/third/gcc/libobjc/init.c @ 21199

Revision 21199, 27.3 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21198, which included commits to RCS files with non-trunk default branches.
Line 
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
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under the
9terms of the GNU General Public License as published by the Free Software
10Foundation; either version 2, or (at your option) any later version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15details.
16
17You should have received a copy of the GNU General Public License along with
18GCC; see the file COPYING.  If not, write to the Free Software
19Foundation, 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.  */
35static struct objc_list *__objc_module_list = 0;        /* !T:MUTEX */
36
37/* This list contains all proto_list's not yet assigned class links.  */
38static struct objc_list *unclaimed_proto_list = 0;      /* !T:MUTEX */
39
40/* List of unresolved static instances.  */
41static struct objc_list *uninitialized_statics = 0;     /* !T:MUTEX */
42
43/* Global runtime "write" mutex.  */
44objc_mutex_t __objc_runtime_mutex = 0;
45
46/* Number of threads that are alive.  */
47int __objc_runtime_threads_alive = 1;                   /* !T:MUTEX */
48
49/* Check compiler vs runtime version.  */
50static void init_check_module_version (Module_t);
51
52/* Assign isa links to protos.  */
53static void __objc_init_protocols (struct objc_protocol_list *protos);
54
55/* Add protocol to class.  */
56static 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.  */
62void (*_objc_load_callback) (Class class, Category *category); /* !T:SAFE */
63
64/* Is all categories/classes resolved?  */
65BOOL __objc_dangling_categories = NO;           /* !T:UNUSED */
66
67extern 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.  */
72static 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.  */
80static void __objc_create_classes_tree (Module_t module);
81
82static 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.  */
86static BOOL class_is_subclass_of_class (Class class, Class superclass);
87
88typedef 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.  */
96static 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.  */
100static cache_ptr __objc_load_methods = NULL;
101
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.
106
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.
114
115   Unfortunately, the tree might also contain classes which had been
116   loaded previously, and whose class links have already been
117   resolved.
118
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.
122*/
123static Class  class_superclass_of_class (Class class)
124{
125  char *super_class_name;
126
127  /* If the class links have been resolved, use the resolved
128   * links.  */
129  if (CLS_ISRESOLV (class))
130    return class->super_class;
131 
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;
136
137  /* Return Nil for a root class.  */
138  if (super_class_name == NULL)
139    return Nil;
140
141  /* Lookup the superclass of non-root classes.  */
142  return objc_lookup_class (super_class_name);
143}
144
145
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.  */
151
152static objc_class_tree *
153create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
154{
155  Class superclass = bottom_class->super_class ?
156                        objc_lookup_class ((char *) bottom_class->super_class)
157                      : Nil;
158                                       
159  objc_class_tree *tree, *prev;
160
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));
165
166  tree = prev = objc_calloc (1, sizeof (objc_class_tree));
167  prev->class = bottom_class;
168
169  while (superclass != upper)
170    {
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;
176    }
177
178  return tree;
179}
180
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.  */
187
188static objc_class_tree *
189__objc_tree_insert_class (objc_class_tree *tree, Class class)
190{
191  DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
192                tree, class->name);
193
194  if (tree == NULL)
195    return create_tree_of_subclasses_inherited_from (class, NULL);
196  else if (class == tree->class)
197    {
198      /* `class' has been already inserted */
199      DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
200      return tree;
201    }
202  else if (class_superclass_of_class (class) == tree->class)
203    {
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;
209
210      while (list)
211        {
212          /* Class has been already inserted; do nothing just return
213             the tree.  */
214          if (((objc_class_tree *) list->head)->class == class)
215            {
216              DEBUG_PRINTF ("2. class %s was previously inserted\n",
217                            class->name);
218              return tree;
219            }
220          list = list->tail;
221        }
222
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;
229    }
230  else
231    {
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;
235
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;
241
242      for (; subclasses != NULL; subclasses = subclasses->tail)
243        {
244          Class aClass = ((objc_class_tree *) (subclasses->head))->class;
245
246          if (class_is_subclass_of_class (class, aClass))
247            {
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;
255            }
256        }
257
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.  */
261      {
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;
267      }
268    }
269}
270
271/* This function inserts `class' in the right tree hierarchy classes.  */
272
273static void
274objc_tree_insert_class (Class class)
275{
276  struct objc_list *list_node;
277  objc_class_tree *tree;
278
279  list_node = __objc_class_tree_list;
280  while (list_node)
281    {
282      tree = __objc_tree_insert_class (list_node->head, class);
283      if (tree)
284        {
285          list_node->head = tree;
286          break;
287        }
288      else
289        list_node = list_node->tail;
290    }
291
292  /* If the list was finished but the class hasn't been inserted,
293     insert it here.  */
294  if (! list_node)
295    {
296      __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
297      __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
298    }
299}
300
301/* Traverse tree in preorder. Used to send +load.  */
302
303static void
304objc_preorder_traverse (objc_class_tree *tree,
305                        int level,
306                        void (*function) (objc_class_tree *, int))
307{
308  struct objc_list *node;
309
310  (*function) (tree, level);
311  for (node = tree->subclasses; node; node = node->tail)
312    objc_preorder_traverse (node->head, level + 1, function);
313}
314
315/* Traverse tree in postorder. Used to destroy a tree.  */
316
317static void
318objc_postorder_traverse (objc_class_tree *tree,
319                         int level,
320                         void (*function) (objc_class_tree *, int))
321{
322  struct objc_list *node;
323
324  for (node = tree->subclasses; node; node = node->tail)
325    objc_postorder_traverse (node->head, level + 1, function);
326  (*function) (tree, level);
327}
328
329/* Used to print a tree class hierarchy.  */
330
331#ifdef DEBUG
332static void
333__objc_tree_print (objc_class_tree *tree, int level)
334{
335  int i;
336
337  for (i = 0; i < level; i++)
338    printf ("  ");
339  printf ("%s\n", tree->class->name);
340}
341#endif
342
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.  */
348
349static void
350__objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
351{
352  int i;
353
354  if (! method_list)
355    return;
356
357  /* First execute the `op' message in the following method lists */
358  __objc_send_message_in_list (method_list->method_next, class, op);
359
360  /* Search the method list.  */
361  for (i = 0; i < method_list->method_count; i++)
362    {
363      Method_t mth = &method_list->method_list[i];
364
365      if (mth->method_name && sel_eq (mth->method_name, op)
366          && ! hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
367        {
368          /* Add this method into the +load hash table */
369          hash_add (&__objc_load_methods, mth->method_imp, mth->method_imp);
370
371          DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
372
373          /* The method was found and wasn't previously executed.  */
374          (*mth->method_imp) ((id)class, mth->method_name);
375
376          break;
377        }
378    }
379}
380
381static void
382__objc_send_load (objc_class_tree *tree,
383                  int level __attribute__ ((__unused__)))
384{
385  static SEL load_sel = 0;
386  Class class = tree->class;
387  MethodList_t method_list = class->class_pointer->methods;
388
389  if (! load_sel)
390    load_sel = sel_register_name ("load");
391
392  __objc_send_message_in_list (method_list, class, load_sel);
393}
394
395static void
396__objc_destroy_class_tree_node (objc_class_tree *tree,
397                                int level __attribute__ ((__unused__)))
398{
399  objc_free (tree);
400}
401
402/* This is used to check if the relationship between two classes
403   before the runtime completely installs the classes.  */
404
405static BOOL
406class_is_subclass_of_class (Class class, Class superclass)
407{
408  for (; class != Nil;)
409    {
410      if (class == superclass)
411        return YES;
412      class = class_superclass_of_class (class);
413    }
414
415  return NO;
416}
417
418/* This list contains all the classes in the runtime system for whom
419   their superclasses are not yet known to the runtime.  */
420static struct objc_list *unresolved_classes = 0;
421
422/* Extern function used to reference the Object and NXConstantString
423   classes.  */
424
425extern void __objc_force_linking (void);
426
427void
428__objc_force_linking (void)
429{
430  extern void __objc_linking (void);
431  __objc_linking ();
432}
433
434/* Run through the statics list, removing modules as soon as all its
435   statics have been initialized.  */
436
437static void
438objc_init_statics (void)
439{
440  struct objc_list **cell = &uninitialized_statics;
441  struct objc_static_instances **statics_in_module;
442
443  objc_mutex_lock (__objc_runtime_mutex);
444
445  while (*cell)
446    {
447      int module_initialized = 1;
448
449      for (statics_in_module = (*cell)->head;
450           *statics_in_module; statics_in_module++)
451        {
452          struct objc_static_instances *statics = *statics_in_module;
453          Class class = objc_lookup_class (statics->class_name);
454
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)
462            {
463              id *inst;
464
465              for (inst = &statics->instances[0]; *inst; inst++)
466                {
467                  (*inst)->class_pointer = class;
468
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.  */
472
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?  */
477                }
478            }
479        }
480      if (module_initialized)
481        {
482          /* Remove this module from the uninitialized list.  */
483          struct objc_list *this = *cell;
484          *cell = this->tail;
485          objc_free (this);
486        }
487      else
488        cell = &(*cell)->tail;
489    }
490
491  objc_mutex_unlock (__objc_runtime_mutex);
492} /* objc_init_statics */
493
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.  */
498
499void
500__objc_exec_class (Module_t module)
501{
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;
505
506  static struct objc_list *unclaimed_categories = 0;
507
508  /* The symbol table (defined in objc-api.h) generated by gcc */
509  Symtab_t symtab = module->symtab;
510
511  /* The statics in this module */
512  struct objc_static_instances **statics
513    = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
514
515  /* Entry used to traverse hash lists */
516  struct objc_list **cell;
517
518  /* The table of selector references for this module */
519  SEL selectors = symtab->refs;
520
521  /* dummy counter */
522  int i;
523
524  DEBUG_PRINTF ("received module: %s\n", module->name);
525
526  /* check gcc version */
527  init_check_module_version (module);
528
529  /* On the first call of this routine, initialize some data structures.  */
530  if (! previous_constructors)
531    {
532        /* Initialize thread-safe system */
533      __objc_init_thread_system ();
534      __objc_runtime_threads_alive = 1;
535      __objc_runtime_mutex = objc_mutex_allocate ();
536
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;
544    }
545
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);
549
550  /* Replace referenced selectors from names to SEL's.  */
551  if (selectors)
552    {
553      for (i = 0; selectors[i].sel_id; ++i)
554        {
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);
563        }
564    }
565
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)
569    {
570      Class class = (Class) symtab->defs[i];
571      const char *superclass = (char *) class->super_class;
572
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);
577
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;
581
582      /* Store the class in the class table and assign class numbers.  */
583      __objc_add_class_to_hash (class);
584
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);
588
589      /* Install the fake dispatch tables */
590      __objc_install_premature_dtable (class);
591      __objc_install_premature_dtable (class->class_pointer);
592
593      /* Register the instance methods as class methods, this is
594         only done for root classes.  */
595      __objc_register_instance_methods_to_class (class);
596
597      if (class->protocols)
598        __objc_init_protocols (class->protocols);
599
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);
604   }
605
606  /* Process category information from the module.  */
607  for (i = 0; i < symtab->cat_def_cnt; ++i)
608    {
609      Category_t category = symtab->defs[i + symtab->cls_def_cnt];
610      Class class = objc_lookup_class (category->class_name);
611     
612      /* If the class for the category exists then append its methods.  */
613      if (class)
614        {
615
616          DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
617                        module->name,
618                        class->name);
619
620          /* Do instance methods.  */
621          if (category->instance_methods)
622            class_add_method_list (class, category->instance_methods);
623
624          /* Do class methods.  */
625          if (category->class_methods)
626            class_add_method_list ((Class) class->class_pointer,
627                                   category->class_methods);
628
629          if (category->protocols)
630            {
631              __objc_init_protocols (category->protocols);
632              __objc_class_add_protocols (class, category->protocols);
633            }
634
635          /* Register the instance methods as class methods, this is
636             only done for root classes.  */
637          __objc_register_instance_methods_to_class (class);
638        }
639      else
640        {
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);
644        }
645    }
646
647  if (statics)
648    uninitialized_statics = list_cons (statics, uninitialized_statics);
649  if (uninitialized_statics)
650    objc_init_statics ();
651
652  /* Scan the unclaimed category hash.  Attempt to attach any unclaimed
653     categories to objects.  */
654  for (cell = &unclaimed_categories; *cell; )
655    {
656      Category_t category = (*cell)->head;
657      Class class = objc_lookup_class (category->class_name);
658     
659      if (class)
660        {
661          DEBUG_PRINTF ("attaching stored categories to object: %s\n",
662                        class->name);
663         
664          list_remove_head (cell);
665         
666          if (category->instance_methods)
667            class_add_method_list (class, category->instance_methods);
668         
669          if (category->class_methods)
670            class_add_method_list ((Class) class->class_pointer,
671                                   category->class_methods);
672
673          if (category->protocols)
674            {
675              __objc_init_protocols (category->protocols);
676              __objc_class_add_protocols (class, category->protocols);
677            }
678
679          /* Register the instance methods as class methods, this is
680             only done for root classes.  */
681          __objc_register_instance_methods_to_class (class);
682        }
683      else
684        cell = &(*cell)->tail;
685    }
686 
687  if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
688    {
689      list_mapcar (unclaimed_proto_list,
690                   (void (*) (void *))__objc_init_protocols);
691      list_free (unclaimed_proto_list);
692      unclaimed_proto_list = 0;
693    }
694
695  objc_send_load ();
696
697  objc_mutex_unlock (__objc_runtime_mutex);
698}
699
700static void
701objc_send_load (void)
702{
703  if (! __objc_module_list)
704    return;
705 
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)
711    {
712      Class class = unresolved_classes->head;
713
714      while (objc_lookup_class ((char *) class->super_class))
715        {
716          list_remove_head (&unresolved_classes);
717          if (unresolved_classes)
718            class = unresolved_classes->head;
719          else
720            break;
721        }
722
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;
728    }
729
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;
736
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);
742
743  while (__objc_class_tree_list)
744    {
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);
754    }
755
756  list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
757  list_free (__objc_module_list);
758  __objc_module_list = NULL;
759}
760
761static void
762__objc_create_classes_tree (Module_t module)
763{
764  /* The runtime mutex is locked in this point */
765
766  Symtab_t symtab = module->symtab;
767  int i;
768
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++)
772    {
773      Class class = (Class) symtab->defs[i];
774
775      objc_tree_insert_class (class);
776    }
777}
778
779static void
780__objc_call_callback (Module_t module)
781{
782  /* The runtime mutex is locked in this point.  */
783
784  Symtab_t symtab = module->symtab;
785  int i;
786
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++)
790    {
791      Class class = (Class) symtab->defs[i];
792
793      /* Call the _objc_load_callback for this class.  */
794      if (_objc_load_callback)
795        _objc_load_callback (class, 0);
796    }
797
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++)
802    {
803      Category_t category = symtab->defs[i + symtab->cls_def_cnt];
804      Class class = objc_lookup_class (category->class_name);
805     
806      if (_objc_load_callback)
807        _objc_load_callback (class, category);
808    }
809}
810
811/* Sanity check the version of gcc used to compile `module'.  */
812
813static void
814init_check_module_version (Module_t module)
815{
816  if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
817    {
818      int code;
819
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;
826
827      objc_error (nil, code, "Module %s version %d doesn't match runtime %d\n",
828                  module->name, (int)module->version, OBJC_VERSION);
829    }
830}
831
832static void
833__objc_init_protocols (struct objc_protocol_list *protos)
834{
835  size_t i;
836  static Class proto_class = 0;
837
838  if (! protos)
839    return;
840
841  objc_mutex_lock (__objc_runtime_mutex);
842
843  if (! proto_class)
844    proto_class = objc_lookup_class ("Protocol");
845
846  if (! proto_class)
847    {
848      unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
849      objc_mutex_unlock (__objc_runtime_mutex);
850      return;
851    }
852
853#if 0
854  assert (protos->next == 0);   /* only single ones allowed */
855#endif
856
857  for (i = 0; i < protos->count; i++)
858    {
859      struct objc_protocol *aProto = protos->list[i];
860      if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
861        {
862          /* assign class pointer */
863          aProto->class_pointer = proto_class;
864
865          /* init super protocols */
866          __objc_init_protocols (aProto->protocol_list);
867        }
868      else if (protos->list[i]->class_pointer != proto_class)
869        {
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);
875        }
876    }
877
878  objc_mutex_unlock (__objc_runtime_mutex);
879}
880
881static void
882__objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
883{
884  /* Well...  */
885  if (! protos)
886    return;
887
888  /* Add it...  */
889  protos->next = class->protocols;
890  class->protocols = protos;
891}
Note: See TracBrowser for help on using the repository browser.