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