support for libc builtins
authorMatthias Braun <matze@braunis.de>
Fri, 25 Jul 2008 08:59:48 +0000 (08:59 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 25 Jul 2008 08:59:48 +0000 (08:59 +0000)
[r20680]

12 files changed:
Makefile
builtins/builtins.c [new file with mode: 0644]
create_builtins_h.sh [new file with mode: 0755]
driver/firm_opt.c
lexer.c
lexer.h
main.c
parser.c
parser.h
write_caml.c [new file with mode: 0644]
write_caml.h [new file with mode: 0644]
write_fluffy.c

index 87b732d..acc6009 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,7 @@ SOURCES := \
        type_hash.c \
        warning.c \
        write_fluffy.c \
+       write_caml.c \
        driver/firm_cmdline.c \
        driver/firm_timing.c \
        driver/firm_codegen.c \
@@ -110,6 +111,10 @@ $(DIRS):
        @echo "===> MKDIR $@"
        $(Q)mkdir -p $@
 
+builtins.h: builtins/builtins.c
+       @echo '===> CREATE_BUILTINS $<'
+       $(Q)./create_builtins_h.sh > $@
+
 build/cpb/%.o: %.c build/cparser
        @echo '===> CPARSER $<'
        $(Q)./build/cparser $(CPPFLAGS) -std=c99 -Wall -g3 -c $< -o $@
diff --git a/builtins/builtins.c b/builtins/builtins.c
new file mode 100644 (file)
index 0000000..6cab6aa
--- /dev/null
@@ -0,0 +1,36 @@
+static inline char *strchr(const char *s, int c)
+{
+       for ( ; *s != 0; ++s) {
+               if (*s == c)
+                       return (char*) s;
+       }
+       return (char*) 0;
+}
+
+static inline char *strrchr(const char *s, int c)
+{
+       const char *result = (const char*) 0;
+
+       for ( ; *s != 0; ++s) {
+               if (*s == c)
+                       result = s;
+       }
+       return (char*) result;
+}
+
+static inline int strcmp(const char *s1, const char *s2)
+{
+       for( ; (*s1 | *s2) != 0; ++s1, ++s2) {
+               if(*s1 != *s2)
+                       break;
+       }
+       return *s1 - *s2;
+}
+
+static inline __SIZE_TYPE__ strlen(const char *s)
+{
+       __SIZE_TYPE__ result = 0;
+       for ( ; *s != 0; ++s)
+               result++;
+       return result;
+}
diff --git a/create_builtins_h.sh b/create_builtins_h.sh
new file mode 100755 (executable)
index 0000000..e9d86eb
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+cat <<__EOF__
+/* WARNING: automatically generated file. Generated from builtins/builtins.c */
+
+static const char builtins[] =
+__EOF__
+
+cat builtins/builtins.c | sed -e 's/^/\t\"/g' -e 's/$/\\n\"/g'
+
+cat << __EOF__
+;
+__EOF__
index bacf110..261dbd2 100644 (file)
@@ -1130,8 +1130,11 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm
     stat_dump_snapshot(input_filename, "noopt");
   }
 
-  if (firm_opt.enabled)
+  if (firm_opt.enabled) {
+    do_firm_optimizations(input_filename, firm_const_exists);
     do_firm_optimizations(input_filename, firm_const_exists);
+    do_firm_optimizations(input_filename, firm_const_exists);
+  }
 
   if (firm_dump.gen_firm_asm) {
     timer_push(TV_FIRM_ASM);
diff --git a/lexer.c b/lexer.c
index faecfe3..fe51c2f 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -81,6 +81,11 @@ static inline void next_real_char(void)
 {
        assert(bufpos <= bufend);
        if (bufpos >= bufend) {
+               if (input == NULL) {
+                       c = EOF;
+                       return;
+               }
+
                size_t s = fread(buf + MAX_PUTBACK, 1, sizeof(buf) - MAX_PUTBACK,
                                 input);
                if(s == 0) {
@@ -1596,6 +1601,7 @@ newline_found:
 void init_lexer(void)
 {
        strset_init(&stringset);
+       symbol_L = symbol_table_insert("L");
 }
 
 void lexer_open_stream(FILE *stream, const char *input_name)
@@ -1604,7 +1610,6 @@ void lexer_open_stream(FILE *stream, const char *input_name)
        lexer_token.source_position.linenr     = 0;
        lexer_token.source_position.input_name = input_name;
 
-       symbol_L = symbol_table_insert("L");
        bufpos = NULL;
        bufend = NULL;
 
@@ -1613,6 +1618,20 @@ void lexer_open_stream(FILE *stream, const char *input_name)
        c = '\n';
 }
 
+void lexer_open_buffer(const char *buffer, size_t len, const char *input_name)
+{
+       input                                  = NULL;
+       lexer_token.source_position.linenr     = 0;
+       lexer_token.source_position.input_name = input_name;
+
+       bufpos = buffer;
+       bufend = buffer + len;
+
+       /* place a virtual \n at the beginning so the lexer knows that we're
+        * at the beginning of a line */
+       c = '\n';
+}
+
 void exit_lexer(void)
 {
        strset_destroy(&stringset);
diff --git a/lexer.h b/lexer.h
index 587b19e..8adcdd9 100644 (file)
--- a/lexer.h
+++ b/lexer.h
@@ -34,6 +34,7 @@ void init_lexer(void);
 void exit_lexer(void);
 
 void lexer_open_stream(FILE *stream, const char *input_name);
+void lexer_open_buffer(const char *buffer, size_t len, const char *input_name);
 
 string_t      concat_strings(           const string_t      *s1, const string_t      *s2);
 wide_string_t concat_string_wide_string(const string_t      *s1, const wide_string_t *s2);
diff --git a/main.c b/main.c
index 9890beb..1add07c 100644 (file)
--- a/main.c
+++ b/main.c
 #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
@@ -102,6 +103,9 @@ bool char_is_signed = true;
 /** 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;
 
@@ -173,10 +177,21 @@ static void get_output_name(char *buf, size_t buflen, const char *inputname,
        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;
 }
 
@@ -359,6 +374,7 @@ typedef enum compile_mode_t {
        LexTest,
        PrintAst,
        PrintFluffy,
+       PrintCaml,
        Link
 } compile_mode_t;
 
@@ -464,6 +480,7 @@ int main(int argc, char **argv)
        case 3:
                set_option("cond-eval");
                set_option("if-conv");
+               use_builtins = true;
                /* fallthrough */
        case 2:
                set_option("inline");
@@ -633,7 +650,7 @@ int main(int argc, char **argv)
                                        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);
@@ -679,6 +696,8 @@ int main(int argc, char **argv)
                                        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);
@@ -718,7 +737,8 @@ int main(int argc, char **argv)
                                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) {
@@ -775,6 +795,7 @@ int main(int argc, char **argv)
                case BenchmarkParser:
                case PrintAst:
                case PrintFluffy:
+               case PrintCaml:
                case LexTest:
                        if(outname == NULL)
                                outname = "-";
@@ -902,10 +923,11 @@ int main(int argc, char **argv)
                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);
 
index 1882d8a..4e37812 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -104,6 +104,7 @@ static goto_statement_t   *goto_first        = NULL;
 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 };
@@ -3900,7 +3901,7 @@ static declaration_t *internal_record_declaration(
                        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);
@@ -8066,18 +8067,8 @@ static void check_unused_globals(void)
 /**
  * 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 */
@@ -8087,16 +8078,6 @@ static translation_unit_t *parse_translation_unit(void)
                        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;
 }
 
 /**
@@ -8104,7 +8085,7 @@ static translation_unit_t *parse_translation_unit(void)
  *
  * @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);
@@ -8115,16 +8096,43 @@ translation_unit_t *parse(void)
        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();
 }
 
 /**
index c892482..b6ee305 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -28,7 +28,9 @@ typedef struct environment_entry_t environment_entry_t;
 void init_parser(void);
 void exit_parser(void);
 
-translation_unit_t *parse(void);
+void start_parsing(void);
+void parse(void);
+translation_unit_t *finish_parsing(void);
 
 type_t *revert_automatic_type_conversion(const expression_t *expression);
 declaration_t *expr_is_variable(const expression_t *expression);
diff --git a/write_caml.c b/write_caml.c
new file mode 100644 (file)
index 0000000..b688cc6
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * 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);
+       }
+}
diff --git a/write_caml.h b/write_caml.h
new file mode 100644 (file)
index 0000000..9273e47
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+#ifndef WRITE_CAML_H
+#define WRITE_CAML_H
+
+#include "ast.h"
+
+void write_caml_decls(FILE *out, const translation_unit_t *unit);
+
+#endif
index 0d66b0b..5379aee 100644 (file)
@@ -334,6 +334,7 @@ void write_fluffy_decls(FILE *output, const translation_unit_t *unit)
        global_scope = &unit->scope;
 
        ast_set_output(out);
+       type_set_output(out);
        fprintf(out, "/* WARNING: Automatically generated file */\n");
 
        /* write structs,unions + enums */