source: trunk/third/gcc/objc/init.c @ 8834

Revision 8834, 11.1 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8833, which included commits to RCS files with non-trunk default branches.
Line 
1/* GNU Objective C Runtime initialization
2   Copyright (C) 1993, 1995 Free Software Foundation, Inc.
3   Contributed by Kresten Krab Thorup
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify it under the
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 2, or (at your option) any later version.
10
11GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14details.
15
16You should have received a copy of the GNU General Public License along with
17GNU CC; see the file COPYING.  If not, write to the Free Software
18Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20/* As a special exception, if you link this library with files compiled with
21   GCC to produce an executable, this does not cause the resulting executable
22   to be covered by the GNU General Public License. This exception does not
23   however invalidate any other reasons why the executable file might be
24   covered by the GNU General Public License.  */
25
26#include "runtime.h"
27
28/* The version number of this runtime.  This must match the number
29   defined in gcc (objc-act.c) */
30#define OBJC_VERSION 7
31#define PROTOCOL_VERSION 2
32
33/* This list contains all modules currently loaded into the runtime */
34static struct objc_list* __objc_module_list = 0;
35
36/* This list contains all proto_list's not yet assigned class links */
37static struct objc_list* unclaimed_proto_list = 0;
38
39/* List of unresolved static instances.  */
40static struct objc_list *uninitialized_statics;
41
42/* Check compiler vs runtime version */
43static void init_check_module_version (Module_t);
44
45/* Assign isa links to protos */
46static void __objc_init_protocols (struct objc_protocol_list* protos);
47
48/* Add protocol to class */
49static void __objc_class_add_protocols (Class, struct objc_protocol_list*);
50
51/* This is a hook which is called by __objc_exec_class every time a class
52   or a category is loaded into the runtime.  This may e.g. help a
53   dynamic loader determine the classes that have been loaded when
54   an object file is dynamically linked in */
55void (*_objc_load_callback)(Class class, Category* category) = 0;
56
57/* Is all categories/classes resolved? */
58BOOL __objc_dangling_categories = NO;
59
60extern SEL
61__sel_register_typed_name (const char *name, const char *types,
62                           struct objc_selector *orig);
63
64/* Run through the statics list, removing modules as soon as all its statics
65   have been initialized.  */
66static void
67objc_init_statics ()
68{
69  struct objc_list **cell = &uninitialized_statics;
70  struct objc_static_instances **statics_in_module;
71
72  while (*cell)
73    {
74      int module_initialized = 1;
75
76      for (statics_in_module = (*cell)->head;
77           *statics_in_module; statics_in_module++)
78        {
79          struct objc_static_instances *statics = *statics_in_module;
80          Class class = objc_lookup_class (statics->class_name);
81
82          if (!class)
83            module_initialized = 0;
84          /* Actually, the static's class_pointer will be NULL when we
85             haven't been here before.  However, the comparison is to be
86             reminded of taking into account class posing and to think about
87             possible semantics...  */
88          else if (class != statics->instances[0]->class_pointer)
89            {
90              id *inst;
91
92              for (inst = &statics->instances[0]; *inst; inst++)
93                {
94                  (*inst)->class_pointer = class;
95
96                  /* ??? Make sure the object will not be freed.  With
97                     refcounting, invoke `-retain'.  Without refcounting, do
98                     nothing and hope that `-free' will never be invoked.  */
99
100                  /* ??? Send the object an `-initStatic' or something to
101                     that effect now or later on?  What are the semantics of
102                     statically allocated instances, besides the trivial
103                     NXConstantString, anyway?  */
104                }
105            }
106        }
107      if (module_initialized)
108        {
109          /* Remove this module from the uninitialized list.  */
110          struct objc_list *this = *cell;
111          *cell = this->tail;
112          free (this);
113        }
114      else
115        cell = &(*cell)->tail;
116    }
117} /* objc_init_statics */
118
119/* This function is called by constructor functions generated for each
120   module compiled.  (_GLOBAL_$I$...) The purpose of this function is to
121   gather the module pointers so that they may be processed by the
122   initialization routines as soon as possible */
123
124void
125__objc_exec_class (Module_t module)
126{
127  /* Have we processed any constructors previously?  This flag is used to
128     indicate that some global data structures need to be built.  */
129  static BOOL previous_constructors = 0;
130
131  static struct objc_list* unclaimed_categories = 0;
132
133  /* The symbol table (defined in objc-api.h) generated by gcc */
134  Symtab_t symtab = module->symtab;
135
136  /* Entry used to traverse hash lists */
137  struct objc_list** cell;
138
139  /* The table of selector references for this module */
140  SEL selectors = symtab->refs;
141
142  /* dummy counter */
143  int i;
144
145  DEBUG_PRINTF ("received module: %s\n", module->name);
146
147  /* check gcc version */
148  init_check_module_version(module);
149
150  /* On the first call of this routine, initialize some data structures.  */
151  if (!previous_constructors)
152    {
153      __objc_init_selector_tables();
154      __objc_init_class_tables();
155      __objc_init_dispatch_tables();
156      previous_constructors = 1;
157    }
158
159  /* Save the module pointer for later processing. (not currently used) */
160  __objc_module_list = list_cons(module, __objc_module_list);
161
162  /* Replace referenced selectors from names to SEL's.  */
163  if (selectors)
164    {
165      for (i = 0; selectors[i].sel_id; ++i)
166        {
167          const char *name, *type;
168          name = (char*)selectors[i].sel_id;
169          type = (char*)selectors[i].sel_types;
170          __sel_register_typed_name (name, type,
171                                     (struct objc_selector*)&(selectors[i]));
172        }
173    }
174
175  /* Parse the classes in the load module and gather selector information.  */
176  DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
177  for (i = 0; i < symtab->cls_def_cnt; ++i)
178    {
179      Class class = (Class) symtab->defs[i];
180
181      /* Make sure we have what we think.  */
182      assert (CLS_ISCLASS(class));
183      assert (CLS_ISMETA(class->class_pointer));
184      DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
185
186      /* Store the class in the class table and assign class numbers.  */
187      __objc_add_class_to_hash (class);
188
189      /* Register all of the selectors in the class and meta class.  */
190      __objc_register_selectors_from_class (class);
191      __objc_register_selectors_from_class ((Class) class->class_pointer);
192
193      /* Install the fake dispatch tables */
194      __objc_install_premature_dtable(class);
195      __objc_install_premature_dtable(class->class_pointer);
196
197      if (class->protocols)
198        __objc_init_protocols (class->protocols);
199
200      if (_objc_load_callback)
201        _objc_load_callback(class, 0);
202   }
203
204  /* Process category information from the module.  */
205  for (i = 0; i < symtab->cat_def_cnt; ++i)
206    {
207      Category_t category = symtab->defs[i + symtab->cls_def_cnt];
208      Class class = objc_lookup_class (category->class_name);
209     
210      /* If the class for the category exists then append its methods.  */
211      if (class)
212        {
213
214          DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
215                        module->name,
216                        class->name);
217
218          /* Do instance methods.  */
219          if (category->instance_methods)
220            class_add_method_list (class, category->instance_methods);
221
222          /* Do class methods.  */
223          if (category->class_methods)
224            class_add_method_list ((Class) class->class_pointer,
225                                   category->class_methods);
226
227          if (category->protocols)
228            {
229              __objc_init_protocols (category->protocols);
230              __objc_class_add_protocols (class, category->protocols);
231            }
232
233          if (_objc_load_callback)
234            _objc_load_callback(class, category);
235        }
236      else
237        {
238          /* The object to which the category methods belong can't be found.
239             Save the information.  */
240          unclaimed_categories = list_cons(category, unclaimed_categories);
241        }
242    }
243
244  if (module->statics)
245    uninitialized_statics = list_cons (module->statics, uninitialized_statics);
246  if (uninitialized_statics)
247    objc_init_statics ();
248
249  /* Scan the unclaimed category hash.  Attempt to attach any unclaimed
250     categories to objects.  */
251  for (cell = &unclaimed_categories;
252       *cell;
253       ({ if (*cell) cell = &(*cell)->tail; }))
254    {
255      Category_t category = (*cell)->head;
256      Class class = objc_lookup_class (category->class_name);
257     
258      if (class)
259        {
260          DEBUG_PRINTF ("attaching stored categories to object: %s\n",
261                        class->name);
262         
263          list_remove_head (cell);
264         
265          if (category->instance_methods)
266            class_add_method_list (class, category->instance_methods);
267         
268          if (category->class_methods)
269            class_add_method_list ((Class) class->class_pointer,
270                                   category->class_methods);
271         
272          if (category->protocols)
273            {
274              __objc_init_protocols (category->protocols);
275              __objc_class_add_protocols (class, category->protocols);
276            }
277         
278          if (_objc_load_callback)
279            _objc_load_callback(class, category);
280        }
281    }
282 
283  if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
284    {
285      list_mapcar (unclaimed_proto_list,(void(*)(void*))__objc_init_protocols);
286      list_free (unclaimed_proto_list);
287      unclaimed_proto_list = 0;
288    }
289
290}
291
292/* Sanity check the version of gcc used to compile `module'*/
293static void init_check_module_version(Module_t module)
294{
295  if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
296    {
297      fprintf (stderr, "Module %s version %d doesn't match runtime %d\n",
298               module->name, (int)module->version, OBJC_VERSION);
299      if(module->version > OBJC_VERSION)
300        fprintf (stderr, "Runtime (libobjc.a) is out of date\n");
301      else if (module->version < OBJC_VERSION)
302        fprintf (stderr, "Compiler (gcc) is out of date\n");
303      else
304        fprintf (stderr, "Objective C internal error -- bad Module size\n");
305      abort ();
306    }
307}
308
309static void
310__objc_init_protocols (struct objc_protocol_list* protos)
311{
312  int i;
313  static Class proto_class = 0;
314
315  if (! protos)
316    return;
317
318  if (!proto_class)
319    proto_class = objc_lookup_class("Protocol");
320
321  if (!proto_class)
322    {
323      unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
324      return;
325    }
326
327#if 0
328  assert (protos->next == 0);   /* only single ones allowed */
329#endif
330
331  for(i = 0; i < protos->count; i++)
332    {
333      struct objc_protocol* aProto = protos->list[i];
334      if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
335        {
336          /* assign class pointer */
337          aProto->class_pointer = proto_class;
338
339          /* init super protocols */
340          __objc_init_protocols (aProto->protocol_list);
341        }
342      else if (protos->list[i]->class_pointer != proto_class)
343        {
344          fprintf (stderr,
345                   "Version %d doesn't match runtime protocol version %d\n",
346                   (int)((char*)protos->list[i]->class_pointer-(char*)0),
347                   PROTOCOL_VERSION);
348          abort ();
349        }
350    }
351}
352
353static void __objc_class_add_protocols (Class class,
354                                        struct objc_protocol_list* protos)
355{
356  /* Well... */
357  if (! protos)
358    return;
359
360  /* Add it... */
361  protos->next = class->protocols;
362  class->protocols = protos;
363}
Note: See TracBrowser for help on using the repository browser.