2 * This file is part of cparser.
3 * Copyright (C) 2007-2008 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 "write_jna.h"
31 #include "adt/error.h"
32 #include <libfirm/adt/pset_new.h>
34 static const scope_t *global_scope;
36 static pset_new_t avoid_symbols;
38 static void write_type(type_t *type);
40 static bool is_system_header(const char *fname)
42 return strncmp(fname, "/usr/include", 12) == 0;
45 static const char *fix_builtin_names(const char *name)
47 if (strcmp(name, "class") == 0) {
49 } else if(strcmp(name, "this") == 0) {
51 } else if(strcmp(name, "public") == 0) {
53 } else if(strcmp(name, "protected") == 0) {
55 } else if(strcmp(name, "private") == 0) {
57 } else if(strcmp(name, "final") == 0) {
60 /* TODO put all reserved names here */
64 static const char *get_atomic_type_string(const atomic_type_kind_t type)
67 case ATOMIC_TYPE_VOID: return "void";
68 case ATOMIC_TYPE_CHAR: return "byte";
69 case ATOMIC_TYPE_SCHAR: return "byte";
70 case ATOMIC_TYPE_UCHAR: return "byte";
71 case ATOMIC_TYPE_SHORT: return "short";
72 case ATOMIC_TYPE_USHORT: return "short";
73 case ATOMIC_TYPE_INT: return "int";
74 case ATOMIC_TYPE_UINT: return "int";
75 case ATOMIC_TYPE_LONG: return "NativeLong";
76 case ATOMIC_TYPE_ULONG: return "NativeLong";
77 case ATOMIC_TYPE_LONGLONG: return "long";
78 case ATOMIC_TYPE_ULONGLONG: return "long";
79 case ATOMIC_TYPE_FLOAT: return "float";
80 case ATOMIC_TYPE_DOUBLE: return "double";
81 case ATOMIC_TYPE_LONG_DOUBLE: return "double";
82 case ATOMIC_TYPE_BOOL: return "boolean";
83 default: panic("unsupported atomic type");
87 static void write_atomic_type(const atomic_type_t *type)
89 fputs(get_atomic_type_string(type->akind), out);
92 static void write_pointer_type(const pointer_type_t *type)
94 type_t *points_to = skip_typeref(type->points_to);
95 if (is_type_atomic(points_to, ATOMIC_TYPE_CHAR)) {
99 fputs("Pointer", out);
102 static entity_t *find_typedef(const type_t *type)
104 /* first: search for a matching typedef in the global type... */
105 entity_t *entity = global_scope->entities;
106 for ( ; entity != NULL; entity = entity->base.next) {
107 if (entity->kind != ENTITY_TYPEDEF)
109 if (entity->typedefe.type == type)
116 static entity_t *find_enum_typedef(const enum_t *enume)
118 /* first: search for a matching typedef in the global type... */
119 entity_t *entity = global_scope->entities;
120 for ( ; entity != NULL; entity = entity->base.next) {
121 if (entity->kind != ENTITY_TYPEDEF)
123 type_t *type = entity->typedefe.type;
124 if (type->kind != TYPE_ENUM)
127 enum_t *e_entity = type->enumt.enume;
128 if (e_entity == enume)
135 static void write_compound_type(const compound_type_t *type)
137 entity_t *entity = find_typedef((const type_t*) type);
139 fputs(entity->base.symbol->string, out);
143 /* does the struct have a name? */
144 symbol_t *symbol = type->compound->base.symbol;
146 /* TODO: make sure we create a struct for it... */
147 fputs(symbol->string, out);
150 /* TODO: create a struct and use its name here... */
151 fputs("/* TODO anonymous struct */byte", out);
154 static void write_enum_name(const enum_type_t *type)
156 entity_t *entity = find_typedef((const type_t*) type);
157 if (entity != NULL) {
158 fputs(entity->base.symbol->string, out);
162 /* does the enum have a name? */
163 symbol_t *symbol = type->enume->base.symbol;
164 if (symbol != NULL) {
165 /* TODO: make sure we create an enum for it... */
166 fputs(symbol->string, out);
170 /* now we have a problem as we don't know how we'll call the anonymous
172 panic("can't reference entries from anonymous enums yet");
175 static void write_enum_type(const enum_type_t *type)
177 entity_t *entity = find_typedef((const type_t*) type);
178 if (entity != NULL) {
179 fprintf(out, "/* %s */int", entity->base.symbol->string);
183 /* does the enum have a name? */
184 symbol_t *symbol = type->enume->base.symbol;
185 if (symbol != NULL) {
186 /* TODO: make sure we create an enum for it... */
187 fprintf(out, "/* %s */int", symbol->string);
190 fprintf(out, "/* anonymous enum */int");
193 static void write_type(type_t *type)
195 type = skip_typeref(type);
198 write_atomic_type(&type->atomic);
201 write_pointer_type(&type->pointer);
203 case TYPE_COMPOUND_UNION:
204 case TYPE_COMPOUND_STRUCT:
205 write_compound_type(&type->compound);
208 write_enum_type(&type->enumt);
211 write_type(type->builtin.real_type);
217 panic("invalid type found");
224 fprintf(out, "/* TODO type */Pointer");
230 static void write_compound_entry(const entity_t *entity)
232 fprintf(out, "\t%s : ", entity->base.symbol->string);
233 write_type(entity->declaration.type);
237 static void write_compound(const symbol_t *symbol, const compound_type_t *type)
239 fprintf(out, "%s %s:\n",
240 type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
243 const entity_t *entity = type->compound->members.entities;
244 for ( ; entity != NULL; entity = entity->base.next) {
245 write_compound_entry(entity);
252 static void write_expression(const expression_t *expression);
254 static void write_unary_expression(const unary_expression_t *expression)
256 switch(expression->base.kind) {
257 case EXPR_UNARY_NEGATE:
263 case EXPR_UNARY_CAST_IMPLICIT:
264 write_expression(expression->value);
267 panic("unimeplemented unary expression found");
269 write_expression(expression->value);
272 static void write_binary_expression(const binary_expression_t *expression)
275 write_expression(expression->left);
276 switch(expression->base.kind) {
277 case EXPR_BINARY_BITWISE_OR: fputs("|", out); break;
278 case EXPR_BINARY_BITWISE_AND: fputs("&", out); break;
279 case EXPR_BINARY_BITWISE_XOR: fputs("^", out); break;
280 case EXPR_BINARY_SHIFTLEFT: fputs("<<", out); break;
281 case EXPR_BINARY_SHIFTRIGHT: fputs(">>", out); break;
282 case EXPR_BINARY_ADD: fputs("+", out); break;
283 case EXPR_BINARY_SUB: fputs("-", out); break;
284 case EXPR_BINARY_MUL: fputs("*", out); break;
285 case EXPR_BINARY_DIV: fputs("/", out); break;
287 panic("unimplemented binexpr");
289 write_expression(expression->right);
293 static void write_expression(const expression_t *expression)
295 const const_expression_t *constant;
297 switch(expression->kind) {
299 constant = &expression->conste;
300 if(is_type_integer(expression->base.type)) {
301 fprintf(out, "%lld", constant->v.int_value);
303 fprintf(out, "%Lf", constant->v.float_value);
306 case EXPR_REFERENCE_ENUM_VALUE: {
307 /* UHOH... hacking */
308 entity_t *entity = expression->reference.entity;
309 write_enum_name(& entity->enum_value.enum_type->enumt);
310 fprintf(out, ".%s.val", entity->base.symbol->string);
314 write_unary_expression(&expression->unary);
317 write_binary_expression(&expression->binary);
320 panic("not implemented expression");
324 static void write_enum(const symbol_t *symbol, const enum_t *entity)
329 if (symbol == NULL) {
330 static int lastenum = 0;
331 snprintf(buf, sizeof(buf), "AnonEnum%d", lastenum++);
334 name = symbol->string;
337 fprintf(out, "\tpublic static enum %s {\n", name);
339 entity_t *entry = entity->base.next;
340 for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
341 entry = entry->base.next) {
342 fprintf(out, "\t\t%s", entry->base.symbol->string);
344 if(entry->enum_value.value != NULL) {
345 write_expression(entry->enum_value.value);
348 if (entry->base.next != NULL
349 && entry->base.next->kind == ENTITY_ENUM_VALUE) {
355 fprintf(out, "\t\tpublic final int val;\n");
356 fprintf(out, "\t\tprivate static class C { static int next_val; }\n\n");
357 fprintf(out, "\t\t%s(int val) {\n", name);
358 fprintf(out, "\t\t\tthis.val = val;\n");
359 fprintf(out, "\t\t\tC.next_val = val + 1;\n");
360 fprintf(out, "\t\t}\n");
361 fprintf(out, "\t\t%s() {\n", name);
362 fprintf(out, "\t\t\tthis.val = C.next_val++;\n");
363 fprintf(out, "\t\t}\n");
364 fprintf(out, "\t\t\n");
365 fprintf(out, "\t\tpublic static %s getEnum(int val) {\n", name);
366 fprintf(out, "\t\t\tfor(%s entry : values()) {\n", name);
367 fprintf(out, "\t\t\t\tif (val == entry.val)\n");
368 fprintf(out, "\t\t\t\t\treturn entry;\n");
369 fprintf(out, "\t\t\t}\n");
370 fprintf(out, "\t\t\treturn null;\n");
371 fprintf(out, "\t\t}\n");
372 fprintf(out, "\t}\n");
376 static void write_variable(const entity_t *entity)
378 fprintf(out, "var %s : ", entity->base.symbol->string);
379 write_type(entity->declaration.type);
384 static void write_function(const entity_t *entity)
386 if (entity->function.statement != NULL) {
387 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
388 entity->base.symbol->string);
393 const function_type_t *function_type
394 = (const function_type_t*) entity->declaration.type;
397 type_t *return_type = skip_typeref(function_type->return_type);
398 write_type(return_type);
399 fprintf(out, " %s(", entity->base.symbol->string);
401 entity_t *parameter = entity->function.parameters.entities;
404 for( ; parameter != NULL; parameter = parameter->base.next) {
405 assert(parameter->kind == ENTITY_PARAMETER);
411 write_type(parameter->declaration.type);
412 if(parameter->base.symbol != NULL) {
413 fprintf(out, " %s", fix_builtin_names(parameter->base.symbol->string));
415 fprintf(out, " _%d", n++);
418 if(function_type->variadic) {
424 fputs("Object ... args", out);
426 fprintf(out, ");\n");
430 void write_jna_decls(FILE *output, const translation_unit_t *unit)
433 global_scope = &unit->scope;
435 pset_new_init(&avoid_symbols);
438 type_set_output(out);
439 fprintf(out, "/* WARNING: Automatically generated file */\n");
440 fputs("import com.sun.jna.Library;\n", out);
441 fputs("import com.sun.jna.Native;\n", out);
442 fputs("import com.sun.jna.Platform;\n", out);
443 fputs("import com.sun.jna.Pointer;\n", out);
444 fputs("import com.sun.jna.NativeLong;\n", out);
447 /* TODO: where to get the name from? */
448 fputs("public interface binding extends Library {\n", out);
450 /* read the avoid list */
451 FILE *avoid = fopen("avoid.config", "r");
453 while (!feof(avoid)) {
455 fgets(buf, sizeof(buf), avoid);
456 size_t len = strlen(buf);
457 if (buf[len-1] == '\n')
462 char *str = malloc(len);
463 memcpy(str, buf, len);
464 symbol_t *symbol = symbol_table_insert(str);
465 pset_new_insert(&avoid_symbols, symbol);
470 /* write structs,unions + enums */
471 entity_t *entity = unit->scope.entities;
472 for( ; entity != NULL; entity = entity->base.next) {
473 if (entity->kind == ENTITY_ENUM) {
474 if (find_enum_typedef(&entity->enume) != NULL)
476 write_enum(entity->base.symbol, &entity->enume);
477 } else if (entity->kind == ENTITY_TYPEDEF) {
478 type_t *type = entity->typedefe.type;
479 if (type->kind == TYPE_ENUM) {
480 write_enum(entity->base.symbol, type->enumt.enume);
485 if(type->kind == TYPE_COMPOUND_STRUCT
486 || type->kind == TYPE_COMPOUND_UNION) {
487 write_compound(entity->base.symbol, &type->compound);
492 /* write functions */
493 entity = unit->scope.entities;
494 for( ; entity != NULL; entity = entity->base.next) {
495 if (entity->kind != ENTITY_FUNCTION)
497 if (is_system_header(entity->base.source_position.input_name))
500 if (pset_new_contains(&avoid_symbols, entity->base.symbol))
502 write_function(entity);
507 pset_new_destroy(&avoid_symbols);