Mercurial > hg > CbC > CbC_gcc
comparison libobjc/ivars.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* GNU Objective C Runtime ivar related functions. | |
2 Copyright (C) 2010-2017 Free Software Foundation, Inc. | |
3 Contributed by Nicola Pero | |
4 | |
5 This file is part of GCC. | |
6 | |
7 GCC is free software; you can redistribute it and/or modify it under the | |
8 terms of the GNU General Public License as published by the Free Software | |
9 Foundation; either version 3, or (at your option) any later version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
14 details. | |
15 | |
16 Under Section 7 of GPL version 3, you are granted additional | |
17 permissions described in the GCC Runtime Library Exception, version | |
18 3.1, as published by the Free Software Foundation. | |
19 | |
20 You should have received a copy of the GNU General Public License and | |
21 a copy of the GCC Runtime Library Exception along with this program; | |
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 <http://www.gnu.org/licenses/>. */ | |
24 | |
25 #include "objc-private/common.h" | |
26 #include "objc/runtime.h" | |
27 #include "objc-private/module-abi-8.h" /* For runtime structures */ | |
28 #include "objc/thr.h" | |
29 #include "objc-private/runtime.h" /* the kitchen sink */ | |
30 #include <string.h> /* For strcmp. */ | |
31 #include <stdlib.h> /* For malloc. */ | |
32 | |
33 struct objc_ivar * | |
34 class_getInstanceVariable (Class class_, const char *name) | |
35 { | |
36 if (class_ != Nil && name != NULL && ! CLS_IS_IN_CONSTRUCTION (class_)) | |
37 { | |
38 while (class_ != Nil) | |
39 { | |
40 struct objc_ivar_list *ivars = class_->ivars; | |
41 if (ivars != NULL) | |
42 { | |
43 int i; | |
44 | |
45 for (i = 0; i < ivars->ivar_count; i++) | |
46 { | |
47 struct objc_ivar *ivar = &(ivars->ivar_list[i]); | |
48 | |
49 if (!strcmp (ivar->ivar_name, name)) | |
50 return ivar; | |
51 } | |
52 } | |
53 class_ = class_getSuperclass (class_); | |
54 } | |
55 } | |
56 return NULL; | |
57 } | |
58 | |
59 struct objc_ivar * | |
60 class_getClassVariable (Class class_, const char *name) | |
61 { | |
62 if (class_ == Nil) | |
63 return NULL; | |
64 | |
65 /* Logically, since a class is an instance of its meta-class, and | |
66 since its class methods are the instance methods of the | |
67 meta-class, class variables should be instance variables of the | |
68 meta-class. That is different from the normal use of having | |
69 'static' variables in the class implementation file, because | |
70 every class would have its own variables. | |
71 | |
72 Anyway, it is all speculative at this stage, but if we get class | |
73 variables in Objective-C, it is conceivable that this | |
74 implementation should work. */ | |
75 return class_getInstanceVariable (class_->class_pointer, name); | |
76 } | |
77 | |
78 void * | |
79 object_getIndexedIvars (id object) | |
80 { | |
81 if (object == nil) | |
82 return NULL; | |
83 else | |
84 return (void *)(((char *)object) | |
85 + object->class_pointer->instance_size); | |
86 } | |
87 | |
88 struct objc_ivar * | |
89 object_getInstanceVariable (id object, const char *name, void **returnValue) | |
90 { | |
91 if (object == nil || name == NULL) | |
92 return NULL; | |
93 else | |
94 { | |
95 struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name); | |
96 | |
97 if (variable != NULL && returnValue != NULL) | |
98 { | |
99 char *location = (char *)object + variable->ivar_offset; | |
100 | |
101 *returnValue = *((id *)location); | |
102 } | |
103 | |
104 return variable; | |
105 } | |
106 } | |
107 | |
108 struct objc_ivar * | |
109 object_setInstanceVariable (id object, const char *name, void *newValue) | |
110 { | |
111 if (object == nil || name == NULL) | |
112 return NULL; | |
113 else | |
114 { | |
115 struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name); | |
116 | |
117 if (variable != NULL) | |
118 { | |
119 char *location = (char *)object + variable->ivar_offset; | |
120 | |
121 *((id *)location) = (id)newValue; | |
122 } | |
123 | |
124 return variable; | |
125 } | |
126 } | |
127 | |
128 id object_getIvar (id object, struct objc_ivar * variable) | |
129 { | |
130 if (object == nil || variable == NULL) | |
131 return nil; | |
132 else | |
133 { | |
134 char *location = (char *)object + variable->ivar_offset; | |
135 | |
136 return *((id *)location); | |
137 } | |
138 } | |
139 | |
140 void object_setIvar (id object, struct objc_ivar * variable, id value) | |
141 { | |
142 if (object == nil || variable == NULL) | |
143 return; | |
144 else | |
145 { | |
146 char *location = (char *)object + variable->ivar_offset; | |
147 | |
148 *((id *)location) = value; | |
149 } | |
150 } | |
151 | |
152 const char * ivar_getName (struct objc_ivar * variable) | |
153 { | |
154 if (variable == NULL) | |
155 return NULL; | |
156 | |
157 return variable->ivar_name; | |
158 } | |
159 | |
160 ptrdiff_t ivar_getOffset (struct objc_ivar * variable) | |
161 { | |
162 if (variable == NULL) | |
163 return 0; | |
164 | |
165 return (ptrdiff_t)(variable->ivar_offset); | |
166 } | |
167 | |
168 const char * ivar_getTypeEncoding (struct objc_ivar * variable) | |
169 { | |
170 if (variable == NULL) | |
171 return NULL; | |
172 | |
173 return variable->ivar_type; | |
174 } | |
175 | |
176 struct objc_ivar ** class_copyIvarList (Class class_, unsigned int *numberOfReturnedIvars) | |
177 { | |
178 unsigned int count = 0; | |
179 struct objc_ivar **returnValue = NULL; | |
180 struct objc_ivar_list* ivar_list; | |
181 | |
182 if (class_ == Nil || CLS_IS_IN_CONSTRUCTION (class_) || !class_->ivars) | |
183 { | |
184 if (numberOfReturnedIvars) | |
185 *numberOfReturnedIvars = 0; | |
186 return NULL; | |
187 } | |
188 | |
189 /* Count how many ivars we have. */ | |
190 ivar_list = class_->ivars; | |
191 count = ivar_list->ivar_count; | |
192 | |
193 if (count != 0) | |
194 { | |
195 unsigned int i = 0; | |
196 | |
197 /* Allocate enough memory to hold them. */ | |
198 returnValue = (struct objc_ivar **)(malloc (sizeof (struct objc_ivar *) * (count + 1))); | |
199 | |
200 /* Copy the ivars. */ | |
201 for (i = 0; i < count; i++) | |
202 returnValue[i] = &(ivar_list->ivar_list[i]); | |
203 | |
204 returnValue[i] = NULL; | |
205 } | |
206 | |
207 if (numberOfReturnedIvars) | |
208 *numberOfReturnedIvars = count; | |
209 | |
210 return returnValue; | |
211 } | |
212 | |
213 BOOL | |
214 class_addIvar (Class class_, const char * ivar_name, size_t size, | |
215 unsigned char log_2_of_alignment, const char *type) | |
216 { | |
217 struct objc_ivar_list *ivars; | |
218 | |
219 if (class_ == Nil | |
220 || (! CLS_IS_IN_CONSTRUCTION (class_)) | |
221 || ivar_name == NULL | |
222 || (strcmp (ivar_name, "") == 0) | |
223 || size == 0 | |
224 || type == NULL) | |
225 return NO; | |
226 | |
227 /* Check if the class has an instance variable with that name | |
228 already. */ | |
229 ivars = class_->ivars; | |
230 | |
231 if (ivars != NULL) | |
232 { | |
233 int i; | |
234 | |
235 for (i = 0; i < ivars->ivar_count; i++) | |
236 { | |
237 struct objc_ivar *ivar = &(ivars->ivar_list[i]); | |
238 | |
239 if (strcmp (ivar->ivar_name, ivar_name) == 0) | |
240 return NO; | |
241 } | |
242 } | |
243 | |
244 /* Ok, no direct ivars. Check superclasses. */ | |
245 if (class_getInstanceVariable (objc_getClass ((char *)(class_->super_class)), | |
246 ivar_name)) | |
247 return NO; | |
248 | |
249 /* Good. Create space for the new instance variable. */ | |
250 if (ivars) | |
251 { | |
252 int ivar_count = ivars->ivar_count + 1; | |
253 int new_size = sizeof (struct objc_ivar_list) | |
254 + (ivar_count - 1) * sizeof (struct objc_ivar); | |
255 | |
256 ivars = (struct objc_ivar_list*) objc_realloc (ivars, new_size); | |
257 ivars->ivar_count = ivar_count; | |
258 class_->ivars = ivars; | |
259 } | |
260 else | |
261 { | |
262 int new_size = sizeof (struct objc_ivar_list); | |
263 | |
264 ivars = (struct objc_ivar_list*) objc_malloc (new_size); | |
265 ivars->ivar_count = 1; | |
266 class_->ivars = ivars; | |
267 } | |
268 | |
269 /* Now ivars is set to a list of instance variables of the right | |
270 size. */ | |
271 { | |
272 struct objc_ivar *ivar = &(ivars->ivar_list[ivars->ivar_count - 1]); | |
273 unsigned int alignment = 1 << log_2_of_alignment; | |
274 int misalignment; | |
275 | |
276 ivar->ivar_name = objc_malloc (strlen (ivar_name) + 1); | |
277 strcpy ((char *)ivar->ivar_name, ivar_name); | |
278 | |
279 ivar->ivar_type = objc_malloc (strlen (type) + 1); | |
280 strcpy ((char *)ivar->ivar_type, type); | |
281 | |
282 /* The new instance variable is placed at the end of the existing | |
283 instance_size, at the first byte that is aligned with | |
284 alignment. */ | |
285 misalignment = class_->instance_size % alignment; | |
286 | |
287 if (misalignment == 0) | |
288 ivar->ivar_offset = class_->instance_size; | |
289 else | |
290 ivar->ivar_offset = class_->instance_size - misalignment + alignment; | |
291 | |
292 class_->instance_size = ivar->ivar_offset + size; | |
293 } | |
294 | |
295 return YES; | |
296 } | |
297 | |
298 | |
299 const char * | |
300 property_getName (struct objc_property * property __attribute__ ((__unused__))) | |
301 { | |
302 if (property == NULL) | |
303 return NULL; | |
304 | |
305 /* TODO: New ABI. */ | |
306 /* The current ABI does not have any information on properties. */ | |
307 return NULL; | |
308 } | |
309 | |
310 const char * | |
311 property_getAttributes (struct objc_property * property __attribute__ ((__unused__))) | |
312 { | |
313 if (property == NULL) | |
314 return NULL; | |
315 | |
316 /* TODO: New ABI. */ | |
317 /* The current ABI does not have any information on properties. */ | |
318 return NULL; | |
319 } | |
320 | |
321 struct objc_property * | |
322 class_getProperty (Class class_ __attribute__ ((__unused__)), | |
323 const char *propertyName __attribute__ ((__unused__))) | |
324 { | |
325 if (class_ == NULL || propertyName == NULL) | |
326 return NULL; | |
327 | |
328 /* TODO: New ABI. */ | |
329 /* The current ABI does not have any information on class properties. */ | |
330 return NULL; | |
331 } | |
332 | |
333 struct objc_property ** | |
334 class_copyPropertyList (Class class_ __attribute__ ((__unused__)), | |
335 unsigned int *numberOfReturnedProperties __attribute__ ((__unused__))) | |
336 { | |
337 if (class_ == Nil) | |
338 { | |
339 if (numberOfReturnedProperties) | |
340 *numberOfReturnedProperties = 0; | |
341 return NULL; | |
342 } | |
343 | |
344 /* TODO: New ABI. */ | |
345 /* The current ABI does not have any information on class properties. */ | |
346 if (numberOfReturnedProperties) | |
347 *numberOfReturnedProperties = 0; | |
348 | |
349 return NULL; | |
350 } | |
351 | |
352 const char * | |
353 class_getIvarLayout (Class class_ __attribute__ ((__unused__))) | |
354 { | |
355 return NULL; | |
356 } | |
357 | |
358 const char * | |
359 class_getWeakIvarLayout (Class class_ __attribute__ ((__unused__))) | |
360 { | |
361 return NULL; | |
362 } | |
363 | |
364 void | |
365 class_setIvarLayout (Class class_ __attribute__ ((__unused__)), | |
366 const char *layout __attribute__ ((__unused__))) | |
367 { | |
368 return; | |
369 } | |
370 | |
371 void | |
372 class_setWeakIvarLayout (Class class_ __attribute__ ((__unused__)), | |
373 const char *layout __attribute__ ((__unused__))) | |
374 { | |
375 return; | |
376 } |