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