OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libobjc/] [init.c] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* 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 GCC.
7
 
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.
11
 
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.
16
 
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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "objc/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
/* 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
*/
123
static 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
 
152
static objc_class_tree *
153
create_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
 
188
static 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
 
273
static void
274
objc_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
 
303
static void
304
objc_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
 
317
static void
318
objc_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
332
static 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
 
349
static 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
          && ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
367
        {
368
          /* Add this method into the +load hash table */
369
          objc_hash_add (&__objc_load_methods,
370
                         mth->method_imp,
371
                         mth->method_imp);
372
 
373
          DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
374
 
375
          /* The method was found and wasn't previously executed.  */
376
          (*mth->method_imp) ((id)class, mth->method_name);
377
 
378
          break;
379
        }
380
    }
381
}
382
 
383
static void
384
__objc_send_load (objc_class_tree *tree,
385
                  int level __attribute__ ((__unused__)))
386
{
387
  static SEL load_sel = 0;
388
  Class class = tree->class;
389
  MethodList_t method_list = class->class_pointer->methods;
390
 
391
  if (! load_sel)
392
    load_sel = sel_register_name ("load");
393
 
394
  __objc_send_message_in_list (method_list, class, load_sel);
395
}
396
 
397
static void
398
__objc_destroy_class_tree_node (objc_class_tree *tree,
399
                                int level __attribute__ ((__unused__)))
400
{
401
  objc_free (tree);
402
}
403
 
404
/* This is used to check if the relationship between two classes
405
   before the runtime completely installs the classes.  */
406
 
407
static BOOL
408
class_is_subclass_of_class (Class class, Class superclass)
409
{
410
  for (; class != Nil;)
411
    {
412
      if (class == superclass)
413
        return YES;
414
      class = class_superclass_of_class (class);
415
    }
416
 
417
  return NO;
418
}
419
 
420
/* This list contains all the classes in the runtime system for whom
421
   their superclasses are not yet known to the runtime.  */
422
static struct objc_list *unresolved_classes = 0;
423
 
424
/* Extern function used to reference the Object and NXConstantString
425
   classes.  */
426
 
427
extern void __objc_force_linking (void);
428
 
429
void
430
__objc_force_linking (void)
431
{
432
  extern void __objc_linking (void);
433
  __objc_linking ();
434
}
435
 
436
/* Run through the statics list, removing modules as soon as all its
437
   statics have been initialized.  */
438
 
439
static void
440
objc_init_statics (void)
441
{
442
  struct objc_list **cell = &uninitialized_statics;
443
  struct objc_static_instances **statics_in_module;
444
 
445
  objc_mutex_lock (__objc_runtime_mutex);
446
 
447
  while (*cell)
448
    {
449
      int module_initialized = 1;
450
 
451
      for (statics_in_module = (*cell)->head;
452
           *statics_in_module; statics_in_module++)
453
        {
454
          struct objc_static_instances *statics = *statics_in_module;
455
          Class class = objc_lookup_class (statics->class_name);
456
 
457
          if (! class)
458
            module_initialized = 0;
459
          /* Actually, the static's class_pointer will be NULL when we
460
             haven't been here before.  However, the comparison is to be
461
             reminded of taking into account class posing and to think about
462
             possible semantics...  */
463
          else if (class != statics->instances[0]->class_pointer)
464
            {
465
              id *inst;
466
 
467
              for (inst = &statics->instances[0]; *inst; inst++)
468
                {
469
                  (*inst)->class_pointer = class;
470
 
471
                  /* ??? Make sure the object will not be freed.  With
472
                     refcounting, invoke `-retain'.  Without refcounting, do
473
                     nothing and hope that `-free' will never be invoked.  */
474
 
475
                  /* ??? Send the object an `-initStatic' or something to
476
                     that effect now or later on?  What are the semantics of
477
                     statically allocated instances, besides the trivial
478
                     NXConstantString, anyway?  */
479
                }
480
            }
481
        }
482
      if (module_initialized)
483
        {
484
          /* Remove this module from the uninitialized list.  */
485
          struct objc_list *this = *cell;
486
          *cell = this->tail;
487
          objc_free (this);
488
        }
489
      else
490
        cell = &(*cell)->tail;
491
    }
492
 
493
  objc_mutex_unlock (__objc_runtime_mutex);
494
} /* objc_init_statics */
495
 
496
/* This function is called by constructor functions generated for each
497
   module compiled.  (_GLOBAL_$I$...) The purpose of this function is
498
   to gather the module pointers so that they may be processed by the
499
   initialization routines as soon as possible.  */
500
 
501
void
502
__objc_exec_class (Module_t module)
503
{
504
  /* Have we processed any constructors previously?  This flag is used to
505
     indicate that some global data structures need to be built.  */
506
  static BOOL previous_constructors = 0;
507
 
508
  static struct objc_list *unclaimed_categories = 0;
509
 
510
  /* The symbol table (defined in objc-api.h) generated by gcc */
511
  Symtab_t symtab = module->symtab;
512
 
513
  /* The statics in this module */
514
  struct objc_static_instances **statics
515
    = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
516
 
517
  /* Entry used to traverse hash lists */
518
  struct objc_list **cell;
519
 
520
  /* The table of selector references for this module */
521
  SEL selectors = symtab->refs;
522
 
523
  /* dummy counter */
524
  int i;
525
 
526
  DEBUG_PRINTF ("received module: %s\n", module->name);
527
 
528
  /* check gcc version */
529
  init_check_module_version (module);
530
 
531
  /* On the first call of this routine, initialize some data structures.  */
532
  if (! previous_constructors)
533
    {
534
        /* Initialize thread-safe system */
535
      __objc_init_thread_system ();
536
      __objc_runtime_threads_alive = 1;
537
      __objc_runtime_mutex = objc_mutex_allocate ();
538
 
539
      __objc_init_selector_tables ();
540
      __objc_init_class_tables ();
541
      __objc_init_dispatch_tables ();
542
      __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
543
      __objc_load_methods = objc_hash_new (128,
544
                                           (hash_func_type)objc_hash_ptr,
545
                                           objc_compare_ptrs);
546
      previous_constructors = 1;
547
    }
548
 
549
  /* Save the module pointer for later processing. (not currently used) */
550
  objc_mutex_lock (__objc_runtime_mutex);
551
  __objc_module_list = list_cons (module, __objc_module_list);
552
 
553
  /* Replace referenced selectors from names to SEL's.  */
554
  if (selectors)
555
    {
556
      for (i = 0; selectors[i].sel_id; ++i)
557
        {
558
          const char *name, *type;
559
          name = (char *) selectors[i].sel_id;
560
          type = (char *) selectors[i].sel_types;
561
          /* Constructors are constant static data so we can safely store
562
             pointers to them in the runtime structures. is_const == YES */
563
          __sel_register_typed_name (name, type,
564
                                     (struct objc_selector *) &(selectors[i]),
565
                                     YES);
566
        }
567
    }
568
 
569
  /* Parse the classes in the load module and gather selector information.  */
570
  DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
571
  for (i = 0; i < symtab->cls_def_cnt; ++i)
572
    {
573
      Class class = (Class) symtab->defs[i];
574
      const char *superclass = (char *) class->super_class;
575
 
576
      /* Make sure we have what we think.  */
577
      assert (CLS_ISCLASS (class));
578
      assert (CLS_ISMETA (class->class_pointer));
579
      DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
580
 
581
      /* Initialize the subclass list to be NULL.
582
         In some cases it isn't and this crashes the program.  */
583
      class->subclass_list = NULL;
584
 
585
      /* Store the class in the class table and assign class numbers.  */
586
      __objc_add_class_to_hash (class);
587
 
588
      /* Register all of the selectors in the class and meta class.  */
589
      __objc_register_selectors_from_class (class);
590
      __objc_register_selectors_from_class ((Class) class->class_pointer);
591
 
592
      /* Install the fake dispatch tables */
593
      __objc_install_premature_dtable (class);
594
      __objc_install_premature_dtable (class->class_pointer);
595
 
596
      /* Register the instance methods as class methods, this is
597
         only done for root classes.  */
598
      __objc_register_instance_methods_to_class (class);
599
 
600
      if (class->protocols)
601
        __objc_init_protocols (class->protocols);
602
 
603
      /* Check to see if the superclass is known in this point. If it's not
604
         add the class to the unresolved_classes list.  */
605
      if (superclass && ! objc_lookup_class (superclass))
606
        unresolved_classes = list_cons (class, unresolved_classes);
607
   }
608
 
609
  /* Process category information from the module.  */
610
  for (i = 0; i < symtab->cat_def_cnt; ++i)
611
    {
612
      Category_t category = symtab->defs[i + symtab->cls_def_cnt];
613
      Class class = objc_lookup_class (category->class_name);
614
 
615
      /* If the class for the category exists then append its methods.  */
616
      if (class)
617
        {
618
 
619
          DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
620
                        module->name,
621
                        class->name);
622
 
623
          /* Do instance methods.  */
624
          if (category->instance_methods)
625
            class_add_method_list (class, category->instance_methods);
626
 
627
          /* Do class methods.  */
628
          if (category->class_methods)
629
            class_add_method_list ((Class) class->class_pointer,
630
                                   category->class_methods);
631
 
632
          if (category->protocols)
633
            {
634
              __objc_init_protocols (category->protocols);
635
              __objc_class_add_protocols (class, category->protocols);
636
            }
637
 
638
          /* Register the instance methods as class methods, this is
639
             only done for root classes.  */
640
          __objc_register_instance_methods_to_class (class);
641
        }
642
      else
643
        {
644
          /* The object to which the category methods belong can't be found.
645
             Save the information.  */
646
          unclaimed_categories = list_cons (category, unclaimed_categories);
647
        }
648
    }
649
 
650
  if (statics)
651
    uninitialized_statics = list_cons (statics, uninitialized_statics);
652
  if (uninitialized_statics)
653
    objc_init_statics ();
654
 
655
  /* Scan the unclaimed category hash.  Attempt to attach any unclaimed
656
     categories to objects.  */
657
  for (cell = &unclaimed_categories; *cell; )
658
    {
659
      Category_t category = (*cell)->head;
660
      Class class = objc_lookup_class (category->class_name);
661
 
662
      if (class)
663
        {
664
          DEBUG_PRINTF ("attaching stored categories to object: %s\n",
665
                        class->name);
666
 
667
          list_remove_head (cell);
668
 
669
          if (category->instance_methods)
670
            class_add_method_list (class, category->instance_methods);
671
 
672
          if (category->class_methods)
673
            class_add_method_list ((Class) class->class_pointer,
674
                                   category->class_methods);
675
 
676
          if (category->protocols)
677
            {
678
              __objc_init_protocols (category->protocols);
679
              __objc_class_add_protocols (class, category->protocols);
680
            }
681
 
682
          /* Register the instance methods as class methods, this is
683
             only done for root classes.  */
684
          __objc_register_instance_methods_to_class (class);
685
        }
686
      else
687
        cell = &(*cell)->tail;
688
    }
689
 
690
  if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
691
    {
692
      list_mapcar (unclaimed_proto_list,
693
                   (void (*) (void *))__objc_init_protocols);
694
      list_free (unclaimed_proto_list);
695
      unclaimed_proto_list = 0;
696
    }
697
 
698
  objc_send_load ();
699
 
700
  objc_mutex_unlock (__objc_runtime_mutex);
701
}
702
 
703
static void
704
objc_send_load (void)
705
{
706
  if (! __objc_module_list)
707
    return;
708
 
709
  /* Try to find out if all the classes loaded so far also have their
710
     superclasses known to the runtime. We suppose that the objects
711
     that are allocated in the +load method are in general of a class
712
     declared in the same module.  */
713
  if (unresolved_classes)
714
    {
715
      Class class = unresolved_classes->head;
716
 
717
      while (objc_lookup_class ((char *) class->super_class))
718
        {
719
          list_remove_head (&unresolved_classes);
720
          if (unresolved_classes)
721
            class = unresolved_classes->head;
722
          else
723
            break;
724
        }
725
 
726
      /* If we still have classes for whom we don't have yet their
727
         super classes known to the runtime we don't send the +load
728
         messages.  */
729
      if (unresolved_classes)
730
        return;
731
    }
732
 
733
  /* Special check to allow creating and sending messages to constant
734
     strings in +load methods. If these classes are not yet known,
735
     even if all the other classes are known, delay sending of +load.  */
736
  if (! objc_lookup_class ("NXConstantString") ||
737
      ! objc_lookup_class ("Object"))
738
    return;
739
 
740
  /* Iterate over all modules in the __objc_module_list and call on
741
     them the __objc_create_classes_tree function. This function
742
     creates a tree of classes that resembles the class hierarchy.  */
743
  list_mapcar (__objc_module_list,
744
               (void (*) (void *)) __objc_create_classes_tree);
745
 
746
  while (__objc_class_tree_list)
747
    {
748
#ifdef DEBUG
749
      objc_preorder_traverse (__objc_class_tree_list->head,
750
                              0, __objc_tree_print);
751
#endif
752
      objc_preorder_traverse (__objc_class_tree_list->head,
753
                              0, __objc_send_load);
754
      objc_postorder_traverse (__objc_class_tree_list->head,
755
                              0, __objc_destroy_class_tree_node);
756
      list_remove_head (&__objc_class_tree_list);
757
    }
758
 
759
  list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
760
  list_free (__objc_module_list);
761
  __objc_module_list = NULL;
762
}
763
 
764
static void
765
__objc_create_classes_tree (Module_t module)
766
{
767
  /* The runtime mutex is locked in this point */
768
 
769
  Symtab_t symtab = module->symtab;
770
  int i;
771
 
772
  /* Iterate thru classes defined in this module and insert them in
773
     the classes tree hierarchy.  */
774
  for (i = 0; i < symtab->cls_def_cnt; i++)
775
    {
776
      Class class = (Class) symtab->defs[i];
777
 
778
      objc_tree_insert_class (class);
779
    }
780
}
781
 
782
static void
783
__objc_call_callback (Module_t module)
784
{
785
  /* The runtime mutex is locked in this point.  */
786
 
787
  Symtab_t symtab = module->symtab;
788
  int i;
789
 
790
  /* Iterate thru classes defined in this module and call the callback
791
     for each one.  */
792
  for (i = 0; i < symtab->cls_def_cnt; i++)
793
    {
794
      Class class = (Class) symtab->defs[i];
795
 
796
      /* Call the _objc_load_callback for this class.  */
797
      if (_objc_load_callback)
798
        _objc_load_callback (class, 0);
799
    }
800
 
801
  /* Call the _objc_load_callback for categories. Don't register the
802
     instance methods as class methods for categories to root classes
803
     since they were already added in the class.  */
804
  for (i = 0; i < symtab->cat_def_cnt; i++)
805
    {
806
      Category_t category = symtab->defs[i + symtab->cls_def_cnt];
807
      Class class = objc_lookup_class (category->class_name);
808
 
809
      if (_objc_load_callback)
810
        _objc_load_callback (class, category);
811
    }
812
}
813
 
814
/* Sanity check the version of gcc used to compile `module'.  */
815
 
816
static void
817
init_check_module_version (Module_t module)
818
{
819
  if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
820
    {
821
      int code;
822
 
823
      if (module->version > OBJC_VERSION)
824
        code = OBJC_ERR_OBJC_VERSION;
825
      else if (module->version < OBJC_VERSION)
826
        code = OBJC_ERR_GCC_VERSION;
827
      else
828
        code = OBJC_ERR_MODULE_SIZE;
829
 
830
      objc_error (nil, code, "Module %s version %d doesn't match runtime %d\n",
831
                  module->name, (int)module->version, OBJC_VERSION);
832
    }
833
}
834
 
835
static void
836
__objc_init_protocols (struct objc_protocol_list *protos)
837
{
838
  size_t i;
839
  static Class proto_class = 0;
840
 
841
  if (! protos)
842
    return;
843
 
844
  objc_mutex_lock (__objc_runtime_mutex);
845
 
846
  if (! proto_class)
847
    proto_class = objc_lookup_class ("Protocol");
848
 
849
  if (! proto_class)
850
    {
851
      unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
852
      objc_mutex_unlock (__objc_runtime_mutex);
853
      return;
854
    }
855
 
856
#if 0
857
  assert (protos->next == 0);    /* only single ones allowed */
858
#endif
859
 
860
  for (i = 0; i < protos->count; i++)
861
    {
862
      struct objc_protocol *aProto = protos->list[i];
863
      if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
864
        {
865
          /* assign class pointer */
866
          aProto->class_pointer = proto_class;
867
 
868
          /* init super protocols */
869
          __objc_init_protocols (aProto->protocol_list);
870
        }
871
      else if (protos->list[i]->class_pointer != proto_class)
872
        {
873
          objc_error (nil, OBJC_ERR_PROTOCOL_VERSION,
874
                     "Version %d doesn't match runtime protocol version %d\n",
875
                     (int) ((char *) protos->list[i]->class_pointer
876
                            - (char *) 0),
877
                     PROTOCOL_VERSION);
878
        }
879
    }
880
 
881
  objc_mutex_unlock (__objc_runtime_mutex);
882
}
883
 
884
static void
885
__objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
886
{
887
  /* Well...  */
888
  if (! protos)
889
    return;
890
 
891
  /* Add it...  */
892
  protos->next = class->protocols;
893
  class->protocols = protos;
894
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.