write_jna: Properly check whether a declaration is in a system header.
[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         if (streq(name, "class")) {
37                 return "_class";
38         } else if (streq(name, "this")) {
39                 return "_this";
40         } else if (streq(name, "public")) {
41                 return "_public";
42         } else if (streq(name, "protected")) {
43                 return "_protected";
44         } else if (streq(name, "private")) {
45                 return "_private";
46         } else if (streq(name, "final")) {
47                 return "_final";
48         }
49         /* TODO put all reserved names here */
50         return name;
51 }
52
53 static const char *get_atomic_type_string(const atomic_type_kind_t type)
54 {
55         switch(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");
72         }
73 }
74
75 static void write_atomic_type(const atomic_type_t *type)
76 {
77         fputs(get_atomic_type_string(type->akind), out);
78 }
79
80 static void write_pointer_type(const pointer_type_t *type)
81 {
82         type_t *points_to = skip_typeref(type->points_to);
83         if (is_type_atomic(points_to, ATOMIC_TYPE_CHAR)) {
84                 fputs("String", out);
85                 return;
86         }
87         if (is_type_pointer(points_to)) {
88                 /* hack... */
89                 fputs("java.nio.Buffer", out);
90                 return;
91         }
92         fputs("Pointer", out);
93 }
94
95 static entity_t *find_typedef(const type_t *type)
96 {
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)
101                         continue;
102                 if (entity->typedefe.type == type)
103                         break;
104         }
105
106         return entity;
107 }
108
109 static entity_t *find_enum_typedef(const enum_t *enume)
110 {
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)
115                         continue;
116                 type_t *type = entity->typedefe.type;
117                 if (type->kind != TYPE_ENUM)
118                         continue;
119
120                 enum_t *e_entity = type->enumt.enume;
121                 if (e_entity == enume)
122                         break;
123         }
124
125         return entity;
126 }
127
128 static void write_compound_type(const compound_type_t *type)
129 {
130         entity_t *entity = find_typedef((const type_t*) type);
131         if(entity != NULL) {
132                 fputs(entity->base.symbol->string, out);
133                 return;
134         }
135
136         /* does the struct have a name? */
137         symbol_t *symbol = type->compound->base.symbol;
138         if(symbol != NULL) {
139                 /* TODO: make sure we create a struct for it... */
140                 fputs(symbol->string, out);
141                 return;
142         }
143         /* TODO: create a struct and use its name here... */
144         fputs("/* TODO anonymous struct */byte", out);
145 }
146
147 static void write_enum_name(const enum_type_t *type)
148 {
149         entity_t *entity = find_typedef((const type_t*) type);
150         if (entity != NULL) {
151                 fputs(entity->base.symbol->string, out);
152                 return;
153         }
154
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);
160                 return;
161         }
162
163         /* now we have a problem as we don't know how we'll call the anonymous
164          * enum */
165         panic("can't reference entries from anonymous enums yet");
166 }
167
168 static void write_enum_type(const enum_type_t *type)
169 {
170         entity_t *entity = find_typedef((const type_t*) type);
171         if (entity != NULL) {
172                 fprintf(out, "/* %s */int", entity->base.symbol->string);
173                 return;
174         }
175
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);
181                 return;
182         }
183         fprintf(out, "/* anonymous enum */int");
184 }
185
186 static void write_type(type_t *type)
187 {
188         type = skip_typeref(type);
189         switch(type->kind) {
190         case TYPE_ATOMIC:
191                 write_atomic_type(&type->atomic);
192                 return;
193         case TYPE_POINTER:
194                 write_pointer_type(&type->pointer);
195                 return;
196         case TYPE_COMPOUND_UNION:
197         case TYPE_COMPOUND_STRUCT:
198                 write_compound_type(&type->compound);
199                 return;
200         case TYPE_ENUM:
201                 write_enum_type(&type->enumt);
202                 return;
203         case TYPE_ERROR:
204         case TYPE_TYPEOF:
205         case TYPE_TYPEDEF:
206                 panic("invalid type");
207         case TYPE_ARRAY:
208         case TYPE_REFERENCE:
209         case TYPE_FUNCTION:
210         case TYPE_COMPLEX:
211         case TYPE_IMAGINARY:
212                 fprintf(out, "/* TODO type */Pointer");
213                 break;
214         }
215 }
216
217 #if 0
218 static void write_compound_entry(const entity_t *entity)
219 {
220         fprintf(out, "\t%s : ", entity->base.symbol->string);
221         write_type(entity->declaration.type);
222         fprintf(out, "\n");
223 }
224
225 static void write_compound(const symbol_t *symbol, const compound_type_t *type)
226 {
227         fprintf(out, "%s %s:\n",
228                 type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
229                         symbol->string);
230
231         const entity_t *entity = type->compound->members.entities;
232         for ( ; entity != NULL; entity = entity->base.next) {
233                 write_compound_entry(entity);
234         }
235
236         fprintf(out, "\n");
237 }
238 #endif
239
240 static void write_expression(const expression_t *expression);
241
242 static void write_unary_expression(const unary_expression_t *expression)
243 {
244         switch(expression->base.kind) {
245         case EXPR_UNARY_NEGATE:
246                 fputc('-', out);
247                 break;
248         case EXPR_UNARY_NOT:
249                 fputc('!', out);
250                 break;
251         case EXPR_UNARY_CAST:
252                 write_expression(expression->value);
253                 return;
254         default:
255                 panic("unimplemented unary expression");
256         }
257         write_expression(expression->value);
258 }
259
260 static void write_binary_expression(const binary_expression_t *expression)
261 {
262         fputs("(", out);
263         write_expression(expression->left);
264         fputc(' ', out);
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;
275         default:
276                 panic("unimplemented binexpr");
277         }
278         fputc(' ', out);
279         write_expression(expression->right);
280         fputs(")", out);
281 }
282
283 static void write_integer(const literal_expression_t *literal)
284 {
285         for (const char *c = literal->value.begin; c != literal->suffix; ++c) {
286                 fputc(*c, out);
287         }
288 }
289
290 static void write_expression(const expression_t *expression)
291 {
292         /* TODO */
293         switch(expression->kind) {
294         case EXPR_LITERAL_INTEGER:
295                 write_integer(&expression->literal);
296                 break;
297
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);
303                 break;
304         }
305         case EXPR_UNARY_CASES:
306                 write_unary_expression(&expression->unary);
307                 break;
308         case EXPR_BINARY_CASES:
309                 write_binary_expression(&expression->binary);
310                 break;
311         default:
312                 panic("not implemented expression");
313         }
314 }
315
316 static void write_enum(const symbol_t *symbol, const enum_t *entity)
317 {
318         char buf[128];
319         const char *name;
320
321         if (symbol == NULL) {
322                 static int lastenum = 0;
323                 snprintf(buf, sizeof(buf), "AnonEnum%d", lastenum++);
324                 name = buf;
325         } else {
326                 name = symbol->string;
327         }
328
329         fprintf(out, "\tpublic static enum %s {\n", name);
330
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);
335                 fprintf(out, "(");
336                 if(entry->enum_value.value != NULL) {
337                         write_expression(entry->enum_value.value);
338                 }
339                 fprintf(out, ")");
340                 if (entry->base.next != NULL
341                                 && entry->base.next->kind == ENTITY_ENUM_VALUE) {
342                         fputs(",\n", out);
343                 } else {
344                         fputs(";\n", out);
345                 }
346         }
347         fprintf(out, "\t\tpublic final int val;\n");
348         fprintf(out, "\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");
352         fprintf(out, "\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");
357         fprintf(out, "\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");
361         fprintf(out, "\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");
370         fprintf(out, "\n");
371 }
372
373 #if 0
374 static void write_variable(const entity_t *entity)
375 {
376         fprintf(out, "var %s : ", entity->base.symbol->string);
377         write_type(entity->declaration.type);
378         fprintf(out, "\n");
379 }
380 #endif
381
382 static void write_function(const entity_t *entity)
383 {
384         if (entity->function.body != NULL) {
385                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
386                         entity->base.symbol->string);
387                 return;
388         }
389
390
391         const function_type_t *function_type
392                 = (const function_type_t*) entity->declaration.type;
393
394         fputc('\n', out);
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);
399
400         entity_t   *parameter = entity->function.parameters.entities;
401         separator_t sep       = { "", ", " };
402         int         n         = 0;
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));
409                 } else {
410                         fprintf(out, " _%d", n++);
411                 }
412         }
413         if(function_type->variadic) {
414                 fputs(sep_next(&sep), out);
415                 fputs("Object ... args", out);
416         }
417         fprintf(out, ");\n");
418 }
419
420 void jna_limit_output(const char *filename)
421 {
422         output_limit *limit = xmalloc(sizeof(limit[0]));
423         limit->filename = filename;
424
425         limit->next   = output_limits;
426         output_limits = limit;
427 }
428
429 void jna_set_libname(const char *new_libname)
430 {
431         libname = new_libname;
432 }
433
434 void write_jna_decls(FILE *output, const translation_unit_t *unit)
435 {
436         out          = output;
437         global_scope = &unit->scope;
438
439         pset_new_init(&avoid_symbols);
440
441         print_to_file(out);
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);
445         fputs("\n", out);
446
447         const char *register_libname = libname;
448         if (register_libname == NULL)
449                 register_libname = "library";
450
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);
455         fputs("\t}\n", out);
456         fputs("\n", out);
457
458         /* read the avoid list */
459         FILE *avoid = fopen("avoid.config", "r");
460         if (avoid != NULL) {
461                 while (!feof(avoid)) {
462                         char buf[1024];
463                         char *res = fgets(buf, sizeof(buf), avoid);
464                         if (res == NULL)
465                                 break;
466                         if (buf[0] == 0)
467                                 continue;
468
469                         size_t len = strlen(buf);
470                         if (buf[len-1] == '\n')
471                                 buf[len-1] = 0;
472
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);
477                 }
478                 fclose(avoid);
479         }
480
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)
486                                 continue;
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);
492                         }
493                 }
494
495 #if 0
496                 if (is_type_compound(type)) {
497                         write_compound(entity->base.symbol, &type->compound);
498                 }
499 #endif
500         }
501
502         /* write functions */
503         entity = unit->scope.entities;
504         for ( ; entity != NULL; entity = entity->base.next) {
505                 if (entity->kind != ENTITY_FUNCTION)
506                         continue;
507                 if (entity->base.pos.is_system_header)
508                         continue;
509                 if (entity->function.elf_visibility != ELF_VISIBILITY_DEFAULT)
510                         continue;
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)) {
517                                         in_limits = true;
518                                         break;
519                                 }
520                         }
521                         if (!in_limits)
522                                 continue;
523                 }
524
525                 if (pset_new_contains(&avoid_symbols, entity->base.symbol))
526                         continue;
527                 write_function(entity);
528         }
529
530         fputs("}\n", out);
531
532         pset_new_destroy(&avoid_symbols);
533 }