1 /* src/cacaoh/headers.c - functions for header generation
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
8 This file is part of CACAO.
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.
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.
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
37 #if defined(ENABLE_THREADS)
38 # if defined(__DARWIN__)
41 # include <ucontext.h>
44 #include "mm/gc-common.h"
45 #include "mm/memory.h"
47 #include "toolbox/chain.h"
48 #include "toolbox/logging.h"
50 #include "vm/builtin.h"
51 #include "vm/global.h"
52 #include "vm/stringlocal.h"
54 #include "vmcore/class.h"
55 #include "vmcore/method.h"
56 #include "vmcore/loader.h"
57 #include "vmcore/options.h"
60 /************************ global variables **********************/
62 #define ACC_NATIVELY_OVERLOADED 0x10000000
64 #if defined(ENABLE_HANDLES)
65 # define HEAP_PREFIX "heap_"
67 # define HEAP_PREFIX ""
70 chain *ident_chain; /* chain with method and field names in current class */
72 static uint32_t outputsize;
73 static bool dopadding;
76 static void printIDpart(int c)
78 if ((c >= 'a' && c <= 'z') ||
79 (c >= 'A' && c <= 'Z') ||
80 (c >= '0' && c <= '9') ||
90 char *utf_ptr = u->text;
93 for (i = 0; i < utf_get_number_of_u2s(u); i++)
94 printIDpart(utf_nextu2(&utf_ptr));
98 static void addoutputsize(int len)
106 newsize = MEMORY_ALIGN(outputsize, len);
108 for (i = outputsize; i < newsize; i++)
109 fprintf(file, " uint8_t pad%d\n", (int) i);
111 outputsize = newsize;
115 void printOverloadPart(utf *desc)
117 char *utf_ptr=desc->text;
122 while ((c = utf_nextu2(&utf_ptr)) != ')') {
132 fprintf(file, "%c", (char) c);
139 while ((c = utf_nextu2(&utf_ptr)) != ';')
146 log_text("invalid method descriptor");
152 static char *printtype(char *utf_ptr, char *prefix, char *infix)
156 switch (utf_nextu2(&utf_ptr)) {
158 fprintf(file, "void");
166 fprintf(file, "int32_t");
170 fprintf(file, "int64_t");
174 fprintf(file, "float");
178 fprintf(file, "double");
181 addoutputsize ( sizeof(java_array_t*) );
182 switch (utf_nextu2(&utf_ptr)) {
183 case 'I': fprintf (file, "java%s_intarray_t*", infix); break;
184 case 'J': fprintf (file, "java%s_longarray_t*", infix); break;
185 case 'Z': fprintf (file, "java%s_booleanarray_t*", infix); break;
186 case 'B': fprintf (file, "java%s_bytearray_t*", infix); break;
187 case 'S': fprintf (file, "java%s_shortarray_t*", infix); break;
188 case 'C': fprintf (file, "java%s_chararray_t*", infix); break;
189 case 'F': fprintf (file, "java%s_floatarray_t*", infix); break;
190 case 'D': fprintf (file, "java%s_doublearray_t*", infix); break;
192 case '[': fprintf(file, "java%s_objectarray_t*", infix);
193 while ((c = utf_nextu2(&utf_ptr)) == '[');
195 while (utf_nextu2(&utf_ptr) != ';');
198 case 'L': fprintf(file, "java%s_objectarray_t*", infix);
199 while (utf_nextu2(&utf_ptr) != ';');
202 log_text("invalid type descriptor");
208 addoutputsize ( sizeof(java_object_t*));
209 fprintf (file, "struct %s", prefix);
210 while ( (c = utf_nextu2(&utf_ptr)) != ';' ) printIDpart (c);
215 log_text("Unknown type in field descriptor");
223 /***** determine the number of entries of a utf string in the ident chain *****/
225 static int searchidentchain_utf(utf *ident)
227 utf *u = chain_first(ident_chain); /* first element of list */
231 if (u==ident) count++; /* string found */
232 u = chain_next(ident_chain); /* next element in list */
239 /************** print structure for direct access to objects ******************/
241 static void printfields(classinfo *c)
248 addoutputsize(sizeof(java_object_t));
249 fprintf(file, " java_object_t header;\n");
253 printfields(c->super.cls);
255 for (i = 0; i < c->fieldscount; i++) {
258 if (!(f->flags & ACC_STATIC)) {
260 printtype(f->descriptor->text, HEAP_PREFIX, "");
262 utf_fprint_printable_ascii(file, f->name);
264 /* rename multiple fieldnames */
265 if ((ident_count = searchidentchain_utf(f->name)))
266 fprintf(file, "%d", ident_count - 1);
267 chain_addlast(ident_chain, f->name);
269 fprintf(file, ";\n");
275 /***************** store prototype for native method in file ******************/
277 void printmethod(methodinfo *m)
280 int32_t paramnum = 1;
282 /* search for return-type in descriptor */
283 utf_ptr = m->descriptor->text;
284 while (utf_nextu2(&utf_ptr) != ')');
287 fprintf(file, "\n/*\n * Class: ");
288 utf_fprint_printable_ascii(file, m->class->name);
289 fprintf(file, "\n * Method: ");
290 utf_fprint_printable_ascii(file, m->name);
291 fprintf(file, "\n * Signature: ");
292 utf_fprint_printable_ascii(file, m->descriptor);
293 fprintf(file, "\n */\n");
295 /* create prototype */
296 fprintf(file, "JNIEXPORT ");
297 printtype(utf_ptr, "", "_handle");
298 fprintf(file, " JNICALL Java_");
299 printID(m->class->name);
301 chain_addlast(ident_chain, m->name);
306 /* ATTENTION: We use a dummy flag here. */
308 if (m->flags & ACC_NATIVELY_OVERLOADED)
309 printOverloadPart(m->descriptor);
311 fprintf(file, "(JNIEnv *env");
313 utf_ptr = m->descriptor->text + 1;
315 if (!(m->flags & ACC_STATIC)) {
316 fprintf(file, ", struct ");
317 printID(m->class->name);
318 fprintf(file, "* this");
321 fprintf(file, ", jclass clazz");
324 if ((*utf_ptr) != ')') fprintf(file, ", ");
326 while ((*utf_ptr) != ')') {
327 utf_ptr = printtype(utf_ptr, "", "_handle");
328 fprintf(file, " par%d", paramnum++);
329 if ((*utf_ptr)!=')') fprintf(file, ", ");
332 fprintf(file, ");\n\n");
336 /******* remove package-name in fully-qualified classname *********************/
338 void gen_header_filename(char *buffer, utf *u)
342 for (i = 0; i < utf_get_number_of_u2s(u); i++) {
343 if ((u->text[i] == '/') || (u->text[i] == '$')) {
344 buffer[i] = '_'; /* convert '$' and '/' to '_' */
347 buffer[i] = u->text[i];
350 buffer[utf_get_number_of_u2s(u)] = '\0';
354 /* create headerfile for classes and store native methods in chain ************/
356 void headerfile_generate(classinfo *c, char *opt_directory)
358 char header_filename[1024] = "";
359 char classname[1024];
360 char uclassname[1024];
365 bool nativelyoverloaded;
367 /* prevent compiler warnings */
369 nativelyoverloaded = false;
371 /* open headerfile for class */
372 gen_header_filename(classname, c->name);
374 /* create chain for renaming fields */
375 ident_chain = chain_new();
378 sprintf(header_filename, "%s/%s.h", opt_directory, classname);
381 sprintf(header_filename, "%s.h", classname);
384 file = fopen(header_filename, "w");
386 log_text("Can not open file to store header information");
390 fprintf(file, "/* This file is machine generated, don't edit it! */\n\n");
392 /* convert to uppercase */
393 for (i = 0; classname[i]; i++) {
394 uclassname[i] = toupper(classname[i]);
396 uclassname[i] = '\0';
398 fprintf(file, "#ifndef _%s_H\n#define _%s_H\n\n", uclassname, uclassname);
400 /* create structure for direct access to objects */
401 fprintf(file, "/* Structure information for class: ");
402 utf_fprint_printable_ascii(file, c->name);
403 fprintf(file, " */\n\n");
404 fprintf(file, "typedef struct %s", HEAP_PREFIX);
406 fprintf(file, " {\n");
412 fprintf(file, "} %s", HEAP_PREFIX);
414 fprintf(file, ";\n\n");
416 #if defined(ENABLE_HANDLES)
417 /* create structure for indirection cell */
418 fprintf(file, "typedef struct ");
420 fprintf(file, " {\n");
421 fprintf(file, " %s", HEAP_PREFIX);
423 fprintf(file, " *heap_object;\n");
426 fprintf(file, ";\n\n");
429 /* create chain for renaming overloaded methods */
430 chain_free(ident_chain);
431 ident_chain = chain_new();
433 /* create method-prototypes */
435 /* find overloaded methods */
437 for (i = 0; i < c->methodscount; i++) {
438 m = &(c->methods[i]);
440 if (!(m->flags & ACC_NATIVE))
443 /* We use a dummy flag here. */
445 if (!(m->flags & ACC_NATIVELY_OVERLOADED)) {
446 nativelyoverloaded = false;
448 for (j = i + 1; j < c->methodscount; j++) {
449 m2 = &(c->methods[j]);
451 if (!(m2->flags & ACC_NATIVE))
454 if (m->name == m2->name) {
455 m2->flags |= ACC_NATIVELY_OVERLOADED;
456 nativelyoverloaded = true;
461 if (nativelyoverloaded == true)
462 m->flags |= ACC_NATIVELY_OVERLOADED;
465 for (i = 0; i < c->methodscount; i++) {
466 m = &(c->methods[i]);
468 if (m->flags & ACC_NATIVE)
472 chain_free(ident_chain);
474 fprintf(file, "#endif\n\n");
480 /******** print classname, '$' used to seperate inner-class name ***********/
482 void print_classname(classinfo *clazz)
484 utf *u = clazz->name;
485 char *endpos = u->text + u->blength;
486 char *utf_ptr = u->text;
489 while (utf_ptr < endpos) {
490 if ((c = utf_nextu2(&utf_ptr)) == '_')
499 * These are local overrides for various environment variables in Emacs.
500 * Please do not remove this and leave it at the end of the file, where
501 * Emacs will automagically detect them.
502 * ---------------------------------------------------------------------
505 * indent-tabs-mode: t
509 * vim:noexpandtab:sw=4:ts=4: