replaced malloc by VLA
[cparser] / write_caml.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2007-2008 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_caml.h"
26 #include "symbol_t.h"
27 #include "ast_t.h"
28 #include "type_t.h"
29 #include "type.h"
30 #include "adt/error.h"
31
32 static const scope_t *global_scope;
33 static FILE          *out;
34
35 static void write_type(const type_t *type);
36
37 static const char *get_atomic_type_string(const atomic_type_kind_t type)
38 {
39         switch(type) {
40         case ATOMIC_TYPE_VOID:        return "unit";
41         case ATOMIC_TYPE_CHAR:        return "byte";
42         case ATOMIC_TYPE_SCHAR:       return "byte";
43         case ATOMIC_TYPE_UCHAR:       return "unsigned byte";
44         case ATOMIC_TYPE_SHORT:       return "short";
45         case ATOMIC_TYPE_USHORT:      return "unsigned short";
46         case ATOMIC_TYPE_INT:         return "int";
47         case ATOMIC_TYPE_UINT:        return "unsigned int";
48         case ATOMIC_TYPE_LONG:        return "int";
49         case ATOMIC_TYPE_ULONG:       return "unsigned int";
50         case ATOMIC_TYPE_LONGLONG:    return "long";
51         case ATOMIC_TYPE_ULONGLONG:   return "unsigned long";
52         case ATOMIC_TYPE_FLOAT:       return "float";
53         case ATOMIC_TYPE_DOUBLE:      return "double";
54         case ATOMIC_TYPE_LONG_DOUBLE: return "double";
55         case ATOMIC_TYPE_BOOL:        return "bool";
56         default:                      panic("unsupported atomic type");
57         }
58 }
59
60 static void write_atomic_type(const atomic_type_t *type)
61 {
62         fprintf(out, "%s", get_atomic_type_string(type->akind));
63 }
64
65 static void write_pointer_type(const pointer_type_t *type)
66 {
67         type_t *points_to = type->points_to;
68         if (points_to->kind == TYPE_ATOMIC &&
69                         is_type_atomic(points_to, ATOMIC_TYPE_CHAR)) {
70                 fputs("string", out);
71                 return;
72         }
73
74         write_type(type->points_to);
75         fputc('*', out);
76 }
77
78 static declaration_t *find_typedef(const type_t *type)
79 {
80         /* first: search for a matching typedef in the global type... */
81         declaration_t *declaration = global_scope->declarations;
82         while(declaration != NULL) {
83                 if (! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
84                         declaration = declaration->next;
85                         continue;
86                 }
87                 if (declaration->type == type)
88                         break;
89                 declaration = declaration->next;
90         }
91
92         return declaration;
93 }
94
95 static void write_compound_type(const compound_type_t *type)
96 {
97         declaration_t *declaration = find_typedef((const type_t*) type);
98         if (declaration != NULL) {
99                 fprintf(out, "%s", declaration->symbol->string);
100                 return;
101         }
102
103         /* does the struct have a name? */
104         symbol_t *symbol = type->declaration->symbol;
105         if (symbol != NULL) {
106                 /* TODO: make sure we create a struct for it... */
107                 fprintf(out, "%s", symbol->string);
108                 return;
109         }
110         /* TODO: create a struct and use its name here... */
111         fprintf(out, "/* TODO anonymous struct */byte");
112 }
113
114 static void write_enum_type(const enum_type_t *type)
115 {
116         declaration_t *declaration = find_typedef((const type_t*) type);
117         if (declaration != NULL) {
118                 fprintf(out, "%s", declaration->symbol->string);
119                 return;
120         }
121
122         /* does the enum have a name? */
123         symbol_t *symbol = type->declaration->symbol;
124         if (symbol != NULL) {
125                 /* TODO: make sure we create an enum for it... */
126                 fprintf(out, "%s", symbol->string);
127                 return;
128         }
129         /* TODO: create a struct and use its name here... */
130         fprintf(out, "/* TODO anonymous enum */byte");
131 }
132
133 static void write_function_type(const function_type_t *type)
134 {
135         fprintf(out, "(func(");
136
137         function_parameter_t *parameter = type->parameters;
138         int                   first     = 1;
139         while(parameter != NULL) {
140                 if (!first) {
141                         fprintf(out, ", ");
142                 } else {
143                         first = 0;
144                 }
145
146 #if 0
147                 if (parameter->symbol != NULL) {
148                         fprintf(out, "%s : ", parameter->symbol->string);
149                 } else {
150                         /* TODO make up some unused names (or allow _ in fluffy?) */
151                         fprintf(out, "_ : ");
152                 }
153 #endif
154                 fputs("_ : ", out);
155                 write_type(parameter->type);
156
157                 parameter = parameter->next;
158         }
159
160         fprintf(out, ") : ");
161         write_type(type->return_type);
162         fprintf(out, ")");
163 }
164
165 static void write_type(const type_t *type)
166 {
167         switch(type->kind) {
168         case TYPE_ATOMIC:
169                 write_atomic_type(&type->atomic);
170                 return;
171         case TYPE_POINTER:
172                 write_pointer_type(&type->pointer);
173                 return;
174         case TYPE_COMPOUND_UNION:
175         case TYPE_COMPOUND_STRUCT:
176                 write_compound_type(&type->compound);
177                 return;
178         case TYPE_ENUM:
179                 write_enum_type(&type->enumt);
180                 return;
181         case TYPE_FUNCTION:
182                 write_function_type(&type->function);
183                 return;
184         case TYPE_INVALID:
185                 panic("invalid type found");
186                 break;
187         case TYPE_COMPLEX:
188         case TYPE_IMAGINARY:
189         default:
190                 fprintf(out, "/* TODO type */");
191                 break;
192         }
193 }
194
195 #if 0
196 static void write_struct_entry(const declaration_t *declaration)
197 {
198         fprintf(out, "\t%s : ", declaration->symbol->string);
199         write_type(declaration->type);
200         fprintf(out, "\n");
201 }
202
203 static void write_struct(const symbol_t *symbol, const compound_type_t *type)
204 {
205         fprintf(out, "struct %s:\n", symbol->string);
206
207         const declaration_t *declaration = type->declaration->scope.declarations;
208         while(declaration != NULL) {
209                 write_struct_entry(declaration);
210                 declaration = declaration->next;
211         }
212
213         fprintf(out, "\n");
214 }
215
216 static void write_union(const symbol_t *symbol, const compound_type_t *type)
217 {
218         fprintf(out, "union %s:\n", symbol->string);
219
220         const declaration_t *declaration = type->declaration->scope.declarations;
221         while(declaration != NULL) {
222                 write_struct_entry(declaration);
223                 declaration = declaration->next;
224         }
225
226         fprintf(out, "\n");
227 }
228
229 static void write_expression(const expression_t *expression);
230
231 static void write_unary_expression(const unary_expression_t *expression)
232 {
233         switch(expression->base.kind) {
234         case EXPR_UNARY_NEGATE:
235                 fputc('-', out);
236                 break;
237         case EXPR_UNARY_NOT:
238                 fputc('!', out);
239                 break;
240         default:
241                 panic("unimeplemented unary expression found");
242         }
243         write_expression(expression->value);
244 }
245
246 static void write_expression(const expression_t *expression)
247 {
248         const const_expression_t *constant;
249         /* TODO */
250         switch(expression->kind) {
251         case EXPR_CONST:
252                 constant = &expression->conste;
253                 if (is_type_integer(expression->base.type)) {
254                         fprintf(out, "%lld", constant->v.int_value);
255                 } else {
256                         fprintf(out, "%Lf", constant->v.float_value);
257                 }
258                 break;
259         EXPR_UNARY_CASES
260                 write_unary_expression((const unary_expression_t*) expression);
261                 break;
262         default:
263                 panic("not implemented expression");
264         }
265 }
266
267 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
268 {
269         fprintf(out, "enum %s:\n", symbol->string);
270
271         declaration_t *entry = type->declaration->next;
272         for ( ; entry != NULL && entry->storage_class == STORAGE_CLASS_ENUM_ENTRY;
273                         entry = entry->next) {
274                 fprintf(out, "\t%s", entry->symbol->string);
275                 if (entry->init.initializer != NULL) {
276                         fprintf(out, " <- ");
277                         write_expression(entry->init.enum_value);
278                 }
279                 fputc('\n', out);
280         }
281         fprintf(out, "typealias %s <- int\n", symbol->string);
282         fprintf(out, "\n");
283 }
284
285 static void write_variable(const declaration_t *declaration)
286 {
287         fprintf(out, "var %s : ", declaration->symbol->string);
288         write_type(declaration->type);
289         /* TODO: initializers */
290         fprintf(out, "\n");
291 }
292 #endif
293
294 static void write_function(const declaration_t *declaration)
295 {
296         if (declaration->init.statement != NULL) {
297                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
298                         declaration->symbol->string);
299         }
300
301         fprintf(out, "external %s: ", declaration->symbol->string);
302
303         const function_type_t *function_type
304                 = (const function_type_t*) declaration->type;
305
306         declaration_t *parameter = declaration->scope.declarations;
307         for( ; parameter != NULL; parameter = parameter->next) {
308                 write_type(parameter->type);
309                 fputs(" -> ", out);
310         }
311         if (function_type->variadic) {
312                 fprintf(stderr, "WARNING: Variadic function not supported yet\n");
313         }
314         if (function_type->unspecified_parameters) {
315                 fprintf(stderr, "WARNING: unspecified params not supported\n");
316         }
317         const type_t *return_type = function_type->return_type;
318         write_type(return_type);
319
320         fputs(" = \"", out);
321         fputs(declaration->symbol->string, out);
322         fputs("\"", out);
323
324         fputc('\n', out);
325 }
326
327 void write_caml_decls(FILE *output, const translation_unit_t *unit)
328 {
329         out          = output;
330         global_scope = &unit->scope;
331
332         ast_set_output(out);
333         fprintf(out, "(* WARNING: Automatically generated file - chaning is useless *)\n");
334
335 #if 0
336         /* write structs,unions + enums */
337         declaration_t *declaration = unit->scope.declarations;
338         for( ; declaration != NULL; declaration = declaration->next) {
339                 //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
340                 if (! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
341                         continue;
342                 }
343                 type_t *type = declaration->type;
344                 if (type->kind == TYPE_COMPOUND_STRUCT) {
345                         write_struct(declaration->symbol, &type->compound);
346                 } else if (type->kind == TYPE_COMPOUND_UNION) {
347                         write_union(declaration->symbol, &type->compound);
348                 } else if (type->kind == TYPE_ENUM) {
349                         write_enum(declaration->symbol, &type->enumt);
350                 }
351         }
352
353         /* write global variables */
354         declaration = unit->scope.declarations;
355         for( ; declaration != NULL; declaration = declaration->next) {
356                 if (declaration->namespc != NAMESPACE_NORMAL)
357                         continue;
358                 if (declaration->storage_class == STORAGE_CLASS_TYPEDEF
359                                 || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
360                         continue;
361
362                 type_t *type = declaration->type;
363                 if (type->kind == TYPE_FUNCTION)
364                         continue;
365
366                 write_variable(declaration);
367         }
368 #endif
369
370         /* write functions */
371         declaration_t *declaration = unit->scope.declarations;
372         for( ; declaration != NULL; declaration = declaration->next) {
373                 if (declaration->namespc != NAMESPACE_NORMAL)
374                         continue;
375                 if (declaration->storage_class == STORAGE_CLASS_TYPEDEF
376                                 || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
377                         continue;
378
379                 type_t *type = declaration->type;
380                 if (type->kind != TYPE_FUNCTION)
381                         continue;
382
383                 write_function(declaration);
384         }
385 }