* autogen.sh: Made executeable.
[cacao.git] / src / vmcore / annotation.c
1 /* src/vmcore/annotation.c - class annotations
2
3    Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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 */
26
27 #include "config.h"
28
29 #include <assert.h>
30
31 #include "native/llni.h"
32
33 #include "vm/types.h"
34 #include "vm/array.h"
35 #include "vm/builtin.h"
36 #include "vm/primitive.h"
37
38 #include "mm/memory.h"
39
40 #include "toolbox/logging.h"
41
42 #include "vmcore/annotation.h"
43 #include "vmcore/class.h"
44 #include "vmcore/suck.h"
45
46 #if !defined(ENABLE_ANNOTATIONS)
47 # error annotation support has to be enabled when compling this file!
48 #endif
49
50
51 /* annotation_bytearrays_resize ***********************************************
52
53    Resize an array of bytearrays.
54
55 *******************************************************************************/
56
57 static bool annotation_bytearrays_resize(java_handle_objectarray_t **bas,
58         uint32_t size)
59 {
60         java_handle_objectarray_t *newbas = NULL;
61         java_handle_t             *o;
62         uint32_t i;
63         uint32_t minsize;
64         uint32_t oldsize;
65         
66         assert(bas != NULL);
67         
68         /* if the size already fits do nothing */
69         if (*bas != NULL) {
70                 oldsize = array_length_get((java_handle_t*)*bas);
71
72                 if (size == oldsize) {
73                         return true;
74                 }
75         }
76
77         newbas = builtin_anewarray(size,
78                 primitive_arrayclass_get_by_type(PRIMITIVETYPE_BYTE));
79         
80         if (newbas == NULL) {
81                 /* out of memory */
82                 return false;
83         }
84         
85         /* is there a old byte array array? */
86         if (*bas != NULL) {
87                 minsize = size < oldsize ? size : oldsize;
88
89                 MCOPY(LLNI_array_data(newbas), LLNI_array_data(*bas), java_object_t*, minsize);
90         }
91
92         *bas = newbas;
93
94         return true;
95 }
96
97
98 /* annotation_bytearrays_insert ***********************************************
99
100    Insert a bytearray into an array of bytearrays.
101
102 *******************************************************************************/
103
104 static bool annotation_bytearrays_insert(java_handle_objectarray_t **bas,
105         uint32_t index, java_handle_bytearray_t *ba)
106 {
107         uint32_t size = 0;
108
109         assert(bas != NULL);
110
111         /* do nothing if NULL is inserted but no array exists */
112         if (ba == NULL && *bas == NULL) {
113                 return true;
114         }
115
116         /* get lengths if array exists */
117         if (*bas != NULL) {
118                 size = array_length_get((java_handle_t*)*bas);
119         }
120
121         if (ba == NULL) {
122                 /* insert NULL only if array is big enough */
123                 if (size > index) {
124                         array_objectarray_element_set(*bas, index, NULL);
125                 }
126         }
127         else {
128                 /* resize array if it's not enough for inserted value */
129                 if (size <= index) {
130                         if (!annotation_bytearrays_resize(bas, index + 1)) {
131                                 /* out of memory */
132                                 return false;
133                         }
134                 }
135
136                 array_objectarray_element_set(*bas, index, (java_handle_t*)ba);
137         }
138         
139         return true;
140 }
141
142
143 /* annotation_load_attribute_body *********************************************
144
145    This function loads the body of a generic attribute.
146
147    XXX: Maybe this function should be called loader_load_attribute_body and
148         located in vmcore/loader.c?
149
150    attribute_info {
151        u2 attribute_name_index;
152        u4 attribute_length;
153        u1 info[attribute_length];
154    }
155
156    IN:
157        cb.................classbuffer from which to read the data.
158        errormsg_prefix....prefix for error messages (if any).
159
160    OUT:
161        attribute..........bytearray-pointer which will be set to the read data.
162    
163    RETURN VALUE:
164        true if all went good. false otherwhise.
165
166 *******************************************************************************/
167
168 static bool annotation_load_attribute_body(classbuffer *cb,
169         java_handle_bytearray_t **attribute, const char *errormsg_prefix)
170 {
171         uint32_t size = 0;
172         java_handle_bytearray_t *ba = NULL;
173
174         assert(cb != NULL);
175         assert(attribute != NULL);
176
177         if (!suck_check_classbuffer_size(cb, 4)) {
178                 log_println("%s: size missing", errormsg_prefix);
179                 return false;
180         }
181
182         /* load attribute_length */
183         size = suck_u4(cb);
184         
185         if (!suck_check_classbuffer_size(cb, size)) {
186                 log_println("%s: invalid size", errormsg_prefix);
187                 return false;
188         }
189         
190         /* if attribute_length == 0 then NULL is
191          * the right value for this attribute */
192         if (size > 0) {
193                 ba = builtin_newarray_byte(size);
194
195                 if (ba == NULL) {
196                         /* out of memory */
197                         return false;
198                 }
199
200                 /* load data */
201                 suck_nbytes((uint8_t*)LLNI_array_data(ba), cb, size);
202
203                 /* return data */
204                 *attribute = ba;
205         }
206         
207         return true;
208 }
209
210
211 /* annotation_load_method_attribute_annotationdefault *************************
212
213    Load annotation default value.
214
215    AnnotationDefault_attribute {
216        u2 attribute_name_index;
217        u4 attribute_length;
218        element_value default_value;
219    }
220
221    IN:
222        cb.................classbuffer from which to read the data.
223        m..................methodinfo for the method of which the annotation
224                           default value is read and into which the value is
225                           stored into.
226
227    RETURN VALUE:
228        true if all went good. false otherwhise.
229
230 *******************************************************************************/
231
232 bool annotation_load_method_attribute_annotationdefault(
233                 classbuffer *cb, methodinfo *m)
234 {
235         int slot = 0;
236         java_handle_bytearray_t    *annotationdefault  = NULL;
237         java_handle_objectarray_t **annotationdefaults = NULL;
238
239         assert(cb != NULL);
240         assert(m != NULL);
241
242         annotationdefaults = &(m->class->method_annotationdefaults);
243
244         if (!annotation_load_attribute_body(
245                         cb, &annotationdefault,
246                         "invalid annotation default method attribute")) {
247                 return false;
248         }
249
250         if (annotationdefault != NULL) {
251                 slot = m - m->class->methods;
252
253                 if (!annotation_bytearrays_insert(
254                                 annotationdefaults, slot, annotationdefault)) {
255                         return false;
256                 }
257         }
258
259         return true;
260 }
261
262
263 /* annotation_load_method_attribute_runtimevisibleparameterannotations ********
264
265    Load runtime visible parameter annotations.
266
267    RuntimeVisibleParameterAnnotations_attribute {
268        u2 attribute_name_index;
269        u4 attribute_length;
270        u1 num_parameters;
271        {
272            u2 num_annotations;
273            annotation annotations[num_annotations];
274        } parameter_annotations[num_parameters];
275    }
276
277    IN:
278        cb.................classbuffer from which to read the data.
279        m..................methodinfo for the method of which the parameter
280                           annotations are read and into which the parameter
281                           annotations are stored into.
282
283    RETURN VALUE:
284        true if all went good. false otherwhise.
285
286 *******************************************************************************/
287
288 bool annotation_load_method_attribute_runtimevisibleparameterannotations(
289                 classbuffer *cb, methodinfo *m)
290 {
291         int slot = 0;
292         java_handle_bytearray_t    *annotations          = NULL;
293         java_handle_objectarray_t **parameterannotations = NULL;
294
295         assert(cb != NULL);
296         assert(m != NULL);
297
298         parameterannotations = &(m->class->method_parameterannotations);
299
300         if (!annotation_load_attribute_body(
301                         cb, &annotations,
302                         "invalid runtime visible parameter annotations method attribute")) {
303                 return false;
304         }
305
306         if (annotations != NULL) {
307                 slot = m - m->class->methods;
308
309                 if (!annotation_bytearrays_insert(
310                                 parameterannotations, slot, annotations)) {
311                         return false;
312                 }
313         }
314
315         return true;
316 }
317
318
319 /* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
320  
321    Load runtime invisible parameter annotations.
322
323    <quote cite="http://jcp.org/en/jsr/detail?id=202">
324    The RuntimeInvisibleParameterAnnotations attribute is similar to the
325    RuntimeVisibleParameterAnnotations attribute, except that the annotations
326    represented by a RuntimeInvisibleParameterAnnotations attribute must not be
327    made available for return by reflective APIs, unless the the JVM has
328    specifically been instructed to retain these annotations via some
329    implementation-specific mechanism such as a command line flag. In the
330    absence of such instructions, the JVM ignores this attribute.
331    </quote>
332
333    Hotspot loads them into the same bytearray as the runtime visible parameter
334    annotations (after the runtime visible parameter annotations). But in J2SE
335    the bytearray will only be parsed as if ther is only one annotation
336    structure in it, so the runtime invisible parameter annotatios will be
337    ignored.
338
339    Therefore I do not even bother to read them.
340
341    RuntimeInvisibleParameterAnnotations_attribute {
342        u2 attribute_name_index;
343        u4 attribute_length;
344        u1 num_parameters;
345        {
346            u2 num_annotations;
347            annotation annotations[num_annotations];
348        } parameter_annotations[num_parameters];
349    }
350
351    IN:
352        cb.................classbuffer from which to read the data.
353        m..................methodinfo for the method of which the parameter
354                           annotations are read and into which the parameter
355                           annotations are stored into.
356
357    RETURN VALUE:
358        true if all went good. false otherwhise.
359
360 *******************************************************************************/
361
362 bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
363                 classbuffer *cb, methodinfo *m)
364 {
365         return loader_skip_attribute_body(cb);
366 }
367
368
369 /* annotation_load_class_attribute_runtimevisibleannotations ******************
370    
371    Load runtime visible annotations of a class.
372    
373 *******************************************************************************/
374
375 bool annotation_load_class_attribute_runtimevisibleannotations(
376         classbuffer *cb)
377 {
378         return annotation_load_attribute_body(
379                 cb, &(cb->class->annotations),
380                 "invalid runtime visible annotations class attribute");
381 }
382
383
384 /* annotation_load_class_attribute_runtimeinvisibleannotations ****************
385    
386    Load runtime invisible annotations of a class (just skip them).
387    
388 *******************************************************************************/
389
390 bool annotation_load_class_attribute_runtimeinvisibleannotations(
391         classbuffer *cb)
392 {
393         return loader_skip_attribute_body(cb);
394 }
395
396
397 /* annotation_load_method_attribute_runtimevisibleannotations *****************
398    
399    Load runtime visible annotations of a method.
400    
401 *******************************************************************************/
402
403 bool annotation_load_method_attribute_runtimevisibleannotations(
404         classbuffer *cb, methodinfo *m)
405 {
406         int slot = 0;
407         java_handle_bytearray_t    *annotations        = NULL;
408         java_handle_objectarray_t **method_annotations = NULL;
409
410         assert(cb != NULL);
411         assert(m != NULL);
412
413         method_annotations = &(m->class->method_annotations);
414
415         if (!annotation_load_attribute_body(
416                         cb, &annotations,
417                         "invalid runtime visible annotations method attribute")) {
418                 return false;
419         }
420
421         if (annotations != NULL) {
422                 slot = m - m->class->methods;
423
424                 if (!annotation_bytearrays_insert(
425                                 method_annotations, slot, annotations)) {
426                         return false;
427                 }
428         }
429
430         return true;
431 }
432
433
434 /* annotation_load_method_attribute_runtimeinvisibleannotations ****************
435    
436    Load runtime invisible annotations of a method (just skip them).
437    
438 *******************************************************************************/
439
440 bool annotation_load_method_attribute_runtimeinvisibleannotations(
441         classbuffer *cb, methodinfo *m)
442 {
443         return loader_skip_attribute_body(cb);
444 }
445
446
447 /* annotation_load_field_attribute_runtimevisibleannotations ******************
448    
449    Load runtime visible annotations of a field.
450    
451 *******************************************************************************/
452
453 bool annotation_load_field_attribute_runtimevisibleannotations(
454         classbuffer *cb, fieldinfo *f)
455 {
456         int slot = 0;
457         java_handle_bytearray_t    *annotations       = NULL;
458         java_handle_objectarray_t **field_annotations = NULL;
459
460         assert(cb != NULL);
461         assert(f != NULL);
462
463         field_annotations = &(f->class->field_annotations);
464
465         if (!annotation_load_attribute_body(
466                         cb, &annotations,
467                         "invalid runtime visible annotations field attribute")) {
468                 return false;
469         }
470
471         if (annotations != NULL) {
472                 slot = f - f->class->fields;
473
474                 if (!annotation_bytearrays_insert(
475                                 field_annotations, slot, annotations)) {
476                         return false;
477                 }
478         }
479
480         return true;
481 }
482
483
484 /* annotation_load_field_attribute_runtimeinvisibleannotations ****************
485    
486    Load runtime invisible annotations of a field (just skip them).
487    
488 *******************************************************************************/
489
490 bool annotation_load_field_attribute_runtimeinvisibleannotations(
491         classbuffer *cb, fieldinfo *f)
492 {
493         return loader_skip_attribute_body(cb);
494 }
495
496
497 /*
498  * These are local overrides for various environment variables in Emacs.
499  * Please do not remove this and leave it at the end of the file, where
500  * Emacs will automagically detect them.
501  * ---------------------------------------------------------------------
502  * Local variables:
503  * mode: c
504  * indent-tabs-mode: t
505  * c-basic-offset: 4
506  * tab-width: 4
507  * End:
508  * vim:noexpandtab:sw=4:ts=4:
509  */