OSDN Git Service

b41ce95ea6dc45f9f8dbd8529b0cf56c824c6c39
[pf3gnuchains/gcc-fork.git] / gcc / objc / init.c
1 /* GNU Objective C Runtime initialization 
2    Copyright (C) 1993 Free Software Foundation, Inc.
3
4 Author: Kresten Krab Thorup
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, 675 Mass Ave, Cambridge, MA 02139, 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 6
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;
36
37 /* This list contains all proto_list's not yet assigned class links */
38 static struct objc_list* unclaimed_proto_list = 0;
39
40 /* Check compiler vs runtime version */
41 static void init_check_module_version(Module_t);
42
43 /* Assign isa links to protos */
44 static void __objc_init_protocols (struct objc_protocol_list* protos);
45
46 /* Add protocol to class */
47 static void __objc_class_add_protocols (Class*, struct objc_protocol_list*);
48
49 /* Is all categories/classes resolved? */
50 BOOL __objc_dangling_categories = NO;
51
52 extern SEL
53 __sel_register_typed_name (const char *name, const char *types, 
54                            struct objc_selector *orig);
55
56
57 /* This function is called by constructor functions generated for each
58    module compiled.  (_GLOBAL_$I$...) The purpose of this function is to
59    gather the module pointers so that they may be processed by the
60    initialization routines as soon as possible */
61
62 void
63 __objc_exec_class (Module_t module)
64 {
65   /* Has we processed any constructors previously?  This flag used to 
66      indicate that some global data structures need to be built.  */ 
67   static BOOL previous_constructors = 0;
68
69   static struct objc_list* unclaimed_categories = 0;
70
71   /* The symbol table (defined in objc.h) generated by gcc */
72   Symtab_t symtab = module->symtab;
73
74   /* Entry used to traverse hash lists */
75   struct objc_list** cell;
76
77   /* The table of selector references for this module */
78   SEL selectors = symtab->refs; 
79
80   /* dummy counter */
81   int i;
82
83   DEBUG_PRINTF ("received module: %s\n", module->name);
84   /* check gcc version */
85   init_check_module_version(module);
86
87   /* On the first call of this routine, initialize some data structures.  */
88   if (!previous_constructors)
89     {
90       __objc_init_selector_tables();
91       __objc_init_class_tables();
92       __objc_init_dispatch_tables();
93       previous_constructors = 1;
94     }
95
96   /* Save the module pointer for later processing. (not currently used) */
97   __objc_module_list = list_cons(module, __objc_module_list);
98
99   /* Replace referenced selectors from names to SEL's.  */
100   if (selectors)
101     {
102       for (i = 0; selectors[i].sel_id; ++i)
103         {
104           const char *name, *type;
105           name = (char*)selectors[i].sel_id;
106           type = (char*)selectors[i].sel_types;
107           __sel_register_typed_name (name, type, 
108                                      (struct objc_selector*)&(selectors[i]));
109         }
110     }
111
112   /* Parse the classes in the load module and gather selector information.  */
113   DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
114   for (i = 0; i < symtab->cls_def_cnt; ++i)
115     {
116       Class* class = (Class*) symtab->defs[i];
117
118       /* Make sure we have what we think.  */
119       assert (CLS_ISCLASS(class));
120       assert (CLS_ISMETA(class->class_pointer));
121       DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
122
123       /* Store the class in the class table and assign class numbers.  */
124       __objc_add_class_to_hash (class);
125
126       /* Register all of the selectors in the class and meta class.  */
127       __objc_register_selectors_from_class (class);
128       __objc_register_selectors_from_class ((Class*) class->class_pointer);
129
130       /* Install the fake dispatch tables */
131       __objc_install_premature_dtable(class);
132       __objc_install_premature_dtable(class->class_pointer);
133
134       if (class->protocols)
135         __objc_init_protocols (class->protocols);
136    }
137
138   /* Process category information from the module.  */
139   for (i = 0; i < symtab->cat_def_cnt; ++i)
140     {
141       Category_t category = symtab->defs[i + symtab->cls_def_cnt];
142       Class* class = objc_lookup_class (category->class_name);
143       
144       /* If the class for the category exists then append its methods.  */
145       if (class)
146         {
147
148           DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
149                         module->name,
150                         class->name);
151
152           /* Do instance methods.  */
153           if (category->instance_methods)
154             class_add_method_list (class, category->instance_methods);
155
156           /* Do class methods.  */
157           if (category->class_methods)
158             class_add_method_list ((Class*) class->class_pointer, 
159                                    category->class_methods);
160
161           if (category->protocols)
162             {
163               __objc_init_protocols (category->protocols);
164               __objc_class_add_protocols (class, category->protocols);
165             }
166
167         }
168       else
169         {
170           /* The object to which the category methods belong can't be found.
171              Save the information.  */
172           unclaimed_categories = list_cons(category, unclaimed_categories);
173         }
174     }
175
176   /* Scan the unclaimed category hash.  Attempt to attach any unclaimed
177      categories to objects.  */
178   for (cell = &unclaimed_categories;
179        *cell;
180        ({ if (*cell) cell = &(*cell)->tail; }))
181     {
182       Category_t category = (*cell)->head;
183       Class* class = objc_lookup_class (category->class_name);
184       
185       if (class)
186         {
187           DEBUG_PRINTF ("attaching stored categories to object: %s\n",
188                         class->name);
189           
190           list_remove_head (cell);
191           
192           if (category->instance_methods)
193             class_add_method_list (class, category->instance_methods);
194           
195           if (category->class_methods)
196             class_add_method_list ((Class*) class->class_pointer,
197                                    category->class_methods);
198           
199           if (category->protocols)
200             {
201               __objc_init_protocols (category->protocols);
202               __objc_class_add_protocols (class, category->protocols);
203             }
204           
205         }
206     }
207   
208   if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
209     {
210       list_mapcar (unclaimed_proto_list,(void(*)(void*))__objc_init_protocols);
211       list_free (unclaimed_proto_list);
212       unclaimed_proto_list = 0;
213     }
214
215 }
216
217 /* Sanity check the version of gcc used to compile `module'*/
218 static void init_check_module_version(Module_t module)
219 {
220   if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
221     {
222       fprintf (stderr, "Module %s version %d doesn't match runtime %d\n",
223                module->name, (int)module->version, OBJC_VERSION);
224       if(module->version > OBJC_VERSION)
225         fprintf (stderr, "Runtime (libobjc.a) is out of date\n");
226       else if (module->version < OBJC_VERSION)
227         fprintf (stderr, "Compiler (gcc) is out of date\n");
228       else
229         fprintf (stderr, "Objective C internal error -- bad Module size\n");
230       abort ();
231     }
232 }
233
234 static void
235 __objc_init_protocols (struct objc_protocol_list* protos)
236 {
237   int i;
238   static Class* proto_class = 0;
239
240   if (! protos)
241     return;
242
243   if (!proto_class)
244     proto_class = objc_lookup_class("Protocol");
245
246   if (!proto_class)
247     {
248       unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
249       return;
250     }
251
252   assert (protos->next == 0);   /* only single ones allowed */
253
254   for(i = 0; i < protos->count; i++)
255     {
256       struct objc_protocol* aProto = protos->list[i];
257       if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
258         {
259           /* assign class pointer */
260           aProto->class_pointer = proto_class;
261
262           /* init super protocols */
263           __objc_init_protocols (aProto->protocol_list);
264         }
265       else if (protos->list[i]->class_pointer != proto_class)
266         {
267           fprintf (stderr,
268                    "Version %d doesn't match runtime protocol version %d\n",
269                    (int)((char*)protos->list[i]->class_pointer-(char*)0),
270                    PROTOCOL_VERSION);
271           abort ();
272         }
273     }
274 }
275
276 static void __objc_class_add_protocols (Class* class,
277                                         struct objc_protocol_list* protos)
278 {
279   /* Well... */
280   if (! protos)
281     return;
282
283   /* Add it... */
284   protos->next = class->protocols;
285   class->protocols = protos;
286 }