#include "driver/firm_cmdline.h"
#include "adt/error.h"
#include "write_fluffy.h"
+#include "write_caml.h"
#include "revision.h"
#include "warning.h"
#ifndef PREPROCESSOR
-#define PREPROCESSOR "cpp -std=c99 -U__WCHAR_TYPE__ -D__WCHAR_TYPE__=int -m32"
+#define PREPROCESSOR "cpp -std=c99 -U__WCHAR_TYPE__ -D__WCHAR_TYPE__=int -D__SIZE_TYPE__=__SIZE_TYPE__ -m32"
#endif
#ifndef LINKER
/** true for strict language checking. */
bool strict_mode = false;
+/** use builtins for some libc functions */
+bool use_builtins = false;
+
/* to switch on printing of implicit casts */
extern bool print_implicit_casts;
memcpy(buf+last_dot, newext, extlen);
}
+#include "builtins.h"
+
static translation_unit_t *do_parsing(FILE *const in, const char *const input_name)
{
+ start_parsing();
+
+ if (use_builtins) {
+ lexer_open_buffer(builtins, sizeof(builtins)-1, "<builtin>");
+ parse();
+ }
+
lexer_open_stream(in, input_name);
- translation_unit_t *unit = parse();
+ parse();
+
+ translation_unit_t *unit = finish_parsing();
return unit;
}
LexTest,
PrintAst,
PrintFluffy,
+ PrintCaml,
Link
} compile_mode_t;
case 3:
set_option("cond-eval");
set_option("if-conv");
+ use_builtins = true;
/* fallthrough */
case 2:
set_option("inline");
input = arg;
}
} else if(strcmp(option, "pg") == 0) {
- set_be_option("-b gprof");
+ set_be_option("gprof");
obstack_printf(&ldflags_obst, " -pg");
} else if(strcmp(option, "pedantic") == 0) {
fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg);
print_parenthesis = true;
} else if(strcmp(option, "print-fluffy") == 0) {
mode = PrintFluffy;
+ } else if(strcmp(option, "print-caml") == 0) {
+ mode = PrintCaml;
} else if(strcmp(option, "version") == 0) {
print_cparser_version();
exit(EXIT_SUCCESS);
continue;
}
- if (strcmp(arg+len-2, ".c") == 0) {
+ if (strcmp(arg+len-2, ".c") == 0
+ || strcmp(arg+len-2, ".h") == 0) {
entry->next = c_files;
c_files = entry;
} else if (strcmp(arg+len-2, ".s") == 0) {
case BenchmarkParser:
case PrintAst:
case PrintFluffy:
+ case PrintCaml:
case LexTest:
if(outname == NULL)
outname = "-";
return result;
if(mode == PrintFluffy) {
- type_set_output(out);
- ast_set_output(out);
write_fluffy_decls(out, unit);
}
+ if (mode == PrintCaml) {
+ write_caml_decls(out, unit);
+ }
translation_unit_to_firm(unit);
static goto_statement_t *goto_last = NULL;
static label_statement_t *label_first = NULL;
static label_statement_t *label_last = NULL;
+static translation_unit_t *unit = NULL;
static struct obstack temp_obst;
static source_position_t null_position = { NULL, 0 };
if (old_storage_class == STORAGE_CLASS_EXTERN &&
new_storage_class == STORAGE_CLASS_EXTERN) {
warn_redundant_declaration:
- if (warning.redundant_decls) {
+ if (warning.redundant_decls && strcmp(previous_declaration->source_position.input_name, "<builtin>") != 0) {
warningf(&declaration->source_position,
"redundant declaration for '%Y' (declared %P)",
symbol, &previous_declaration->source_position);
/**
* Parse a translation unit.
*/
-static translation_unit_t *parse_translation_unit(void)
+static void parse_translation_unit(void)
{
- translation_unit_t *unit = allocate_ast_zero(sizeof(unit[0]));
-
- assert(global_scope == NULL);
- global_scope = &unit->scope;
-
- assert(scope == NULL);
- set_scope(&unit->scope);
-
- initialize_builtin_types();
-
while(token.type != T_EOF) {
if (token.type == ';') {
/* TODO error in strict mode */
parse_external_declaration();
}
}
-
- assert(scope == &unit->scope);
- scope = NULL;
- last_declaration = NULL;
-
- assert(global_scope == &unit->scope);
- check_unused_globals();
- global_scope = NULL;
-
- return unit;
}
/**
*
* @return the translation unit or NULL if errors occurred.
*/
-translation_unit_t *parse(void)
+void start_parsing(void)
{
environment_stack = NEW_ARR_F(stack_entry_t, 0);
label_stack = NEW_ARR_F(stack_entry_t, 0);
type_set_output(stderr);
ast_set_output(stderr);
- lookahead_bufpos = 0;
- for(int i = 0; i < MAX_LOOKAHEAD + 2; ++i) {
- next_token();
- }
- translation_unit_t *unit = parse_translation_unit();
+ assert(unit == NULL);
+ unit = allocate_ast_zero(sizeof(unit[0]));
+
+ assert(global_scope == NULL);
+ global_scope = &unit->scope;
+
+ assert(scope == NULL);
+ set_scope(&unit->scope);
+
+ initialize_builtin_types();
+}
+
+translation_unit_t *finish_parsing(void)
+{
+ assert(scope == &unit->scope);
+ scope = NULL;
+ last_declaration = NULL;
+
+ assert(global_scope == &unit->scope);
+ check_unused_globals();
+ global_scope = NULL;
DEL_ARR_F(environment_stack);
DEL_ARR_F(label_stack);
- return unit;
+ translation_unit_t *result = unit;
+ unit = NULL;
+ return result;
+}
+
+void parse(void)
+{
+ lookahead_bufpos = 0;
+ for(int i = 0; i < MAX_LOOKAHEAD + 2; ++i) {
+ next_token();
+ }
+ parse_translation_unit();
}
/**
--- /dev/null
+/*
+ * This file is part of cparser.
+ * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <config.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include "write_caml.h"
+#include "symbol_t.h"
+#include "ast_t.h"
+#include "type_t.h"
+#include "type.h"
+#include "adt/error.h"
+
+static const scope_t *global_scope;
+static FILE *out;
+
+static void write_type(const type_t *type);
+
+static const char *get_atomic_type_string(const atomic_type_kind_t type)
+{
+ switch(type) {
+ case ATOMIC_TYPE_VOID: return "unit";
+ case ATOMIC_TYPE_CHAR: return "byte";
+ case ATOMIC_TYPE_SCHAR: return "byte";
+ case ATOMIC_TYPE_UCHAR: return "unsigned byte";
+ case ATOMIC_TYPE_SHORT: return "short";
+ case ATOMIC_TYPE_USHORT: return "unsigned short";
+ case ATOMIC_TYPE_INT: return "int";
+ case ATOMIC_TYPE_UINT: return "unsigned int";
+ case ATOMIC_TYPE_LONG: return "int";
+ case ATOMIC_TYPE_ULONG: return "unsigned int";
+ case ATOMIC_TYPE_LONGLONG: return "long";
+ case ATOMIC_TYPE_ULONGLONG: return "unsigned long";
+ case ATOMIC_TYPE_FLOAT: return "float";
+ case ATOMIC_TYPE_DOUBLE: return "double";
+ case ATOMIC_TYPE_LONG_DOUBLE: return "double";
+ case ATOMIC_TYPE_BOOL: return "bool";
+ default: panic("unsupported atomic type");
+ }
+}
+
+static void write_atomic_type(const atomic_type_t *type)
+{
+ fprintf(out, "%s", get_atomic_type_string(type->akind));
+}
+
+static void write_pointer_type(const pointer_type_t *type)
+{
+ type_t *points_to = type->points_to;
+ if (points_to->kind == TYPE_ATOMIC &&
+ is_type_atomic(points_to, ATOMIC_TYPE_CHAR)) {
+ fputs("string", out);
+ return;
+ }
+
+ write_type(type->points_to);
+ fputc('*', out);
+}
+
+static declaration_t *find_typedef(const type_t *type)
+{
+ /* first: search for a matching typedef in the global type... */
+ declaration_t *declaration = global_scope->declarations;
+ while(declaration != NULL) {
+ if (! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
+ declaration = declaration->next;
+ continue;
+ }
+ if (declaration->type == type)
+ break;
+ declaration = declaration->next;
+ }
+
+ return declaration;
+}
+
+static void write_compound_type(const compound_type_t *type)
+{
+ declaration_t *declaration = find_typedef((const type_t*) type);
+ if (declaration != NULL) {
+ fprintf(out, "%s", declaration->symbol->string);
+ return;
+ }
+
+ /* does the struct have a name? */
+ symbol_t *symbol = type->declaration->symbol;
+ if (symbol != NULL) {
+ /* TODO: make sure we create a struct for it... */
+ fprintf(out, "%s", symbol->string);
+ return;
+ }
+ /* TODO: create a struct and use its name here... */
+ fprintf(out, "/* TODO anonymous struct */byte");
+}
+
+static void write_enum_type(const enum_type_t *type)
+{
+ declaration_t *declaration = find_typedef((const type_t*) type);
+ if (declaration != NULL) {
+ fprintf(out, "%s", declaration->symbol->string);
+ return;
+ }
+
+ /* does the enum have a name? */
+ symbol_t *symbol = type->declaration->symbol;
+ if (symbol != NULL) {
+ /* TODO: make sure we create an enum for it... */
+ fprintf(out, "%s", symbol->string);
+ return;
+ }
+ /* TODO: create a struct and use its name here... */
+ fprintf(out, "/* TODO anonymous enum */byte");
+}
+
+static void write_function_type(const function_type_t *type)
+{
+ fprintf(out, "(func(");
+
+ function_parameter_t *parameter = type->parameters;
+ int first = 1;
+ while(parameter != NULL) {
+ if (!first) {
+ fprintf(out, ", ");
+ } else {
+ first = 0;
+ }
+
+#if 0
+ if (parameter->symbol != NULL) {
+ fprintf(out, "%s : ", parameter->symbol->string);
+ } else {
+ /* TODO make up some unused names (or allow _ in fluffy?) */
+ fprintf(out, "_ : ");
+ }
+#endif
+ fputs("_ : ", out);
+ write_type(parameter->type);
+
+ parameter = parameter->next;
+ }
+
+ fprintf(out, ") : ");
+ write_type(type->return_type);
+ fprintf(out, ")");
+}
+
+static void write_type(const type_t *type)
+{
+ switch(type->kind) {
+ case TYPE_ATOMIC:
+ write_atomic_type(&type->atomic);
+ return;
+ case TYPE_POINTER:
+ write_pointer_type(&type->pointer);
+ return;
+ case TYPE_COMPOUND_UNION:
+ case TYPE_COMPOUND_STRUCT:
+ write_compound_type(&type->compound);
+ return;
+ case TYPE_ENUM:
+ write_enum_type(&type->enumt);
+ return;
+ case TYPE_FUNCTION:
+ write_function_type(&type->function);
+ return;
+ case TYPE_INVALID:
+ panic("invalid type found");
+ break;
+ case TYPE_COMPLEX:
+ case TYPE_IMAGINARY:
+ default:
+ fprintf(out, "/* TODO type */");
+ break;
+ }
+}
+
+#if 0
+static void write_struct_entry(const declaration_t *declaration)
+{
+ fprintf(out, "\t%s : ", declaration->symbol->string);
+ write_type(declaration->type);
+ fprintf(out, "\n");
+}
+
+static void write_struct(const symbol_t *symbol, const compound_type_t *type)
+{
+ fprintf(out, "struct %s:\n", symbol->string);
+
+ const declaration_t *declaration = type->declaration->scope.declarations;
+ while(declaration != NULL) {
+ write_struct_entry(declaration);
+ declaration = declaration->next;
+ }
+
+ fprintf(out, "\n");
+}
+
+static void write_union(const symbol_t *symbol, const compound_type_t *type)
+{
+ fprintf(out, "union %s:\n", symbol->string);
+
+ const declaration_t *declaration = type->declaration->scope.declarations;
+ while(declaration != NULL) {
+ write_struct_entry(declaration);
+ declaration = declaration->next;
+ }
+
+ fprintf(out, "\n");
+}
+
+static void write_expression(const expression_t *expression);
+
+static void write_unary_expression(const unary_expression_t *expression)
+{
+ switch(expression->base.kind) {
+ case EXPR_UNARY_NEGATE:
+ fputc('-', out);
+ break;
+ case EXPR_UNARY_NOT:
+ fputc('!', out);
+ break;
+ default:
+ panic("unimeplemented unary expression found");
+ }
+ write_expression(expression->value);
+}
+
+static void write_expression(const expression_t *expression)
+{
+ const const_expression_t *constant;
+ /* TODO */
+ switch(expression->kind) {
+ case EXPR_CONST:
+ constant = &expression->conste;
+ if (is_type_integer(expression->base.type)) {
+ fprintf(out, "%lld", constant->v.int_value);
+ } else {
+ fprintf(out, "%Lf", constant->v.float_value);
+ }
+ break;
+ EXPR_UNARY_CASES
+ write_unary_expression((const unary_expression_t*) expression);
+ break;
+ default:
+ panic("not implemented expression");
+ }
+}
+
+static void write_enum(const symbol_t *symbol, const enum_type_t *type)
+{
+ fprintf(out, "enum %s:\n", symbol->string);
+
+ declaration_t *entry = type->declaration->next;
+ for ( ; entry != NULL && entry->storage_class == STORAGE_CLASS_ENUM_ENTRY;
+ entry = entry->next) {
+ fprintf(out, "\t%s", entry->symbol->string);
+ if (entry->init.initializer != NULL) {
+ fprintf(out, " <- ");
+ write_expression(entry->init.enum_value);
+ }
+ fputc('\n', out);
+ }
+ fprintf(out, "typealias %s <- int\n", symbol->string);
+ fprintf(out, "\n");
+}
+
+static void write_variable(const declaration_t *declaration)
+{
+ fprintf(out, "var %s : ", declaration->symbol->string);
+ write_type(declaration->type);
+ /* TODO: initializers */
+ fprintf(out, "\n");
+}
+#endif
+
+static void write_function(const declaration_t *declaration)
+{
+ if (declaration->init.statement != NULL) {
+ fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
+ declaration->symbol->string);
+ }
+
+ fprintf(out, "external %s: ", declaration->symbol->string);
+
+ const function_type_t *function_type
+ = (const function_type_t*) declaration->type;
+
+ declaration_t *parameter = declaration->scope.declarations;
+ for( ; parameter != NULL; parameter = parameter->next) {
+ write_type(parameter->type);
+ fputs(" -> ", out);
+ }
+ if (function_type->variadic) {
+ fprintf(stderr, "WARNING: Variadic function not supported yet\n");
+ }
+ if (function_type->unspecified_parameters) {
+ fprintf(stderr, "WARNING: unspecified params not supported\n");
+ }
+ const type_t *return_type = function_type->return_type;
+ write_type(return_type);
+
+ fputs(" = \"", out);
+ fputs(declaration->symbol->string, out);
+ fputs("\"", out);
+
+ fputc('\n', out);
+}
+
+void write_caml_decls(FILE *output, const translation_unit_t *unit)
+{
+ out = output;
+ global_scope = &unit->scope;
+
+ ast_set_output(out);
+ fprintf(out, "(* WARNING: Automatically generated file - chaning is useless *)\n");
+
+#if 0
+ /* write structs,unions + enums */
+ declaration_t *declaration = unit->scope.declarations;
+ for( ; declaration != NULL; declaration = declaration->next) {
+ //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
+ if (! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
+ continue;
+ }
+ type_t *type = declaration->type;
+ if (type->kind == TYPE_COMPOUND_STRUCT) {
+ write_struct(declaration->symbol, &type->compound);
+ } else if (type->kind == TYPE_COMPOUND_UNION) {
+ write_union(declaration->symbol, &type->compound);
+ } else if (type->kind == TYPE_ENUM) {
+ write_enum(declaration->symbol, &type->enumt);
+ }
+ }
+
+ /* write global variables */
+ declaration = unit->scope.declarations;
+ for( ; declaration != NULL; declaration = declaration->next) {
+ if (declaration->namespc != NAMESPACE_NORMAL)
+ continue;
+ if (declaration->storage_class == STORAGE_CLASS_TYPEDEF
+ || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
+ continue;
+
+ type_t *type = declaration->type;
+ if (type->kind == TYPE_FUNCTION)
+ continue;
+
+ write_variable(declaration);
+ }
+#endif
+
+ /* write functions */
+ declaration_t *declaration = unit->scope.declarations;
+ for( ; declaration != NULL; declaration = declaration->next) {
+ if (declaration->namespc != NAMESPACE_NORMAL)
+ continue;
+ if (declaration->storage_class == STORAGE_CLASS_TYPEDEF
+ || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
+ continue;
+
+ type_t *type = declaration->type;
+ if (type->kind != TYPE_FUNCTION)
+ continue;
+
+ write_function(declaration);
+ }
+}