1 /* src/cacaoh/headers.c - functions for header generation
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35 #if defined(ENABLE_THREADS)
36 # if defined(__DARWIN__)
39 # include <ucontext.h>
42 #include "mm/gc-common.h"
43 #include "mm/memory.h"
45 #include "toolbox/chain.h"
46 #include "toolbox/logging.h"
48 #include "vm/builtin.h"
49 #include "vm/global.h"
50 #include "vm/stringlocal.h"
52 #include "vmcore/class.h"
53 #include "vmcore/method.h"
54 #include "vmcore/loader.h"
55 #include "vmcore/options.h"
58 /************************ global variables **********************/
60 #define ACC_NATIVELY_OVERLOADED 0x10000000
62 #if defined(ENABLE_HANDLES)
63 # define HEAP_PREFIX "heap_"
65 # define HEAP_PREFIX ""
68 chain *ident_chain; /* chain with method and field names in current class */
70 static uint32_t outputsize;
71 static bool dopadding;
74 static void printIDpart(int c)
76 if ((c >= 'a' && c <= 'z') ||
77 (c >= 'A' && c <= 'Z') ||
78 (c >= '0' && c <= '9') ||
88 char *utf_ptr = u->text;
91 for (i = 0; i < utf_get_number_of_u2s(u); i++)
92 printIDpart(utf_nextu2(&utf_ptr));
96 static void addoutputsize(int len)
104 newsize = MEMORY_ALIGN(outputsize, len);
106 for (i = outputsize; i < newsize; i++)
107 fprintf(file, " uint8_t pad%d\n", (int) i);
109 outputsize = newsize;
113 void printOverloadPart(utf *desc)
115 char *utf_ptr=desc->text;
120 while ((c = utf_nextu2(&utf_ptr)) != ')') {
130 fprintf(file, "%c", (char) c);
137 while ((c = utf_nextu2(&utf_ptr)) != ';')
144 log_text("invalid method descriptor");
150 static char *printtype(char *utf_ptr, char *prefix, char *infix)
154 switch (utf_nextu2(&utf_ptr)) {
156 fprintf(file, "void");
164 fprintf(file, "int32_t");
168 fprintf(file, "int64_t");
172 fprintf(file, "float");
176 fprintf(file, "double");
179 addoutputsize ( sizeof(java_array_t*) );
180 switch (utf_nextu2(&utf_ptr)) {
181 case 'I': fprintf (file, "java%s_intarray_t*", infix); break;
182 case 'J': fprintf (file, "java%s_longarray_t*", infix); break;
183 case 'Z': fprintf (file, "java%s_booleanarray_t*", infix); break;
184 case 'B': fprintf (file, "java%s_bytearray_t*", infix); break;
185 case 'S': fprintf (file, "java%s_shortarray_t*", infix); break;
186 case 'C': fprintf (file, "java%s_chararray_t*", infix); break;
187 case 'F': fprintf (file, "java%s_floatarray_t*", infix); break;
188 case 'D': fprintf (file, "java%s_doublearray_t*", infix); break;
190 case '[': fprintf(file, "java%s_objectarray_t*", infix);
191 while ((c = utf_nextu2(&utf_ptr)) == '[');
193 while (utf_nextu2(&utf_ptr) != ';');
196 case 'L': fprintf(file, "java%s_objectarray_t*", infix);
197 while (utf_nextu2(&utf_ptr) != ';');
200 log_text("invalid type descriptor");
206 addoutputsize ( sizeof(java_object_t*));
207 fprintf (file, "struct %s", prefix);
208 while ( (c = utf_nextu2(&utf_ptr)) != ';' ) printIDpart (c);
213 log_text("Unknown type in field descriptor");
221 /***** determine the number of entries of a utf string in the ident chain *****/
223 static int searchidentchain_utf(utf *ident)
225 utf *u = chain_first(ident_chain); /* first element of list */
229 if (u==ident) count++; /* string found */
230 u = chain_next(ident_chain); /* next element in list */
237 /************** print structure for direct access to objects ******************/
239 static void printfields(classinfo *c)
246 addoutputsize(sizeof(java_object_t));
247 fprintf(file, " java_object_t header;\n");
251 printfields(c->super);
253 for (i = 0; i < c->fieldscount; i++) {
256 if (!(f->flags & ACC_STATIC)) {
258 printtype(f->descriptor->text, HEAP_PREFIX, "");
260 utf_fprint_printable_ascii(file, f->name);
262 /* rename multiple fieldnames */
263 if ((ident_count = searchidentchain_utf(f->name)))
264 fprintf(file, "%d", ident_count - 1);
265 chain_addlast(ident_chain, f->name);
267 fprintf(file, ";\n");
273 /***************** store prototype for native method in file ******************/
275 void printmethod(methodinfo *m)
278 int32_t paramnum = 1;
280 /* search for return-type in descriptor */
281 utf_ptr = m->descriptor->text;
282 while (utf_nextu2(&utf_ptr) != ')');
285 fprintf(file, "\n/*\n * Class: ");
286 utf_fprint_printable_ascii(file, m->clazz->name);
287 fprintf(file, "\n * Method: ");
288 utf_fprint_printable_ascii(file, m->name);
289 fprintf(file, "\n * Signature: ");
290 utf_fprint_printable_ascii(file, m->descriptor);
291 fprintf(file, "\n */\n");
293 /* create prototype */
294 fprintf(file, "JNIEXPORT ");
295 printtype(utf_ptr, "", "_handle");
296 fprintf(file, " JNICALL Java_");
297 printID(m->clazz->name);
299 chain_addlast(ident_chain, m->name);
304 /* ATTENTION: We use a dummy flag here. */
306 if (m->flags & ACC_NATIVELY_OVERLOADED)
307 printOverloadPart(m->descriptor);
309 fprintf(file, "(JNIEnv *env");
311 utf_ptr = m->descriptor->text + 1;
313 if (!(m->flags & ACC_STATIC)) {
314 fprintf(file, ", struct ");
315 printID(m->clazz->name);
316 fprintf(file, "* this");
319 fprintf(file, ", jclass clazz");
322 if ((*utf_ptr) != ')') fprintf(file, ", ");
324 while ((*utf_ptr) != ')') {
325 utf_ptr = printtype(utf_ptr, "", "_handle");
326 fprintf(file, " par%d", paramnum++);
327 if ((*utf_ptr)!=')') fprintf(file, ", ");
330 fprintf(file, ");\n\n");
334 /******* remove package-name in fully-qualified classname *********************/
336 void gen_header_filename(char *buffer, utf *u)
340 for (i = 0; i < utf_get_number_of_u2s(u); i++) {
341 if ((u->text[i] == '/') || (u->text[i] == '$')) {
342 buffer[i] = '_'; /* convert '$' and '/' to '_' */
345 buffer[i] = u->text[i];
348 buffer[utf_get_number_of_u2s(u)] = '\0';
352 /* create headerfile for classes and store native methods in chain ************/
354 void headerfile_generate(classinfo *c, char *opt_directory)
356 char header_filename[1024] = "";
357 char classname[1024];
358 char uclassname[1024];
363 bool nativelyoverloaded;
365 /* prevent compiler warnings */
367 nativelyoverloaded = false;
369 /* open headerfile for class */
370 gen_header_filename(classname, c->name);
372 /* create chain for renaming fields */
373 ident_chain = chain_new();
376 sprintf(header_filename, "%s/%s.h", opt_directory, classname);
379 sprintf(header_filename, "%s.h", classname);
382 file = fopen(header_filename, "w");
384 log_text("Can not open file to store header information");
388 fprintf(file, "/* This file is machine generated, don't edit it! */\n\n");
390 /* convert to uppercase */
391 for (i = 0; classname[i]; i++) {
392 uclassname[i] = toupper(classname[i]);
394 uclassname[i] = '\0';
396 fprintf(file, "#ifndef _%s_H\n#define _%s_H\n\n", uclassname, uclassname);
398 /* create structure for direct access to objects */
399 fprintf(file, "/* Structure information for class: ");
400 utf_fprint_printable_ascii(file, c->name);
401 fprintf(file, " */\n\n");
402 fprintf(file, "typedef struct %s", HEAP_PREFIX);
404 fprintf(file, " {\n");
410 fprintf(file, "} %s", HEAP_PREFIX);
412 fprintf(file, ";\n\n");
414 #if defined(ENABLE_HANDLES)
415 /* create structure for indirection cell */
416 fprintf(file, "typedef struct ");
418 fprintf(file, " {\n");
419 fprintf(file, " %s", HEAP_PREFIX);
421 fprintf(file, " *heap_object;\n");
424 fprintf(file, ";\n\n");
427 /* create chain for renaming overloaded methods */
428 chain_free(ident_chain);
429 ident_chain = chain_new();
431 /* create method-prototypes */
433 /* find overloaded methods */
435 for (i = 0; i < c->methodscount; i++) {
436 m = &(c->methods[i]);
438 if (!(m->flags & ACC_NATIVE))
441 /* We use a dummy flag here. */
443 if (!(m->flags & ACC_NATIVELY_OVERLOADED)) {
444 nativelyoverloaded = false;
446 for (j = i + 1; j < c->methodscount; j++) {
447 m2 = &(c->methods[j]);
449 if (!(m2->flags & ACC_NATIVE))
452 if (m->name == m2->name) {
453 m2->flags |= ACC_NATIVELY_OVERLOADED;
454 nativelyoverloaded = true;
459 if (nativelyoverloaded == true)
460 m->flags |= ACC_NATIVELY_OVERLOADED;
463 for (i = 0; i < c->methodscount; i++) {
464 m = &(c->methods[i]);
466 if (m->flags & ACC_NATIVE)
470 chain_free(ident_chain);
472 fprintf(file, "#endif\n\n");
478 /******** print classname, '$' used to seperate inner-class name ***********/
480 void print_classname(classinfo *clazz)
482 utf *u = clazz->name;
483 char *endpos = u->text + u->blength;
484 char *utf_ptr = u->text;
487 while (utf_ptr < endpos) {
488 if ((c = utf_nextu2(&utf_ptr)) == '_')
497 * These are local overrides for various environment variables in Emacs.
498 * Please do not remove this and leave it at the end of the file, where
499 * Emacs will automagically detect them.
500 * ---------------------------------------------------------------------
503 * indent-tabs-mode: t
507 * vim:noexpandtab:sw=4:ts=4: