- add -f[no-]short-wchar
[cparser] / main.c
diff --git a/main.c b/main.c
index 2b1146c..c643979 100644 (file)
--- a/main.c
+++ b/main.c
@@ -80,7 +80,7 @@
 #include "warning.h"
 
 #ifndef PREPROCESSOR
-#define PREPROCESSOR "cpp -std=c99 -U__WCHAR_TYPE__ -D__WCHAR_TYPE__=int -U__SIZE_TYPE__ -D__SIZE_TYPE__=__SIZE_TYPE__ -m32"
+#define PREPROCESSOR "cpp -std=c99 -U__WCHAR_TYPE__ -D__WCHAR_TYPE__=int -U__SIZE_TYPE__ -D__SIZE_TYPE__=__SIZE_TYPE__ -m32 -U__STRICT_ANSI__"
 #endif
 
 #ifndef LINKER
@@ -118,6 +118,7 @@ static struct obstack cppflags_obst, ldflags_obst;
 typedef struct file_list_entry_t file_list_entry_t;
 
 typedef enum filetype_t {
+       FILETYPE_AUTODETECT,
        FILETYPE_C,
        FILETYPE_PREPROCESSED_C,
        FILETYPE_ASSEMBLER,
@@ -453,6 +454,20 @@ static FILE *open_file(const char *filename)
        return in;
 }
 
+static filetype_t get_filetype_from_string(const char *string)
+{
+       if (strcmp(string, "c") == 0 || strcmp(string, "c-header") == 0)
+               return FILETYPE_C;
+       if (strcmp(string, "assembler") == 0)
+               return FILETYPE_PREPROCESSED_ASSEMBLER;
+       if (strcmp(string, "assembler-with-cpp") == 0)
+               return FILETYPE_ASSEMBLER;
+       if (strcmp(string, "none") == 0)
+               return FILETYPE_AUTODETECT;
+
+       return FILETYPE_UNKNOWN;
+}
+
 int main(int argc, char **argv)
 {
        initialize_firm();
@@ -527,8 +542,9 @@ int main(int argc, char **argv)
        }
 
        /* parse rest of options */
-       bool help_displayed  = false;
-       bool argument_errors = false;
+       filetype_t  forced_filetype = FILETYPE_AUTODETECT;
+       bool        help_displayed  = false;
+       bool        argument_errors = false;
        for(int i = 1; i < argc; ++i) {
                const char *arg = argv[i];
                if(arg[0] == '-' && arg[1] != 0) {
@@ -572,12 +588,21 @@ int main(int argc, char **argv)
                                verbose = 1;
                        } else if(SINGLE_OPTION('w')) {
                                inhibit_all_warnings = true;
+                       } else if(option[0] == 'x') {
+                               const char *opt;
+                               GET_ARG_AFTER(opt, "-x");
+                               forced_filetype = get_filetype_from_string(opt);
+                               if (forced_filetype == FILETYPE_UNKNOWN) {
+                                       fprintf(stderr, "Unknown language '%s'\n", opt);
+                                       argument_errors = true;
+                               }
                        } else if(strcmp(option, "M") == 0) {
                                mode = PreprocessOnly;
                                add_flag(&cppflags_obst, "-M");
-                       } else if(strcmp(option, "MMD") == 0
-                                       || strcmp(option, "MD") == 0
-                                       || strcmp(option, "MM") == 0) {
+                       } else if (strcmp(option, "MMD") == 0 ||
+                                  strcmp(option, "MD")  == 0 ||
+                                  strcmp(option, "MM")  == 0 ||
+                                  strcmp(option, "MP")  == 0) {
                                add_flag(&cppflags_obst, "-%s", option);
                        } else if(strcmp(option, "MT") == 0
                                        || strcmp(option, "MQ") == 0
@@ -588,27 +613,38 @@ int main(int argc, char **argv)
                                add_flag(&cppflags_obst, "%s", opt);
                        } else if(strcmp(option, "pipe") == 0) {
                                /* here for gcc compatibility */
-                       } else if(option[0] == 'f') {
+                       } else if (option[0] == 'f') {
+                               bool truth_value = true;
                                const char *opt;
                                GET_ARG_AFTER(opt, "-f");
+                               if (opt[0] == 'n' && opt[1] == 'o' && opt[2] == '-') {
+                                       truth_value = false;
+                                       opt += 3;
+                               }
 
-                               if(strcmp(opt, "syntax-only") == 0) {
+                               if (strcmp(opt, "dollars-in-identifiers") == 0) {
+                                       allow_dollar_in_symbol = truth_value;
+                               } else if (strcmp(opt, "short-wchar") == 0) {
+                                       opt_short_wchar_t = truth_value;
+                               } else if (strcmp(opt, "syntax-only") == 0) {
                                        mode = ParseOnly;
                                } else if(strcmp(opt, "omit-frame-pointer") == 0) {
-                                       set_be_option("omitfp");
-                               } else if(strcmp(opt, "no-omit-frame-pointer") == 0) {
-                                       set_be_option("omitfp=no");
+                                       set_be_option(truth_value ? "omitfp" : "omitfp=no");
                                } else if(strcmp(opt, "strength-reduce") == 0) {
                                        firm_option("strength-red");
-                               } else if(strcmp(opt, "fast-math") == 0
+                               } else if (strcmp(opt, "fast-math") == 0
+                                               || strcmp(opt, "jump-tables") == 0
                                                || strcmp(opt, "unroll-loops") == 0
                                                || strcmp(opt, "expensive-optimizations") == 0
                                                || strcmp(opt, "no-common") == 0
+                                               || strcmp(opt, "PIC") == 0
                                                || strncmp(opt, "align-loops=", sizeof("align-loops=")-1) == 0
                                                || strncmp(opt, "align-jumps=", sizeof("align-jumps=")-1) == 0
                                                || strncmp(opt, "align-functions=", sizeof("align-functions=")-1) == 0) {
-                                       fprintf(stderr, "ignoring gcc option '-f %s'\n", opt);
+                                                       fprintf(stderr, "ignoring gcc option '-f %s'\n", truth_value ? opt : opt - 3);
                                } else {
+                                       if (! truth_value)
+                                               opt -= 3;
                                        int res = firm_option(opt);
                                        if (res == 0) {
                                                fprintf(stderr, "error: unknown Firm option '-f %s'\n",
@@ -619,7 +655,7 @@ int main(int argc, char **argv)
                                                help_displayed = true;
                                        }
                                }
-                       } else if(option[0] == 'b') {
+                       } else if (option[0] == 'b') {
                                const char *opt;
                                GET_ARG_AFTER(opt, "-b");
                                int res = firm_be_option(opt);
@@ -633,15 +669,21 @@ int main(int argc, char **argv)
                                        if (strncmp(opt, "isa=", 4) == 0)
                                                strncpy(cpu_arch, opt, sizeof(cpu_arch));
                                }
-                       } else if(option[0] == 'W') {
-                               set_warning_opt(&option[1]);
+                       } else if (option[0] == 'W') {
+                               if (strncmp(option + 1, "l,", 2) == 0)  // a gcc-style linker option
+                               {
+                                       const char *opt;
+                                       GET_ARG_AFTER(opt, "-Wl,");
+                                       add_flag(&ldflags_obst, "-Wl,%s", opt);
+                               }
+                               else set_warning_opt(&option[1]);
                        } else if(option[0] == 'm') {
                                /* -m options */
                                const char *opt;
                                char arch_opt[64];
 
                                GET_ARG_AFTER(opt, "-m");
-                               if(strncmp(opt, "arch=", 5) == 0) {
+                               if (strncmp(opt, "arch=", 5) == 0) {
                                        GET_ARG_AFTER(opt, "-march=");
                                        snprintf(arch_opt, sizeof(arch_opt), "%s-arch=%s", cpu_arch, opt);
                                        int res = firm_be_option(arch_opt);
@@ -708,7 +750,8 @@ int main(int argc, char **argv)
                        } else if(strcmp(option, "pg") == 0) {
                                set_be_option("gprof");
                                add_flag(&ldflags_obst, "-pg");
-                       } else if(strcmp(option, "pedantic") == 0) {
+                       } else if(strcmp(option, "pedantic") == 0
+                                       || strcmp(option, "ansi") == 0) {
                                fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg);
                        } else if(strcmp(option, "shared") == 0) {
                                add_flag(&ldflags_obst, "-shared");
@@ -778,39 +821,48 @@ int main(int argc, char **argv)
                                argument_errors = true;
                        }
                } else {
-                       filetype_t  type     = FILETYPE_UNKNOWN;
-                       size_t      len      = strlen(arg);
+                       filetype_t  type     = forced_filetype;
                        const char *filename = arg;
-                       if (len < 2 && arg[0] == '-') {
-                               /* - implicitely means C source file */
-                               type     = FILETYPE_C;
-                               filename = NULL;
-                       } else if (len > 2 && arg[len-2] == '.') {
-                               switch(arg[len-1]) {
-                               case 'c': type = FILETYPE_C; break;
-                               case 'h': type = FILETYPE_C; break;
-                               case 's': type = FILETYPE_PREPROCESSED_ASSEMBLER; break;
-                               case 'S': type = FILETYPE_ASSEMBLER; break;
-                               case 'o': type = FILETYPE_OBJECT; break;
+                       if (type == FILETYPE_AUTODETECT) {
+                               size_t      len      = strlen(arg);
+                               if (len < 2 && arg[0] == '-') {
+                                       /* - implicitly means C source file */
+                                       type     = FILETYPE_C;
+                                       filename = NULL;
+                               } else if (len > 2 && arg[len-2] == '.') {
+                                       switch(arg[len-1]) {
+                                       case 'c': type = FILETYPE_C; break;
+                                       case 'h': type = FILETYPE_C; break;
+                                       case 's': type = FILETYPE_PREPROCESSED_ASSEMBLER; break;
+                                       case 'S': type = FILETYPE_ASSEMBLER; break;
+
+                                       case 'a':
+                                       case 'o': type = FILETYPE_OBJECT; break;
+                                       }
+                               } else if (len > 3 && arg[len-3] == '.') {
+                                       if(strcmp(arg + len - 2, "so") == 0) {
+                                               type = FILETYPE_OBJECT;
+                                       }
+                               }
+
+                               if (type == FILETYPE_AUTODETECT) {
+                                       fprintf(stderr, "'%s': file format not recognized\n", arg);
+                                       continue;
                                }
                        }
 
-                       if (type == FILETYPE_UNKNOWN) {
-                               fprintf(stderr, "'%s': file format not recognized\n", arg);
+                       file_list_entry_t *entry
+                               = obstack_alloc(&file_obst, sizeof(entry[0]));
+                       memset(entry, 0, sizeof(entry[0]));
+                       entry->name = arg;
+                       entry->type = type;
+
+                       if (last_file != NULL) {
+                               last_file->next = entry;
                        } else {
-                               file_list_entry_t *entry
-                                       = obstack_alloc(&file_obst, sizeof(entry[0]));
-                               memset(entry, 0, sizeof(entry[0]));
-                               entry->name = arg;
-                               entry->type = type;
-
-                               if (last_file != NULL) {
-                                       last_file->next = entry;
-                               } else {
-                                       files = entry;
-                               }
-                               last_file = entry;
+                               files = entry;
                        }
+                       last_file = entry;
                }
        }
 
@@ -953,7 +1005,7 @@ int main(int argc, char **argv)
                        if (in == preprocessed_in) {
                                int pp_result = pclose(preprocessed_in);
                                if (pp_result != EXIT_SUCCESS) {
-                                       return pp_result;
+                                       exit(EXIT_FAILURE);
                                }
                        }
 
@@ -1029,6 +1081,9 @@ int main(int argc, char **argv)
                                        return pp_result;
                                }
                        }
+                       if(asm_out != out) {
+                               fclose(asm_out);
+                       }
                }
 
                if (mode == Compile)
@@ -1063,6 +1118,9 @@ int main(int argc, char **argv)
                file->type = filetype;
        }
 
+       if (result != EXIT_SUCCESS)
+               return result;
+
        /* link program file */
        if(mode == CompileAssembleLink) {
                obstack_1grow(&ldflags_obst, '\0');