c2c337a7a5ae87160ae207fd0eb30c115e8adf6a
[cacao.git] / src / vmcore / field.c
1 /* src/vmcore/field.c - field functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: field.c 8227 2007-07-24 11:55:07Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34 #include <stdio.h>
35
36 #include "vm/types.h"
37
38 #include "vm/exceptions.h"
39 #include "vm/stringlocal.h"
40 #include "vm/vm.h"
41
42 #include "vmcore/class.h"
43 #include "vmcore/descriptor.h"
44 #include "vmcore/field.h"
45 #include "vmcore/loader.h"
46 #include "vmcore/options.h"
47 #include "vmcore/primitive.h"
48 #include "vmcore/references.h"
49 #include "vmcore/suck.h"
50 #include "vmcore/utf8.h"
51
52
53 /* field_load ******************************************************************
54
55    Load everything about a class field from the class file and fill a
56    fieldinfo structure.
57
58 *******************************************************************************/
59
60 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
61
62 bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
63 {
64         classinfo *c;
65         u4 attrnum, i;
66         u4 jtype;
67         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
68         utf *u;
69
70         c = cb->class;
71
72         if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
73                 return false;
74
75         f->flags = suck_u2(cb);
76
77         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
78                 return false;
79
80         f->name = u;
81
82         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
83                 return false;
84
85         f->descriptor = u;
86         f->parseddesc = NULL;
87
88         if (!descriptor_pool_add(descpool, u, NULL))
89                 return false;
90
91         /* descriptor_pool_add accepts method descriptors, so we have to
92            check against them here before the call of
93            descriptor_to_basic_type below. */
94
95         if (u->text[0] == '(') {
96                 exceptions_throw_classformaterror(c, "Method descriptor used for field");
97                 return false;
98         }
99
100 #ifdef ENABLE_VERIFIER
101         if (opt_verify) {
102                 /* check name */
103                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
104                         exceptions_throw_classformaterror(c,
105                                                                                           "Illegal Field name \"%s\"",
106                                                                                           f->name->text);
107                         return false;
108                 }
109
110                 /* check flag consistency */
111                 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
112
113                 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
114                         ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
115                         exceptions_throw_classformaterror(c,
116                                                                                           "Illegal field modifiers: 0x%X",
117                                                                                           f->flags);
118                         return false;
119                 }
120
121                 if (c->flags & ACC_INTERFACE) {
122                         if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
123                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
124                                 f->flags & ACC_TRANSIENT) {
125                                 exceptions_throw_classformaterror(c,
126                                                                                                   "Illegal field modifiers: 0x%X",
127                                                                                                   f->flags);
128                                 return false;
129                         }
130                 }
131         }
132 #endif /* ENABLE_VERIFIER */
133
134         /* data type */
135
136         jtype = descriptor_to_basic_type(f->descriptor);
137
138         f->class  = c;
139         f->type   = jtype;
140         f->offset = 0;                             /* offset from start of object */
141
142         switch (f->type) {
143         case TYPE_INT:
144                 f->value.i = 0;
145                 break;
146
147         case TYPE_FLT:
148                 f->value.f = 0.0;
149                 break;
150
151         case TYPE_DBL:
152                 f->value.d = 0.0;
153                 break;
154
155         case TYPE_ADR:
156                 f->value.a = NULL;
157                 if (!(f->flags & ACC_STATIC))
158                         c->flags |= ACC_CLASS_HAS_POINTERS;
159                 break;
160
161         case TYPE_LNG:
162 #if U8_AVAILABLE
163                 f->value.l = 0;
164 #else
165                 f->value.l.low  = 0;
166                 f->value.l.high = 0;
167 #endif
168                 break;
169         }
170
171         /* read attributes */
172         if (!suck_check_classbuffer_size(cb, 2))
173                 return false;
174
175         attrnum = suck_u2(cb);
176         for (i = 0; i < attrnum; i++) {
177                 if (!suck_check_classbuffer_size(cb, 2))
178                         return false;
179
180                 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
181                         return false;
182
183                 if (u == utf_ConstantValue) {
184                         if (!suck_check_classbuffer_size(cb, 4 + 2))
185                                 return false;
186
187                         /* check attribute length */
188
189                         if (suck_u4(cb) != 2) {
190                                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
191                                 return false;
192                         }
193                         
194                         /* constant value attribute */
195
196                         if (pindex != field_load_NOVALUE) {
197                                 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
198                                 return false;
199                         }
200                         
201                         /* index of value in constantpool */
202
203                         pindex = suck_u2(cb);
204                 
205                         /* initialize field with value from constantpool */             
206
207                         switch (jtype) {
208                         case TYPE_INT: {
209                                 constant_integer *ci; 
210
211                                 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
212                                         return false;
213
214                                 f->value.i = ci->value;
215                         }
216                         break;
217                                         
218                         case TYPE_LNG: {
219                                 constant_long *cl; 
220
221                                 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
222                                         return false;
223
224                                 f->value.l = cl->value;
225                         }
226                         break;
227
228                         case TYPE_FLT: {
229                                 constant_float *cf;
230
231                                 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
232                                         return false;
233
234                                 f->value.f = cf->value;
235                         }
236                         break;
237                                                                                         
238                         case TYPE_DBL: {
239                                 constant_double *cd;
240
241                                 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
242                                         return false;
243
244                                 f->value.d = cd->value;
245                         }
246                         break;
247                                                 
248                         case TYPE_ADR:
249                                 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
250                                         return false;
251
252                                 /* create javastring from compressed utf8-string */
253                                 f->value.a = literalstring_new(u);
254                                 break;
255         
256                         default: 
257                                 vm_abort("field_load: invalid field type %d", jtype);
258                         }
259                 }
260 #if defined(ENABLE_JAVASE)
261                 else if (u == utf_Signature) {
262                         /* Signature */
263
264                         if (!loader_load_attribute_signature(cb, &(f->signature)))
265                                 return false;
266                 }
267 #endif
268                 else {
269                         /* unknown attribute */
270
271                         if (!loader_skip_attribute_body(cb))
272                                 return false;
273                 }
274         }
275
276         /* everything was ok */
277
278         return true;
279 }
280
281
282 /* field_get_type **************************************************************
283
284    Returns the type of the field as class.
285
286 *******************************************************************************/
287
288 classinfo *field_get_type(fieldinfo *f)
289 {
290         typedesc  *td;
291         utf       *u;
292         classinfo *c;
293
294         td = f->parseddesc;
295
296         if (td->type == TYPE_ADR) {
297                 assert(td->classref);
298
299                 u = td->classref->name;
300
301                 /* load the class of the field-type with the field's
302                    classloader */
303
304                 c = load_class_from_classloader(u, f->class->classloader);
305         }
306         else {
307                 c = primitive_class_get_by_type(td->decltype);
308         }
309
310         return c;
311 }
312
313
314 /* field_free ******************************************************************
315
316    Frees a fields' resources.
317
318 *******************************************************************************/
319
320 void field_free(fieldinfo *f)
321 {
322         /* empty */
323 }
324
325
326 /* field_printflags ************************************************************
327
328    (debugging only)
329
330 *******************************************************************************/
331
332 #if !defined(NDEBUG)
333 void field_printflags(fieldinfo *f)
334 {
335         if (f == NULL) {
336                 printf("NULL");
337                 return;
338         }
339
340         if (f->flags & ACC_PUBLIC)       printf(" PUBLIC");
341         if (f->flags & ACC_PRIVATE)      printf(" PRIVATE");
342         if (f->flags & ACC_PROTECTED)    printf(" PROTECTED");
343         if (f->flags & ACC_STATIC)       printf(" STATIC");
344         if (f->flags & ACC_FINAL)        printf(" FINAL");
345         if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
346         if (f->flags & ACC_VOLATILE)     printf(" VOLATILE");
347         if (f->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
348         if (f->flags & ACC_NATIVE)       printf(" NATIVE");
349         if (f->flags & ACC_INTERFACE)    printf(" INTERFACE");
350         if (f->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
351 }
352 #endif
353
354
355 /* field_print *****************************************************************
356
357    (debugging only)
358
359 *******************************************************************************/
360
361 #if !defined(NDEBUG)
362 void field_print(fieldinfo *f)
363 {
364         if (f == NULL) {
365                 printf("(fieldinfo*)NULL");
366                 return;
367         }
368
369         utf_display_printable_ascii_classname(f->class->name);
370         printf(".");
371         utf_display_printable_ascii(f->name);
372         printf(" ");
373         utf_display_printable_ascii(f->descriptor);     
374
375         field_printflags(f);
376 }
377 #endif
378
379
380 /* field_println ***************************************************************
381
382    (debugging only)
383
384 *******************************************************************************/
385
386 #if !defined(NDEBUG)
387 void field_println(fieldinfo *f)
388 {
389         field_print(f);
390         printf("\n");
391 }
392 #endif
393
394 /* field_fieldref_print ********************************************************
395
396    (debugging only)
397
398 *******************************************************************************/
399
400 #if !defined(NDEBUG)
401 void field_fieldref_print(constant_FMIref *fr)
402 {
403         if (fr == NULL) {
404                 printf("(constant_FMIref *)NULL");
405                 return;
406         }
407
408         if (IS_FMIREF_RESOLVED(fr)) {
409                 printf("<field> ");
410                 field_print(fr->p.field);
411         }
412         else {
413                 printf("<fieldref> ");
414                 utf_display_printable_ascii_classname(fr->p.classref->name);
415                 printf(".");
416                 utf_display_printable_ascii(fr->name);
417                 printf(" ");
418                 utf_display_printable_ascii(fr->descriptor);
419         }
420 }
421 #endif
422
423 /* field_fieldref_println ******************************************************
424
425    (debugging only)
426
427 *******************************************************************************/
428
429 #if !defined(NDEBUG)
430 void field_fieldref_println(constant_FMIref *fr)
431 {
432         field_fieldref_print(fr);
433         printf("\n");
434 }
435 #endif
436
437 /*
438  * These are local overrides for various environment variables in Emacs.
439  * Please do not remove this and leave it at the end of the file, where
440  * Emacs will automagically detect them.
441  * ---------------------------------------------------------------------
442  * Local variables:
443  * mode: c
444  * indent-tabs-mode: t
445  * c-basic-offset: 4
446  * tab-width: 4
447  * End:
448  */