2 * This file is part of cparser.
3 * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
10 #include "adt/strutil.h"
11 #include "write_jna.h"
18 #include "adt/error.h"
19 #include "adt/xmalloc.h"
20 #include "adt/pset_new.h"
21 #include "separator_t.h"
23 typedef struct output_limit {
25 struct output_limit *next;
28 static const scope_t *global_scope;
30 static pset_new_t avoid_symbols;
31 static output_limit *output_limits;
32 static const char *libname;
34 static const char *fix_builtin_names(const char *name)
36 if (streq(name, "class")) {
38 } else if (streq(name, "this")) {
40 } else if (streq(name, "public")) {
42 } else if (streq(name, "protected")) {
44 } else if (streq(name, "private")) {
46 } else if (streq(name, "final")) {
49 /* TODO put all reserved names here */
53 static const char *get_atomic_type_string(const atomic_type_kind_t type)
56 case ATOMIC_TYPE_VOID: return "void";
57 case ATOMIC_TYPE_CHAR: return "byte";
58 case ATOMIC_TYPE_SCHAR: return "byte";
59 case ATOMIC_TYPE_UCHAR: return "byte";
60 case ATOMIC_TYPE_SHORT: return "short";
61 case ATOMIC_TYPE_USHORT: return "short";
62 case ATOMIC_TYPE_INT: return "int";
63 case ATOMIC_TYPE_UINT: return "int";
64 case ATOMIC_TYPE_LONG: return "com.sun.jna.NativeLong";
65 case ATOMIC_TYPE_ULONG: return "com.sun.jna.NativeLong";
66 case ATOMIC_TYPE_LONGLONG: return "long";
67 case ATOMIC_TYPE_ULONGLONG: return "long";
68 case ATOMIC_TYPE_FLOAT: return "float";
69 case ATOMIC_TYPE_DOUBLE: return "double";
70 case ATOMIC_TYPE_BOOL: return "boolean";
71 default: panic("unsupported atomic type");
75 static void write_atomic_type(const atomic_type_t *type)
77 fputs(get_atomic_type_string(type->akind), out);
80 static void write_pointer_type(const pointer_type_t *type)
82 type_t *points_to = skip_typeref(type->points_to);
83 if (is_type_atomic(points_to, ATOMIC_TYPE_CHAR)) {
87 if (is_type_pointer(points_to)) {
89 fputs("java.nio.Buffer", out);
92 fputs("Pointer", out);
95 static entity_t *find_typedef(const type_t *type)
97 /* first: search for a matching typedef in the global type... */
98 entity_t *entity = global_scope->entities;
99 for ( ; entity != NULL; entity = entity->base.next) {
100 if (entity->kind != ENTITY_TYPEDEF)
102 if (entity->typedefe.type == type)
109 static entity_t *find_enum_typedef(const enum_t *enume)
111 /* first: search for a matching typedef in the global type... */
112 entity_t *entity = global_scope->entities;
113 for ( ; entity != NULL; entity = entity->base.next) {
114 if (entity->kind != ENTITY_TYPEDEF)
116 type_t *type = entity->typedefe.type;
117 if (type->kind != TYPE_ENUM)
120 enum_t *e_entity = type->enumt.enume;
121 if (e_entity == enume)
128 static void write_compound_type(const compound_type_t *type)
130 entity_t *entity = find_typedef((const type_t*) type);
132 fputs(entity->base.symbol->string, out);
136 /* does the struct have a name? */
137 symbol_t *symbol = type->compound->base.symbol;
139 /* TODO: make sure we create a struct for it... */
140 fputs(symbol->string, out);
143 /* TODO: create a struct and use its name here... */
144 fputs("/* TODO anonymous struct */byte", out);
147 static void write_enum_name(const enum_type_t *type)
149 entity_t *entity = find_typedef((const type_t*) type);
150 if (entity != NULL) {
151 fputs(entity->base.symbol->string, out);
155 /* does the enum have a name? */
156 symbol_t *symbol = type->enume->base.symbol;
157 if (symbol != NULL) {
158 /* TODO: make sure we create an enum for it... */
159 fputs(symbol->string, out);
163 /* now we have a problem as we don't know how we'll call the anonymous
165 panic("can't reference entries from anonymous enums yet");
168 static void write_enum_type(const enum_type_t *type)
170 entity_t *entity = find_typedef((const type_t*) type);
171 if (entity != NULL) {
172 fprintf(out, "/* %s */int", entity->base.symbol->string);
176 /* does the enum have a name? */
177 symbol_t *symbol = type->enume->base.symbol;
178 if (symbol != NULL) {
179 /* TODO: make sure we create an enum for it... */
180 fprintf(out, "/* %s */int", symbol->string);
183 fprintf(out, "/* anonymous enum */int");
186 static void write_type(type_t *type)
188 type = skip_typeref(type);
191 write_atomic_type(&type->atomic);
194 write_pointer_type(&type->pointer);
196 case TYPE_COMPOUND_UNION:
197 case TYPE_COMPOUND_STRUCT:
198 write_compound_type(&type->compound);
201 write_enum_type(&type->enumt);
206 panic("invalid type");
212 fprintf(out, "/* TODO type */Pointer");
218 static void write_compound_entry(const entity_t *entity)
220 fprintf(out, "\t%s : ", entity->base.symbol->string);
221 write_type(entity->declaration.type);
225 static void write_compound(const symbol_t *symbol, const compound_type_t *type)
227 fprintf(out, "%s %s:\n",
228 type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
231 const entity_t *entity = type->compound->members.entities;
232 for ( ; entity != NULL; entity = entity->base.next) {
233 write_compound_entry(entity);
240 static void write_expression(const expression_t *expression);
242 static void write_unary_expression(const unary_expression_t *expression)
244 switch(expression->base.kind) {
245 case EXPR_UNARY_NEGATE:
251 case EXPR_UNARY_CAST:
252 write_expression(expression->value);
255 panic("unimplemented unary expression");
257 write_expression(expression->value);
260 static void write_binary_expression(const binary_expression_t *expression)
263 write_expression(expression->left);
265 switch(expression->base.kind) {
266 case EXPR_BINARY_BITWISE_OR: fputs("|", out); break;
267 case EXPR_BINARY_BITWISE_AND: fputs("&", out); break;
268 case EXPR_BINARY_BITWISE_XOR: fputs("^", out); break;
269 case EXPR_BINARY_SHIFTLEFT: fputs("<<", out); break;
270 case EXPR_BINARY_SHIFTRIGHT: fputs(">>", out); break;
271 case EXPR_BINARY_ADD: fputs("+", out); break;
272 case EXPR_BINARY_SUB: fputs("-", out); break;
273 case EXPR_BINARY_MUL: fputs("*", out); break;
274 case EXPR_BINARY_DIV: fputs("/", out); break;
276 panic("unimplemented binexpr");
279 write_expression(expression->right);
283 static void write_integer(const literal_expression_t *literal)
285 for (const char *c = literal->value.begin; c != literal->suffix; ++c) {
290 static void write_expression(const expression_t *expression)
293 switch(expression->kind) {
294 case EXPR_LITERAL_INTEGER:
295 write_integer(&expression->literal);
298 case EXPR_ENUM_CONSTANT: {
299 /* UHOH... hacking */
300 entity_t *entity = expression->reference.entity;
301 write_enum_name(& entity->enum_value.enum_type->enumt);
302 fprintf(out, ".%s.val", entity->base.symbol->string);
305 case EXPR_UNARY_CASES:
306 write_unary_expression(&expression->unary);
308 case EXPR_BINARY_CASES:
309 write_binary_expression(&expression->binary);
312 panic("not implemented expression");
316 static void write_enum(const symbol_t *symbol, const enum_t *entity)
321 if (symbol == NULL) {
322 static int lastenum = 0;
323 snprintf(buf, sizeof(buf), "AnonEnum%d", lastenum++);
326 name = symbol->string;
329 fprintf(out, "\tpublic static enum %s {\n", name);
331 entity_t *entry = entity->base.next;
332 for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
333 entry = entry->base.next) {
334 fprintf(out, "\t\t%s", entry->base.symbol->string);
336 if(entry->enum_value.value != NULL) {
337 write_expression(entry->enum_value.value);
340 if (entry->base.next != NULL
341 && entry->base.next->kind == ENTITY_ENUM_VALUE) {
347 fprintf(out, "\t\tpublic final int val;\n");
349 fprintf(out, "\t\tprivate static class C {\n");
350 fprintf(out, "\t\t\tstatic int next_val;\n");
351 fprintf(out, "\t\t}\n");
353 fprintf(out, "\t\t%s(int val) {\n", name);
354 fprintf(out, "\t\t\tthis.val = val;\n");
355 fprintf(out, "\t\t\tC.next_val = val + 1;\n");
356 fprintf(out, "\t\t}\n");
358 fprintf(out, "\t\t%s() {\n", name);
359 fprintf(out, "\t\t\tthis.val = C.next_val++;\n");
360 fprintf(out, "\t\t}\n");
362 fprintf(out, "\t\tpublic static %s getEnum(int val) {\n", name);
363 fprintf(out, "\t\t\tfor (%s entry : values()) {\n", name);
364 fprintf(out, "\t\t\t\tif (val == entry.val)\n");
365 fprintf(out, "\t\t\t\t\treturn entry;\n");
366 fprintf(out, "\t\t\t}\n");
367 fprintf(out, "\t\t\treturn null;\n");
368 fprintf(out, "\t\t}\n");
369 fprintf(out, "\t}\n");
374 static void write_variable(const entity_t *entity)
376 fprintf(out, "var %s : ", entity->base.symbol->string);
377 write_type(entity->declaration.type);
382 static void write_function(const entity_t *entity)
384 if (entity->function.body != NULL) {
385 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
386 entity->base.symbol->string);
391 const function_type_t *function_type
392 = (const function_type_t*) entity->declaration.type;
395 fprintf(out, "\tpublic static native ");
396 type_t *return_type = skip_typeref(function_type->return_type);
397 write_type(return_type);
398 fprintf(out, " %s(", entity->base.symbol->string);
400 entity_t *parameter = entity->function.parameters.entities;
401 separator_t sep = { "", ", " };
403 for ( ; parameter != NULL; parameter = parameter->base.next) {
404 assert(parameter->kind == ENTITY_PARAMETER);
405 fputs(sep_next(&sep), out);
406 write_type(parameter->declaration.type);
407 if(parameter->base.symbol != NULL) {
408 fprintf(out, " %s", fix_builtin_names(parameter->base.symbol->string));
410 fprintf(out, " _%d", n++);
413 if(function_type->variadic) {
414 fputs(sep_next(&sep), out);
415 fputs("Object ... args", out);
417 fprintf(out, ");\n");
420 void jna_limit_output(const char *filename)
422 output_limit *limit = xmalloc(sizeof(limit[0]));
423 limit->filename = filename;
425 limit->next = output_limits;
426 output_limits = limit;
429 void jna_set_libname(const char *new_libname)
431 libname = new_libname;
434 void write_jna_decls(FILE *output, const translation_unit_t *unit)
437 global_scope = &unit->scope;
439 pset_new_init(&avoid_symbols);
442 fprintf(out, "/* WARNING: Automatically generated file */\n");
443 fputs("import com.sun.jna.Native;\n", out);
444 fputs("import com.sun.jna.Pointer;\n", out);
447 const char *register_libname = libname;
448 if (register_libname == NULL)
449 register_libname = "library";
451 /* TODO: where to get the name from? */
452 fputs("public class binding {\n", out);
453 fputs("\tstatic {\n", out);
454 fprintf(out, "\t\tNative.register(\"%s\");\n", register_libname);
458 /* read the avoid list */
459 FILE *avoid = fopen("avoid.config", "r");
461 while (!feof(avoid)) {
463 char *res = fgets(buf, sizeof(buf), avoid);
469 size_t len = strlen(buf);
470 if (buf[len-1] == '\n')
473 char *str = malloc(len+1);
474 memcpy(str, buf, len+1);
475 symbol_t *symbol = symbol_table_insert(str);
476 pset_new_insert(&avoid_symbols, symbol);
481 /* write structs,unions + enums */
482 entity_t *entity = unit->scope.entities;
483 for ( ; entity != NULL; entity = entity->base.next) {
484 if (entity->kind == ENTITY_ENUM) {
485 if (find_enum_typedef(&entity->enume) != NULL)
487 write_enum(entity->base.symbol, &entity->enume);
488 } else if (entity->kind == ENTITY_TYPEDEF) {
489 type_t *type = entity->typedefe.type;
490 if (type->kind == TYPE_ENUM) {
491 write_enum(entity->base.symbol, type->enumt.enume);
496 if (is_type_compound(type)) {
497 write_compound(entity->base.symbol, &type->compound);
502 /* write functions */
503 entity = unit->scope.entities;
504 for ( ; entity != NULL; entity = entity->base.next) {
505 if (entity->kind != ENTITY_FUNCTION)
507 if (entity->base.pos.is_system_header)
509 if (entity->function.elf_visibility != ELF_VISIBILITY_DEFAULT)
511 if (output_limits != NULL) {
512 bool in_limits = false;
513 char const *const input_name = entity->base.pos.input_name;
514 for (output_limit *limit = output_limits; limit != NULL;
515 limit = limit->next) {
516 if (streq(limit->filename, input_name)) {
525 if (pset_new_contains(&avoid_symbols, entity->base.symbol))
527 write_function(entity);
532 pset_new_destroy(&avoid_symbols);