]>
Commit | Line | Data |
---|---|---|
c72fc2d9 TW |
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) */ | |
a39d31bc | 31 | #define OBJC_VERSION 6 |
c72fc2d9 TW |
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 */ | |
d0b57512 | 47 | static void __objc_class_add_protocols (Class*, struct objc_protocol_list*); |
c72fc2d9 TW |
48 | |
49 | /* Is all categories/classes resolved? */ | |
50 | BOOL __objc_dangling_categories = NO; | |
51 | ||
a39d31bc KKT |
52 | extern SEL |
53 | __sel_register_typed_name (const char *name, const char *types, | |
54 | struct objc_selector *orig); | |
55 | ||
56 | ||
c72fc2d9 TW |
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 | ||
c72fc2d9 TW |
74 | /* Entry used to traverse hash lists */ |
75 | struct objc_list** cell; | |
76 | ||
77 | /* The table of selector references for this module */ | |
a39d31bc | 78 | SEL selectors = symtab->refs; |
c72fc2d9 TW |
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 | ||
a39d31bc KKT |
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 | ||
c72fc2d9 TW |
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 | { | |
d0b57512 | 116 | Class* class = (Class*) symtab->defs[i]; |
c72fc2d9 TW |
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); | |
d0b57512 | 128 | __objc_register_selectors_from_class ((Class*) class->class_pointer); |
c72fc2d9 TW |
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 | ||
c72fc2d9 TW |
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]; | |
d0b57512 | 142 | Class* class = objc_lookup_class (category->class_name); |
c72fc2d9 TW |
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) | |
d0b57512 | 158 | class_add_method_list ((Class*) class->class_pointer, |
c72fc2d9 TW |
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; | |
a39d31bc | 180 | ({ if (*cell) cell = &(*cell)->tail; })) |
c72fc2d9 TW |
181 | { |
182 | Category_t category = (*cell)->head; | |
d0b57512 | 183 | Class* class = objc_lookup_class (category->class_name); |
c72fc2d9 TW |
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) | |
d0b57512 | 196 | class_add_method_list ((Class*) class->class_pointer, |
c72fc2d9 TW |
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", | |
a39d31bc | 223 | module->name, (int)module->version, OBJC_VERSION); |
c72fc2d9 TW |
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; | |
eba92c95 | 238 | static Class* proto_class = 0; |
c72fc2d9 TW |
239 | |
240 | if (! protos) | |
241 | return; | |
242 | ||
eba92c95 RS |
243 | if (!proto_class) |
244 | proto_class = objc_lookup_class("Protocol"); | |
c72fc2d9 | 245 | |
eba92c95 | 246 | if (!proto_class) |
c72fc2d9 TW |
247 | { |
248 | unclaimed_proto_list = list_cons (protos, unclaimed_proto_list); | |
249 | return; | |
250 | } | |
251 | ||
2acb0388 | 252 | #if 0 |
c72fc2d9 | 253 | assert (protos->next == 0); /* only single ones allowed */ |
2acb0388 | 254 | #endif |
c72fc2d9 TW |
255 | |
256 | for(i = 0; i < protos->count; i++) | |
257 | { | |
eba92c95 RS |
258 | struct objc_protocol* aProto = protos->list[i]; |
259 | if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION) | |
260 | { | |
261 | /* assign class pointer */ | |
262 | aProto->class_pointer = proto_class; | |
263 | ||
264 | /* init super protocols */ | |
265 | __objc_init_protocols (aProto->protocol_list); | |
266 | } | |
267 | else if (protos->list[i]->class_pointer != proto_class) | |
c72fc2d9 TW |
268 | { |
269 | fprintf (stderr, | |
0046ffa3 | 270 | "Version %d doesn't match runtime protocol version %d\n", |
a39d31bc | 271 | (int)((char*)protos->list[i]->class_pointer-(char*)0), |
c72fc2d9 TW |
272 | PROTOCOL_VERSION); |
273 | abort (); | |
274 | } | |
275 | } | |
276 | } | |
277 | ||
d0b57512 | 278 | static void __objc_class_add_protocols (Class* class, |
c72fc2d9 TW |
279 | struct objc_protocol_list* protos) |
280 | { | |
c72fc2d9 TW |
281 | /* Well... */ |
282 | if (! protos) | |
283 | return; | |
284 | ||
285 | /* Add it... */ | |
286 | protos->next = class->protocols; | |
287 | class->protocols = protos; | |
288 | } |