- change enum to have an underlying atomic type
[cparser] / main.c
diff --git a/main.c b/main.c
index ae849a9..e711e2b 100644 (file)
--- a/main.c
+++ b/main.c
 #include "driver/firm_opt.h"
 #include "driver/firm_cmdline.h"
 #include "adt/error.h"
-#include "write_fluffy.h"
-#include "write_caml.h"
+#include "wrappergen/write_fluffy.h"
+#include "wrappergen/write_caml.h"
+#include "wrappergen/write_jna.h"
 #include "revision.h"
 #include "warning.h"
 #include "mangle.h"
 
 #ifndef PREPROCESSOR
-#ifdef __APPLE__
+#ifndef __WIN32__
 #define PREPROCESSOR "gcc -E -std=c99 -m32 -U__STRICT_ANSI__"
 #else
 #define PREPROCESSOR "cpp -std=c99 -m32 -U__STRICT_ANSI__"
@@ -231,51 +232,54 @@ static void lextest(FILE *in, const char *fname)
        do {
                lexer_next_preprocessing_token();
                print_token(stdout, &lexer_token);
-               puts("");
+               putchar('\n');
        } while (lexer_token.type != T_EOF);
 }
 
 static void add_flag(struct obstack *obst, const char *format, ...)
 {
+       char buf[4096];
        va_list ap;
-       va_start(ap, format);
 
-       char buf[4096];
-       vsnprintf(buf, sizeof(buf), format, ap);
+       va_start(ap, format);
+#ifdef _WIN32
+       int len =
+#endif
+               vsnprintf(buf, sizeof(buf), format, ap);
+       va_end(ap);
 
-       /* escape stuff... */
        obstack_1grow(obst, ' ');
+#ifdef _WIN32
+       obstack_1grow(obst, '"');
+       obstack_grow(obst, buf, len);
+       obstack_1grow(obst, '"');
+#else
+       /* escape stuff... */
        for (char *c = buf; *c != '\0'; ++c) {
                switch(*c) {
-               case '"':
-               case '\'':
-               case '`':
                case ' ':
-               case '\t':
-               case '\n':
-               case '\r':
-               case '\\':
+               case '"':
                case '$':
+               case '&':
                case '(':
                case ')':
+               case ';':
+               case '<':
+               case '>':
+               case '\'':
+               case '\\':
+               case '\n':
+               case '\r':
+               case '\t':
+               case '`':
+               case '|':
                        obstack_1grow(obst, '\\');
-                       /* fallthrough */
+                       /* FALLTHROUGH */
                default:
                        obstack_1grow(obst, *c);
                        break;
                }
        }
-       va_end(ap);
-}
-
-static void add_quoted_string(struct obstack *obst, const char *s)
-{
-#ifdef _WIN32
-       obstack_1grow(obst, '"');
-       obstack_grow(obst, s, strlen(s));
-       obstack_1grow(obst, '"');
-#else
-       add_flag(obst, "%s", s);
 #endif
 }
 
@@ -294,26 +298,35 @@ static FILE *preprocess(const char *fname)
 
        /* setup default defines */
        add_flag(&cppflags_obst, "-U__WCHAR_TYPE__");
-       add_flag(&cppflags_obst, "-D__WCHAR_TYPE__=");
-       add_quoted_string(&cppflags_obst, type_to_string(type_wchar_t));
+       add_flag(&cppflags_obst, "-D__WCHAR_TYPE__=%s", type_to_string(type_wchar_t));
        add_flag(&cppflags_obst, "-U__SIZE_TYPE__");
-       add_flag(&cppflags_obst, "-D__SIZE_TYPE__=");
-       add_quoted_string(&cppflags_obst, type_to_string(type_size_t));
+       add_flag(&cppflags_obst, "-D__SIZE_TYPE__=%s", type_to_string(type_size_t));
+
+       /* TODO hack... */
+       add_flag(&cppflags_obst, "-D__builtin_abort=abort");
+       add_flag(&cppflags_obst, "-D__builtin_abs=abs");
+       add_flag(&cppflags_obst, "-D__builtin_exit=exit");
+       add_flag(&cppflags_obst, "-D__builtin_malloc=malloc");
+       add_flag(&cppflags_obst, "-D__builtin_memcmp=memcmp");
+       add_flag(&cppflags_obst, "-D__builtin_memcpy=memcpy");
+       add_flag(&cppflags_obst, "-D__builtin_memset=memset");
+       add_flag(&cppflags_obst, "-D__builtin_strlen=strlen");
+       add_flag(&cppflags_obst, "-D__builtin_strcmp=strcmp");
+       add_flag(&cppflags_obst, "-D__builtin_strcpy=strcpy");
 
        /* handle dependency generation */
        if (dep_target[0] != '\0') {
                add_flag(&cppflags_obst, "-MF");
-               add_quoted_string(&cppflags_obst, dep_target);
+               add_flag(&cppflags_obst, dep_target);
                if (outname != NULL) {
                                add_flag(&cppflags_obst, "-MQ");
-                               add_quoted_string(&cppflags_obst, outname);
+                               add_flag(&cppflags_obst, outname);
                }
        }
        if (flags[0] != '\0') {
                obstack_printf(&cppflags_obst, " %s", flags);
        }
-       obstack_1grow(&cppflags_obst, ' ');
-       add_quoted_string(&cppflags_obst, fname);
+       add_flag(&cppflags_obst, fname);
 
        obstack_1grow(&cppflags_obst, '\0');
        const char *buf = obstack_finish(&cppflags_obst);
@@ -346,6 +359,30 @@ static void assemble(const char *out, const char *in)
        }
 }
 
+static void print_file_name(const char *file)
+{
+       add_flag(&ldflags_obst, "-print-file-name=%s", file);
+
+       obstack_1grow(&ldflags_obst, '\0');
+       const char *flags = obstack_finish(&ldflags_obst);
+
+       /* construct commandline */
+       obstack_printf(&ldflags_obst, "%s ", LINKER);
+       obstack_printf(&ldflags_obst, "%s", flags);
+       obstack_1grow(&ldflags_obst, '\0');
+
+       char *commandline = obstack_finish(&ldflags_obst);
+
+       if (verbose) {
+               puts(commandline);
+       }
+       int err = system(commandline);
+       if (err != EXIT_SUCCESS) {
+               fprintf(stderr, "linker reported an error\n");
+               exit(1);
+       }
+}
+
 static const char *try_dir(const char *dir)
 {
        if (dir == NULL)
@@ -472,7 +509,8 @@ typedef enum compile_mode_t {
        LexTest,
        PrintAst,
        PrintFluffy,
-       PrintCaml
+       PrintCaml,
+       PrintJna
 } compile_mode_t;
 
 static void usage(const char *argv0)
@@ -481,18 +519,20 @@ static void usage(const char *argv0)
 }
 
 static void print_cparser_version(void) {
-       firm_version_t ver;
-       firm_get_version(&ver);
-
        printf("cparser (%s) using libFirm (%u.%u",
-               cparser_REVISION, ver.major, ver.minor);
-       if (ver.revision[0] != 0) {
+              cparser_REVISION, ir_get_version_major(),
+              ir_get_version_minor());
+
+       const char *revision = ir_get_version_revision();
+       if (revision[0] != 0) {
                putchar(' ');
-               fputs(ver.revision, stdout);
+               fputs(revision, stdout);
        }
-       if (ver.build[0] != 0) {
+
+       const char *build = ir_get_version_build();
+       if (build[0] != 0) {
                putchar(' ');
-               fputs(ver.build, stdout);
+               fputs(build, stdout);
        }
        puts(")\n");
 }
@@ -605,6 +645,7 @@ int main(int argc, char **argv)
        initialize_firm();
 
        const char        *dumpfunction         = NULL;
+       const char        *print_file_name_file = NULL;
        compile_mode_t     mode                 = CompileAssembleLink;
        int                opt_level            = 1;
        int                result               = EXIT_SUCCESS;
@@ -766,6 +807,20 @@ int main(int argc, char **argv)
                                GET_ARG_AFTER(opt, "-MT");
                                add_flag(&cppflags_obst, "-%s", option);
                                add_flag(&cppflags_obst, "%s", opt);
+                       } else if (streq(option, "include")) {
+                               const char *opt;
+                               GET_ARG_AFTER(opt, "-include");
+                               add_flag(&cppflags_obst, "-include");
+                               add_flag(&cppflags_obst, "%s", opt);
+                       } else if (streq(option, "isystem")) {
+                               const char *opt;
+                               GET_ARG_AFTER(opt, "-isystem");
+                               add_flag(&cppflags_obst, "-isystem");
+                               add_flag(&cppflags_obst, "%s", opt);
+                       } else if (streq(option, "nostdinc")
+                                       || streq(option, "trigraphs")) {
+                               /* pass these through to the preprocessor */
+                               add_flag(&cppflags_obst, "%s", arg);
                        } else if (streq(option, "pipe")) {
                                /* here for gcc compatibility */
                        } else if (option[0] == 'f') {
@@ -776,6 +831,8 @@ int main(int argc, char **argv)
                                    strstart(orig_opt, "align-jumps=") ||
                                    strstart(orig_opt, "align-functions=")) {
                                        fprintf(stderr, "ignoring gcc option '-f%s'\n", orig_opt);
+                               } else if (streq(orig_opt, "verbose-asm")) {
+                                       /* ignore: we always print verbose assembler */
                                } else {
                                        char const *opt         = orig_opt;
                                        bool        truth_value = true;
@@ -833,13 +890,22 @@ int main(int argc, char **argv)
                                        strncpy(cpu_arch, opt, sizeof(cpu_arch));
                                }
                        } else if (option[0] == 'W') {
-                               if (strstart(option + 1, "l,")) // a gcc-style linker option
-                               {
+                               if (strstart(option + 1, "p,")) {
+                                       // pass options directly to the preprocessor
+                                       const char *opt;
+                                       GET_ARG_AFTER(opt, "-Wp,");
+                                       add_flag(&cppflags_obst, "-Wp,%s", opt);
+                               } else if (strstart(option + 1, "l,")) {
+                                       // pass options directly to the linker
                                        const char *opt;
                                        GET_ARG_AFTER(opt, "-Wl,");
                                        add_flag(&ldflags_obst, "-Wl,%s", opt);
+                               } else if (streq(option + 1, "no-trigraphs")
+                                                       || streq(option + 1, "undef")) {
+                                       add_flag(&cppflags_obst, "%s", arg);
+                               } else {
+                                       set_warning_opt(&option[1]);
                                }
-                               else set_warning_opt(&option[1]);
                        } else if (option[0] == 'm') {
                                /* -m options */
                                const char *opt;
@@ -937,6 +1003,8 @@ int main(int argc, char **argv)
                                        (fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg), standard);
                        } else if (streq(option, "version")) {
                                print_cparser_version();
+                       } else if (strstart(option, "print-file-name=")) {
+                               GET_ARG_AFTER(print_file_name_file, "-print-file-name=");
                        } else if (option[0] == '-') {
                                /* double dash option */
                                ++option;
@@ -972,6 +1040,8 @@ int main(int argc, char **argv)
                                        mode = PrintFluffy;
                                } else if (streq(option, "print-caml")) {
                                        mode = PrintCaml;
+                               } else if (streq(option, "print-jna")) {
+                                       mode = PrintJna;
                                } else if (streq(option, "version")) {
                                        print_cparser_version();
                                        exit(EXIT_SUCCESS);
@@ -1040,6 +1110,11 @@ int main(int argc, char **argv)
                }
        }
 
+       if (print_file_name_file != NULL) {
+               print_file_name(print_file_name_file);
+               return 0;
+       }
+
        if (files == NULL) {
                fprintf(stderr, "error: no input files specified\n");
                argument_errors = true;
@@ -1086,6 +1161,7 @@ int main(int argc, char **argv)
                case PrintAst:
                case PrintFluffy:
                case PrintCaml:
+               case PrintJna:
                case LexTest:
                case PreprocessOnly:
                case ParseOnly:
@@ -1148,9 +1224,17 @@ int main(int argc, char **argv)
 
                FILE *preprocessed_in = NULL;
                switch (filetype) {
-                       case FILETYPE_C:         filetype = FILETYPE_PREPROCESSED_C;         goto preprocess;
-                       case FILETYPE_CXX:       filetype = FILETYPE_PREPROCESSED_CXX;       goto preprocess;
-                       case FILETYPE_ASSEMBLER: filetype = FILETYPE_PREPROCESSED_ASSEMBLER; goto preprocess;
+                       case FILETYPE_C:
+                               filetype = FILETYPE_PREPROCESSED_C;
+                               goto preprocess;
+                       case FILETYPE_CXX:
+                               filetype = FILETYPE_PREPROCESSED_CXX;
+                               goto preprocess;
+                       case FILETYPE_ASSEMBLER:
+                               filetype = FILETYPE_PREPROCESSED_ASSEMBLER;
+                               add_flag(&cppflags_obst, "-x");
+                               add_flag(&cppflags_obst, "assembler-with-cpp");
+                               goto preprocess;
 preprocess:
                                /* no support for input on FILE* yet */
                                if (in != NULL)
@@ -1161,6 +1245,10 @@ preprocess:
                                        copy_file(out, preprocessed_in);
                                        int result = pclose(preprocessed_in);
                                        fclose(out);
+                                       /* remove output file in case of error */
+                                       if (out != stdout && result != EXIT_SUCCESS) {
+                                               unlink(outname);
+                                       }
                                        return result;
                                }
 
@@ -1250,6 +1338,9 @@ do_parsing:
                        if (in == preprocessed_in) {
                                int pp_result = pclose(preprocessed_in);
                                if (pp_result != EXIT_SUCCESS) {
+                                       /* remove output file */
+                                       if (out != stdout)
+                                               unlink(outname);
                                        exit(EXIT_FAILURE);
                                }
                        }
@@ -1262,6 +1353,9 @@ do_parsing:
                        } else if (mode == PrintCaml) {
                                write_caml_decls(out, unit);
                                continue;
+                       } else if (mode == PrintJna) {
+                               write_jna_decls(out, unit);
+                               continue;
                        }
 
                        translation_unit_to_firm(unit);
@@ -1305,6 +1399,9 @@ do_parsing:
                        if (in == preprocessed_in) {
                                int pp_result = pclose(preprocessed_in);
                                if (pp_result != EXIT_SUCCESS) {
+                                       /* remove output in error case */
+                                       if (out != stdout)
+                                               unlink(outname);
                                        return pp_result;
                                }
                        }
@@ -1345,8 +1442,11 @@ do_parsing:
                file->type = filetype;
        }
 
-       if (result != EXIT_SUCCESS)
+       if (result != EXIT_SUCCESS) {
+               if (out != stdout)
+                       unlink(outname);
                return result;
+       }
 
        /* link program file */
        if (mode == CompileAssembleLink) {