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