2 * This file is part of cparser.
3 * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 #include "adt/strutil.h"
26 #include "write_jna.h"
33 #include "adt/error.h"
34 #include "adt/xmalloc.h"
35 #include "adt/pset_new.h"
37 typedef struct output_limit {
39 struct output_limit *next;
42 static const scope_t *global_scope;
44 static pset_new_t avoid_symbols;
45 static output_limit *output_limits;
46 static const char *libname;
48 static bool is_system_header(const char *fname)
50 if (strstart(fname, "/usr/include"))
52 if (fname == builtin_source_position.input_name)
57 static const char *fix_builtin_names(const char *name)
59 if (streq(name, "class")) {
61 } else if (streq(name, "this")) {
63 } else if (streq(name, "public")) {
65 } else if (streq(name, "protected")) {
67 } else if (streq(name, "private")) {
69 } else if (streq(name, "final")) {
72 /* TODO put all reserved names here */
76 static const char *get_atomic_type_string(const atomic_type_kind_t type)
79 case ATOMIC_TYPE_VOID: return "void";
80 case ATOMIC_TYPE_CHAR: return "byte";
81 case ATOMIC_TYPE_SCHAR: return "byte";
82 case ATOMIC_TYPE_UCHAR: return "byte";
83 case ATOMIC_TYPE_SHORT: return "short";
84 case ATOMIC_TYPE_USHORT: return "short";
85 case ATOMIC_TYPE_INT: return "int";
86 case ATOMIC_TYPE_UINT: return "int";
87 case ATOMIC_TYPE_LONG: return "com.sun.jna.NativeLong";
88 case ATOMIC_TYPE_ULONG: return "com.sun.jna.NativeLong";
89 case ATOMIC_TYPE_LONGLONG: return "long";
90 case ATOMIC_TYPE_ULONGLONG: return "long";
91 case ATOMIC_TYPE_FLOAT: return "float";
92 case ATOMIC_TYPE_DOUBLE: return "double";
93 case ATOMIC_TYPE_BOOL: return "boolean";
94 default: panic("unsupported atomic type");
98 static void write_atomic_type(const atomic_type_t *type)
100 fputs(get_atomic_type_string(type->akind), out);
103 static void write_pointer_type(const pointer_type_t *type)
105 type_t *points_to = skip_typeref(type->points_to);
106 if (is_type_atomic(points_to, ATOMIC_TYPE_CHAR)) {
107 fputs("String", out);
110 if (is_type_pointer(points_to)) {
112 fputs("java.nio.Buffer", out);
115 fputs("Pointer", out);
118 static entity_t *find_typedef(const type_t *type)
120 /* first: search for a matching typedef in the global type... */
121 entity_t *entity = global_scope->entities;
122 for ( ; entity != NULL; entity = entity->base.next) {
123 if (entity->kind != ENTITY_TYPEDEF)
125 if (entity->typedefe.type == type)
132 static entity_t *find_enum_typedef(const enum_t *enume)
134 /* first: search for a matching typedef in the global type... */
135 entity_t *entity = global_scope->entities;
136 for ( ; entity != NULL; entity = entity->base.next) {
137 if (entity->kind != ENTITY_TYPEDEF)
139 type_t *type = entity->typedefe.type;
140 if (type->kind != TYPE_ENUM)
143 enum_t *e_entity = type->enumt.enume;
144 if (e_entity == enume)
151 static void write_compound_type(const compound_type_t *type)
153 entity_t *entity = find_typedef((const type_t*) type);
155 fputs(entity->base.symbol->string, out);
159 /* does the struct have a name? */
160 symbol_t *symbol = type->compound->base.symbol;
162 /* TODO: make sure we create a struct for it... */
163 fputs(symbol->string, out);
166 /* TODO: create a struct and use its name here... */
167 fputs("/* TODO anonymous struct */byte", out);
170 static void write_enum_name(const enum_type_t *type)
172 entity_t *entity = find_typedef((const type_t*) type);
173 if (entity != NULL) {
174 fputs(entity->base.symbol->string, out);
178 /* does the enum have a name? */
179 symbol_t *symbol = type->enume->base.symbol;
180 if (symbol != NULL) {
181 /* TODO: make sure we create an enum for it... */
182 fputs(symbol->string, out);
186 /* now we have a problem as we don't know how we'll call the anonymous
188 panic("can't reference entries from anonymous enums yet");
191 static void write_enum_type(const enum_type_t *type)
193 entity_t *entity = find_typedef((const type_t*) type);
194 if (entity != NULL) {
195 fprintf(out, "/* %s */int", entity->base.symbol->string);
199 /* does the enum have a name? */
200 symbol_t *symbol = type->enume->base.symbol;
201 if (symbol != NULL) {
202 /* TODO: make sure we create an enum for it... */
203 fprintf(out, "/* %s */int", symbol->string);
206 fprintf(out, "/* anonymous enum */int");
209 static void write_type(type_t *type)
211 type = skip_typeref(type);
214 write_atomic_type(&type->atomic);
217 write_pointer_type(&type->pointer);
219 case TYPE_COMPOUND_UNION:
220 case TYPE_COMPOUND_STRUCT:
221 write_compound_type(&type->compound);
224 write_enum_type(&type->enumt);
229 panic("invalid type");
235 fprintf(out, "/* TODO type */Pointer");
241 static void write_compound_entry(const entity_t *entity)
243 fprintf(out, "\t%s : ", entity->base.symbol->string);
244 write_type(entity->declaration.type);
248 static void write_compound(const symbol_t *symbol, const compound_type_t *type)
250 fprintf(out, "%s %s:\n",
251 type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
254 const entity_t *entity = type->compound->members.entities;
255 for ( ; entity != NULL; entity = entity->base.next) {
256 write_compound_entry(entity);
263 static void write_expression(const expression_t *expression);
265 static void write_unary_expression(const unary_expression_t *expression)
267 switch(expression->base.kind) {
268 case EXPR_UNARY_NEGATE:
274 case EXPR_UNARY_CAST:
275 write_expression(expression->value);
278 panic("unimplemented unary expression");
280 write_expression(expression->value);
283 static void write_binary_expression(const binary_expression_t *expression)
286 write_expression(expression->left);
288 switch(expression->base.kind) {
289 case EXPR_BINARY_BITWISE_OR: fputs("|", out); break;
290 case EXPR_BINARY_BITWISE_AND: fputs("&", out); break;
291 case EXPR_BINARY_BITWISE_XOR: fputs("^", out); break;
292 case EXPR_BINARY_SHIFTLEFT: fputs("<<", out); break;
293 case EXPR_BINARY_SHIFTRIGHT: fputs(">>", out); break;
294 case EXPR_BINARY_ADD: fputs("+", out); break;
295 case EXPR_BINARY_SUB: fputs("-", out); break;
296 case EXPR_BINARY_MUL: fputs("*", out); break;
297 case EXPR_BINARY_DIV: fputs("/", out); break;
299 panic("unimplemented binexpr");
302 write_expression(expression->right);
306 static void write_integer(const literal_expression_t *literal)
308 for (const char *c = literal->value.begin; c != literal->suffix; ++c) {
313 static void write_expression(const expression_t *expression)
316 switch(expression->kind) {
317 case EXPR_LITERAL_INTEGER:
318 write_integer(&expression->literal);
321 case EXPR_ENUM_CONSTANT: {
322 /* UHOH... hacking */
323 entity_t *entity = expression->reference.entity;
324 write_enum_name(& entity->enum_value.enum_type->enumt);
325 fprintf(out, ".%s.val", entity->base.symbol->string);
328 case EXPR_UNARY_CASES:
329 write_unary_expression(&expression->unary);
331 case EXPR_BINARY_CASES:
332 write_binary_expression(&expression->binary);
335 panic("not implemented expression");
339 static void write_enum(const symbol_t *symbol, const enum_t *entity)
344 if (symbol == NULL) {
345 static int lastenum = 0;
346 snprintf(buf, sizeof(buf), "AnonEnum%d", lastenum++);
349 name = symbol->string;
352 fprintf(out, "\tpublic static enum %s {\n", name);
354 entity_t *entry = entity->base.next;
355 for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
356 entry = entry->base.next) {
357 fprintf(out, "\t\t%s", entry->base.symbol->string);
359 if(entry->enum_value.value != NULL) {
360 write_expression(entry->enum_value.value);
363 if (entry->base.next != NULL
364 && entry->base.next->kind == ENTITY_ENUM_VALUE) {
370 fprintf(out, "\t\tpublic final int val;\n");
372 fprintf(out, "\t\tprivate static class C {\n");
373 fprintf(out, "\t\t\tstatic int next_val;\n");
374 fprintf(out, "\t\t}\n");
376 fprintf(out, "\t\t%s(int val) {\n", name);
377 fprintf(out, "\t\t\tthis.val = val;\n");
378 fprintf(out, "\t\t\tC.next_val = val + 1;\n");
379 fprintf(out, "\t\t}\n");
381 fprintf(out, "\t\t%s() {\n", name);
382 fprintf(out, "\t\t\tthis.val = C.next_val++;\n");
383 fprintf(out, "\t\t}\n");
385 fprintf(out, "\t\tpublic static %s getEnum(int val) {\n", name);
386 fprintf(out, "\t\t\tfor (%s entry : values()) {\n", name);
387 fprintf(out, "\t\t\t\tif (val == entry.val)\n");
388 fprintf(out, "\t\t\t\t\treturn entry;\n");
389 fprintf(out, "\t\t\t}\n");
390 fprintf(out, "\t\t\treturn null;\n");
391 fprintf(out, "\t\t}\n");
392 fprintf(out, "\t}\n");
397 static void write_variable(const entity_t *entity)
399 fprintf(out, "var %s : ", entity->base.symbol->string);
400 write_type(entity->declaration.type);
405 static void write_function(const entity_t *entity)
407 if (entity->function.body != NULL) {
408 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
409 entity->base.symbol->string);
414 const function_type_t *function_type
415 = (const function_type_t*) entity->declaration.type;
418 fprintf(out, "\tpublic static native ");
419 type_t *return_type = skip_typeref(function_type->return_type);
420 write_type(return_type);
421 fprintf(out, " %s(", entity->base.symbol->string);
423 entity_t *parameter = entity->function.parameters.entities;
426 for ( ; parameter != NULL; parameter = parameter->base.next) {
427 assert(parameter->kind == ENTITY_PARAMETER);
433 write_type(parameter->declaration.type);
434 if(parameter->base.symbol != NULL) {
435 fprintf(out, " %s", fix_builtin_names(parameter->base.symbol->string));
437 fprintf(out, " _%d", n++);
440 if(function_type->variadic) {
444 fputs("Object ... args", out);
446 fprintf(out, ");\n");
449 void jna_limit_output(const char *filename)
451 output_limit *limit = xmalloc(sizeof(limit[0]));
452 limit->filename = filename;
454 limit->next = output_limits;
455 output_limits = limit;
458 void jna_set_libname(const char *new_libname)
460 libname = new_libname;
463 void write_jna_decls(FILE *output, const translation_unit_t *unit)
466 global_scope = &unit->scope;
468 pset_new_init(&avoid_symbols);
471 fprintf(out, "/* WARNING: Automatically generated file */\n");
472 fputs("import com.sun.jna.Native;\n", out);
473 fputs("import com.sun.jna.Pointer;\n", out);
476 const char *register_libname = libname;
477 if (register_libname == NULL)
478 register_libname = "library";
480 /* TODO: where to get the name from? */
481 fputs("public class binding {\n", out);
482 fputs("\tstatic {\n", out);
483 fprintf(out, "\t\tNative.register(\"%s\");\n", register_libname);
487 /* read the avoid list */
488 FILE *avoid = fopen("avoid.config", "r");
490 while (!feof(avoid)) {
492 char *res = fgets(buf, sizeof(buf), avoid);
498 size_t len = strlen(buf);
499 if (buf[len-1] == '\n')
502 char *str = malloc(len+1);
503 memcpy(str, buf, len+1);
504 symbol_t *symbol = symbol_table_insert(str);
505 pset_new_insert(&avoid_symbols, symbol);
510 /* write structs,unions + enums */
511 entity_t *entity = unit->scope.entities;
512 for ( ; entity != NULL; entity = entity->base.next) {
513 if (entity->kind == ENTITY_ENUM) {
514 if (find_enum_typedef(&entity->enume) != NULL)
516 write_enum(entity->base.symbol, &entity->enume);
517 } else if (entity->kind == ENTITY_TYPEDEF) {
518 type_t *type = entity->typedefe.type;
519 if (type->kind == TYPE_ENUM) {
520 write_enum(entity->base.symbol, type->enumt.enume);
525 if (is_type_compound(type)) {
526 write_compound(entity->base.symbol, &type->compound);
531 /* write functions */
532 entity = unit->scope.entities;
533 for ( ; entity != NULL; entity = entity->base.next) {
534 if (entity->kind != ENTITY_FUNCTION)
536 const char *input_name = entity->base.source_position.input_name;
537 if (is_system_header(input_name))
539 if (entity->function.elf_visibility != ELF_VISIBILITY_DEFAULT)
541 if (output_limits != NULL) {
542 bool in_limits = false;
543 for (output_limit *limit = output_limits; limit != NULL;
544 limit = limit->next) {
545 if (streq(limit->filename, input_name)) {
554 if (pset_new_contains(&avoid_symbols, entity->base.symbol))
556 write_function(entity);
561 pset_new_destroy(&avoid_symbols);