ast2firm: Implement casting from complex to real types.
[cparser] / wrappergen / write_jna.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
4  */
5 #include <config.h>
6
7 #include <errno.h>
8 #include <string.h>
9
10 #include "adt/strutil.h"
11 #include "write_jna.h"
12 #include "symbol_t.h"
13 #include "ast_t.h"
14 #include "type_t.h"
15 #include "entity_t.h"
16 #include "type.h"
17 #include "printer.h"
18 #include "adt/error.h"
19 #include "adt/xmalloc.h"
20 #include "adt/pset_new.h"
21 #include "separator_t.h"
22
23 typedef struct output_limit {
24         const char          *filename;
25         struct output_limit *next;
26 } output_limit;
27
28 static const scope_t *global_scope;
29 static FILE          *out;
30 static pset_new_t     avoid_symbols;
31 static output_limit  *output_limits;
32 static const char    *libname;
33
34 static const char *fix_builtin_names(const char *name)
35 {
36 #define FIX(x) if (streq(name, x)) return "_" x
37         FIX("class");
38         FIX("final");
39         FIX("private");
40         FIX("protected");
41         FIX("public");
42         FIX("this");
43         /* TODO put all reserved names here */
44 #undef FIX
45         return name;
46 }
47
48 static const char *get_atomic_type_string(const atomic_type_kind_t type)
49 {
50         switch(type) {
51         case ATOMIC_TYPE_VOID:        return "void";
52         case ATOMIC_TYPE_CHAR:        return "byte";
53         case ATOMIC_TYPE_SCHAR:       return "byte";
54         case ATOMIC_TYPE_UCHAR:       return "byte";
55         case ATOMIC_TYPE_SHORT:       return "short";
56         case ATOMIC_TYPE_USHORT:      return "short";
57         case ATOMIC_TYPE_INT:         return "int";
58         case ATOMIC_TYPE_UINT:        return "int";
59         case ATOMIC_TYPE_LONG:        return "com.sun.jna.NativeLong";
60         case ATOMIC_TYPE_ULONG:       return "com.sun.jna.NativeLong";
61         case ATOMIC_TYPE_LONGLONG:    return "long";
62         case ATOMIC_TYPE_ULONGLONG:   return "long";
63         case ATOMIC_TYPE_FLOAT:       return "float";
64         case ATOMIC_TYPE_DOUBLE:      return "double";
65         case ATOMIC_TYPE_BOOL:        return "boolean";
66         default:                      panic("unsupported atomic type");
67         }
68 }
69
70 static void write_atomic_type(const atomic_type_t *type)
71 {
72         fputs(get_atomic_type_string(type->akind), out);
73 }
74
75 static void write_pointer_type(const pointer_type_t *type)
76 {
77         type_t *points_to = skip_typeref(type->points_to);
78         if (is_type_atomic(points_to, ATOMIC_TYPE_CHAR)) {
79                 fputs("String", out);
80                 return;
81         }
82         if (is_type_pointer(points_to)) {
83                 /* hack... */
84                 fputs("java.nio.Buffer", out);
85                 return;
86         }
87         fputs("Pointer", out);
88 }
89
90 static entity_t *find_typedef(const type_t *type)
91 {
92         /* first: search for a matching typedef in the global type... */
93         entity_t *entity = global_scope->entities;
94         for ( ; entity != NULL; entity = entity->base.next) {
95                 if (entity->kind != ENTITY_TYPEDEF)
96                         continue;
97                 if (entity->typedefe.type == type)
98                         break;
99         }
100
101         return entity;
102 }
103
104 static entity_t *find_enum_typedef(const enum_t *enume)
105 {
106         /* first: search for a matching typedef in the global type... */
107         entity_t *entity = global_scope->entities;
108         for ( ; entity != NULL; entity = entity->base.next) {
109                 if (entity->kind != ENTITY_TYPEDEF)
110                         continue;
111                 type_t *type = entity->typedefe.type;
112                 if (type->kind != TYPE_ENUM)
113                         continue;
114
115                 enum_t *e_entity = type->enumt.enume;
116                 if (e_entity == enume)
117                         break;
118         }
119
120         return entity;
121 }
122
123 static void write_compound_type(const compound_type_t *type)
124 {
125         entity_t *entity = find_typedef((const type_t*) type);
126         if(entity != NULL) {
127                 fputs(entity->base.symbol->string, out);
128                 return;
129         }
130
131         /* does the struct have a name? */
132         symbol_t *symbol = type->compound->base.symbol;
133         if(symbol != NULL) {
134                 /* TODO: make sure we create a struct for it... */
135                 fputs(symbol->string, out);
136                 return;
137         }
138         /* TODO: create a struct and use its name here... */
139         fputs("/* TODO anonymous struct */byte", out);
140 }
141
142 static void write_enum_name(const enum_type_t *type)
143 {
144         entity_t *entity = find_typedef((const type_t*) type);
145         if (entity != NULL) {
146                 fputs(entity->base.symbol->string, out);
147                 return;
148         }
149
150         /* does the enum have a name? */
151         symbol_t *symbol = type->enume->base.symbol;
152         if (symbol != NULL) {
153                 /* TODO: make sure we create an enum for it... */
154                 fputs(symbol->string, out);
155                 return;
156         }
157
158         /* now we have a problem as we don't know how we'll call the anonymous
159          * enum */
160         panic("can't reference entries from anonymous enums yet");
161 }
162
163 static void write_enum_type(const enum_type_t *type)
164 {
165         entity_t *entity = find_typedef((const type_t*) type);
166         if (entity != NULL) {
167                 fprintf(out, "/* %s */int", entity->base.symbol->string);
168                 return;
169         }
170
171         /* does the enum have a name? */
172         symbol_t *symbol = type->enume->base.symbol;
173         if (symbol != NULL) {
174                 /* TODO: make sure we create an enum for it... */
175                 fprintf(out, "/* %s */int", symbol->string);
176                 return;
177         }
178         fprintf(out, "/* anonymous enum */int");
179 }
180
181 static void write_type(type_t *type)
182 {
183         type = skip_typeref(type);
184         switch(type->kind) {
185         case TYPE_ATOMIC:
186                 write_atomic_type(&type->atomic);
187                 return;
188         case TYPE_POINTER:
189                 write_pointer_type(&type->pointer);
190                 return;
191         case TYPE_COMPOUND_UNION:
192         case TYPE_COMPOUND_STRUCT:
193                 write_compound_type(&type->compound);
194                 return;
195         case TYPE_ENUM:
196                 write_enum_type(&type->enumt);
197                 return;
198         case TYPE_ERROR:
199         case TYPE_TYPEOF:
200         case TYPE_TYPEDEF:
201                 panic("invalid type");
202         case TYPE_ARRAY:
203         case TYPE_REFERENCE:
204         case TYPE_FUNCTION:
205         case TYPE_COMPLEX:
206         case TYPE_IMAGINARY:
207                 fprintf(out, "/* TODO type */Pointer");
208                 break;
209         }
210 }
211
212 #if 0
213 static void write_compound_entry(const entity_t *entity)
214 {
215         fprintf(out, "\t%s : ", entity->base.symbol->string);
216         write_type(entity->declaration.type);
217         fprintf(out, "\n");
218 }
219
220 static void write_compound(const symbol_t *symbol, const compound_type_t *type)
221 {
222         fprintf(out, "%s %s:\n",
223                 type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
224                         symbol->string);
225
226         const entity_t *entity = type->compound->members.entities;
227         for ( ; entity != NULL; entity = entity->base.next) {
228                 write_compound_entry(entity);
229         }
230
231         fprintf(out, "\n");
232 }
233 #endif
234
235 static void write_expression(const expression_t *expression);
236
237 static void write_unary_expression(const unary_expression_t *expression)
238 {
239         switch(expression->base.kind) {
240         case EXPR_UNARY_NEGATE:
241                 fputc('-', out);
242                 break;
243         case EXPR_UNARY_NOT:
244                 fputc('!', out);
245                 break;
246         case EXPR_UNARY_CAST:
247                 write_expression(expression->value);
248                 return;
249         default:
250                 panic("unimplemented unary expression");
251         }
252         write_expression(expression->value);
253 }
254
255 static void write_binary_expression(const binary_expression_t *expression)
256 {
257         fputs("(", out);
258         write_expression(expression->left);
259         fputc(' ', out);
260         switch(expression->base.kind) {
261         case EXPR_BINARY_BITWISE_OR:  fputs("|", out); break;
262         case EXPR_BINARY_BITWISE_AND: fputs("&", out); break;
263         case EXPR_BINARY_BITWISE_XOR: fputs("^", out); break;
264         case EXPR_BINARY_SHIFTLEFT:   fputs("<<", out); break;
265         case EXPR_BINARY_SHIFTRIGHT:  fputs(">>", out); break;
266         case EXPR_BINARY_ADD:         fputs("+", out); break;
267         case EXPR_BINARY_SUB:         fputs("-", out); break;
268         case EXPR_BINARY_MUL:         fputs("*", out); break;
269         case EXPR_BINARY_DIV:         fputs("/", out); break;
270         default:
271                 panic("unimplemented binexpr");
272         }
273         fputc(' ', out);
274         write_expression(expression->right);
275         fputs(")", out);
276 }
277
278 static void write_integer(const literal_expression_t *literal)
279 {
280         for (const char *c = literal->value.begin; c != literal->suffix; ++c) {
281                 fputc(*c, out);
282         }
283 }
284
285 static void write_expression(const expression_t *expression)
286 {
287         /* TODO */
288         switch(expression->kind) {
289         case EXPR_LITERAL_INTEGER:
290                 write_integer(&expression->literal);
291                 break;
292
293         case EXPR_ENUM_CONSTANT: {
294                 /* UHOH... hacking */
295                 entity_t *entity = expression->reference.entity;
296                 write_enum_name(& entity->enum_value.enum_type->enumt);
297                 fprintf(out, ".%s.val", entity->base.symbol->string);
298                 break;
299         }
300         case EXPR_UNARY_CASES:
301                 write_unary_expression(&expression->unary);
302                 break;
303         case EXPR_BINARY_CASES:
304                 write_binary_expression(&expression->binary);
305                 break;
306         default:
307                 panic("not implemented expression");
308         }
309 }
310
311 static void write_enum(const symbol_t *symbol, const enum_t *entity)
312 {
313         char buf[128];
314         const char *name;
315
316         if (symbol == NULL) {
317                 static int lastenum = 0;
318                 snprintf(buf, sizeof(buf), "AnonEnum%d", lastenum++);
319                 name = buf;
320         } else {
321                 name = symbol->string;
322         }
323
324         fprintf(out, "\tpublic static enum %s {\n", name);
325
326         entity_t *entry = entity->base.next;
327         for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
328                         entry = entry->base.next) {
329                 fprintf(out, "\t\t%s", entry->base.symbol->string);
330                 fprintf(out, "(");
331                 if(entry->enum_value.value != NULL) {
332                         write_expression(entry->enum_value.value);
333                 }
334                 fprintf(out, ")");
335                 if (entry->base.next != NULL
336                                 && entry->base.next->kind == ENTITY_ENUM_VALUE) {
337                         fputs(",\n", out);
338                 } else {
339                         fputs(";\n", out);
340                 }
341         }
342         fprintf(out, "\t\tpublic final int val;\n");
343         fprintf(out, "\n");
344         fprintf(out, "\t\tprivate static class C {\n");
345         fprintf(out, "\t\t\tstatic int next_val;\n");
346         fprintf(out, "\t\t}\n");
347         fprintf(out, "\n");
348         fprintf(out, "\t\t%s(int val) {\n", name);
349         fprintf(out, "\t\t\tthis.val = val;\n");
350         fprintf(out, "\t\t\tC.next_val = val + 1;\n");
351         fprintf(out, "\t\t}\n");
352         fprintf(out, "\n");
353         fprintf(out, "\t\t%s() {\n", name);
354         fprintf(out, "\t\t\tthis.val = C.next_val++;\n");
355         fprintf(out, "\t\t}\n");
356         fprintf(out, "\n");
357         fprintf(out, "\t\tpublic static %s getEnum(int val) {\n", name);
358         fprintf(out, "\t\t\tfor (%s entry : values()) {\n", name);
359         fprintf(out, "\t\t\t\tif (val == entry.val)\n");
360         fprintf(out, "\t\t\t\t\treturn entry;\n");
361         fprintf(out, "\t\t\t}\n");
362         fprintf(out, "\t\t\treturn null;\n");
363         fprintf(out, "\t\t}\n");
364         fprintf(out, "\t}\n");
365         fprintf(out, "\n");
366 }
367
368 #if 0
369 static void write_variable(const entity_t *entity)
370 {
371         fprintf(out, "var %s : ", entity->base.symbol->string);
372         write_type(entity->declaration.type);
373         fprintf(out, "\n");
374 }
375 #endif
376
377 static void write_function(const entity_t *entity)
378 {
379         if (entity->function.body != NULL) {
380                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
381                         entity->base.symbol->string);
382                 return;
383         }
384
385
386         const function_type_t *function_type
387                 = (const function_type_t*) entity->declaration.type;
388
389         fputc('\n', out);
390         fprintf(out, "\tpublic static native ");
391         type_t *return_type = skip_typeref(function_type->return_type);
392         write_type(return_type);
393         fprintf(out, " %s(", entity->base.symbol->string);
394
395         entity_t   *parameter = entity->function.parameters.entities;
396         separator_t sep       = { "", ", " };
397         int         n         = 0;
398         for ( ; parameter != NULL; parameter = parameter->base.next) {
399                 assert(parameter->kind == ENTITY_PARAMETER);
400                 fputs(sep_next(&sep), out);
401                 write_type(parameter->declaration.type);
402                 if(parameter->base.symbol != NULL) {
403                         fprintf(out, " %s", fix_builtin_names(parameter->base.symbol->string));
404                 } else {
405                         fprintf(out, " _%d", n++);
406                 }
407         }
408         if(function_type->variadic) {
409                 fputs(sep_next(&sep), out);
410                 fputs("Object ... args", out);
411         }
412         fprintf(out, ");\n");
413 }
414
415 void jna_limit_output(const char *filename)
416 {
417         output_limit *limit = xmalloc(sizeof(limit[0]));
418         limit->filename = filename;
419
420         limit->next   = output_limits;
421         output_limits = limit;
422 }
423
424 void jna_set_libname(const char *new_libname)
425 {
426         libname = new_libname;
427 }
428
429 void write_jna_decls(FILE *output, const translation_unit_t *unit)
430 {
431         out          = output;
432         global_scope = &unit->scope;
433
434         pset_new_init(&avoid_symbols);
435
436         print_to_file(out);
437         fprintf(out, "/* WARNING: Automatically generated file */\n");
438         fputs("import com.sun.jna.Native;\n", out);
439         fputs("import com.sun.jna.Pointer;\n", out);
440         fputs("\n", out);
441
442         const char *register_libname = libname;
443         if (register_libname == NULL)
444                 register_libname = "library";
445
446         /* TODO: where to get the name from? */
447         fputs("public class binding {\n", out);
448         fputs("\tstatic {\n", out);
449         fprintf(out, "\t\tNative.register(\"%s\");\n", register_libname);
450         fputs("\t}\n", out);
451         fputs("\n", out);
452
453         /* read the avoid list */
454         FILE *avoid = fopen("avoid.config", "r");
455         if (avoid != NULL) {
456                 while (!feof(avoid)) {
457                         char buf[1024];
458                         char *res = fgets(buf, sizeof(buf), avoid);
459                         if (res == NULL)
460                                 break;
461                         if (buf[0] == 0)
462                                 continue;
463
464                         size_t len = strlen(buf);
465                         if (buf[len-1] == '\n')
466                                 buf[len-1] = 0;
467
468                         char *str = malloc(len+1);
469                         memcpy(str, buf, len+1);
470                         symbol_t *symbol = symbol_table_insert(str);
471                         pset_new_insert(&avoid_symbols, symbol);
472                 }
473                 fclose(avoid);
474         }
475
476         /* write structs,unions + enums */
477         entity_t *entity = unit->scope.entities;
478         for ( ; entity != NULL; entity = entity->base.next) {
479                 if (entity->kind == ENTITY_ENUM) {
480                         if (find_enum_typedef(&entity->enume) != NULL)
481                                 continue;
482                         write_enum(entity->base.symbol, &entity->enume);
483                 } else if (entity->kind == ENTITY_TYPEDEF) {
484                         type_t *type = entity->typedefe.type;
485                         if (type->kind == TYPE_ENUM) {
486                                 write_enum(entity->base.symbol, type->enumt.enume);
487                         }
488                 }
489
490 #if 0
491                 if (is_type_compound(type)) {
492                         write_compound(entity->base.symbol, &type->compound);
493                 }
494 #endif
495         }
496
497         /* write functions */
498         entity = unit->scope.entities;
499         for ( ; entity != NULL; entity = entity->base.next) {
500                 if (entity->kind != ENTITY_FUNCTION)
501                         continue;
502                 if (entity->base.pos.is_system_header)
503                         continue;
504                 if (entity->function.elf_visibility != ELF_VISIBILITY_DEFAULT)
505                         continue;
506                 if (output_limits != NULL) {
507                         bool              in_limits  = false;
508                         char const *const input_name = entity->base.pos.input_name;
509                         for (output_limit *limit = output_limits; limit != NULL;
510                              limit = limit->next) {
511                             if (streq(limit->filename, input_name)) {
512                                         in_limits = true;
513                                         break;
514                                 }
515                         }
516                         if (!in_limits)
517                                 continue;
518                 }
519
520                 if (pset_new_contains(&avoid_symbols, entity->base.symbol))
521                         continue;
522                 write_function(entity);
523         }
524
525         fputs("}\n", out);
526
527         pset_new_destroy(&avoid_symbols);
528 }