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