]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - main.c
-fcorrect-ternary; by default -std=fteqcc now uses fteqcc's wrong ternary precedence...
[xonotic/gmqcc.git] / main.c
diff --git a/main.c b/main.c
index fd34c928fd861b8f13023057cacedf6e2a41d23f..220a2e390b85803daed1c2efcbbdd3e96e347598 100644 (file)
--- a/main.c
+++ b/main.c
 #include "lexer.h"
 
 uint32_t    opts_flags[1 + (COUNT_FLAGS / 32)];
-uint32_t    opts_warn [1 + (COUNT_WARNINGS / 32)];
+uint32_t    opts_optimization[1 + (COUNT_OPTIMIZATIONS / 32)];
+
+/* counter increased in ir.c */
+unsigned int optimization_count[COUNT_OPTIMIZATIONS];
 
 uint32_t    opts_O        = 1;
 const char *opts_output   = "progs.dat";
 int         opts_standard = COMPILER_GMQCC;
 bool        opts_debug    = false;
 bool        opts_memchk   = false;
+bool        opts_dumpfin  = false;
 bool        opts_dump     = false;
-bool        opts_werror   = false;
 bool        opts_forcecrc = false;
 bool        opts_pp_only  = false;
-size_t      opts_max_array_size = 1024;
+size_t      opts_max_array_size = (1024 << 3);
 
 uint16_t    opts_forced_crc;
 
@@ -112,6 +115,9 @@ static bool options_setflag(const char *name, bool on) {
 static bool options_setwarn(const char *name, bool on) {
     return options_setflag_all(name, on, opts_warn, opts_warn_list, COUNT_WARNINGS);
 }
+static bool options_setoptim(const char *name, bool on) {
+    return options_setflag_all(name, on, opts_optimization, opts_opt_list, COUNT_OPTIMIZATIONS);
+}
 
 static bool options_witharg(int *argc_, char ***argv_, char **out) {
     int  argc   = *argc_;
@@ -179,6 +185,13 @@ static void options_set(uint32_t *flags, size_t idx, bool on)
 #endif
 }
 
+static void set_optimizations(unsigned int level)
+{
+    size_t i;
+    for (i = 0; i < COUNT_OPTIMIZATIONS; ++i)
+        options_set(opts_optimization, i, level >= opts_opt_oflag[i]);
+}
+
 static bool options_parse(int argc, char **argv) {
     bool argend = false;
     size_t itr;
@@ -201,10 +214,15 @@ static bool options_parse(int argc, char **argv) {
                     opts_standard = COMPILER_GMQCC;
                 } else if (!strcmp(argarg, "qcc")) {
                     options_set(opts_flags, ADJUST_VECTOR_FIELDS, false);
+                    options_set(opts_flags, ASSIGN_FUNCTION_TYPES, true);
                     opts_standard = COMPILER_QCC;
                 } else if (!strcmp(argarg, "fte") || !strcmp(argarg, "fteqcc")) {
                     options_set(opts_flags, FTEPP,                true);
+                    options_set(opts_flags, TRANSLATABLE_STRINGS, true);
                     options_set(opts_flags, ADJUST_VECTOR_FIELDS, false);
+                    options_set(opts_flags, ASSIGN_FUNCTION_TYPES, true);
+                    options_set(opts_warn, WARN_TERNARY_PRECEDENCE, true);
+                    options_set(opts_flags, CORRECT_TERNARY, false);
                     opts_standard = COMPILER_FTEQCC;
                 } else if (!strcmp(argarg, "qccx")) {
                     options_set(opts_flags, ADJUST_VECTOR_FIELDS, false);
@@ -229,6 +247,31 @@ static bool options_parse(int argc, char **argv) {
                 continue;
             }
 
+            /* show defaults (like pathscale) */
+            if (!strcmp(argv[0]+1, "show-defaults")) {
+                size_t itr;
+                char   buffer[1024];
+                for (itr = 0; itr < COUNT_FLAGS; ++itr) {
+                    if (!OPTS_FLAG(itr))
+                        continue;
+
+                    memset(buffer, 0, sizeof(buffer));
+                    util_strtononcmd(opts_flag_list[itr].name, buffer, strlen(opts_flag_list[itr].name) + 1);
+
+                    con_out("-f%s ", buffer);
+                }
+                for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
+                    if (!OPTS_WARN(itr))
+                        continue;
+
+                    memset(buffer, 0, sizeof(buffer));
+                    util_strtononcmd(opts_warn_list[itr].name, buffer, strlen(opts_warn_list[itr].name) + 1);
+                    con_out("-W%s ", buffer);
+                }
+                con_out("\n");
+                exit(0);
+            }
+
             if (!strcmp(argv[0]+1, "debug")) {
                 opts_debug = true;
                 continue;
@@ -237,6 +280,10 @@ static bool options_parse(int argc, char **argv) {
                 opts_dump = true;
                 continue;
             }
+            if (!strcmp(argv[0]+1, "dumpfin")) {
+                opts_dumpfin = true;
+                continue;
+            }
             if (!strcmp(argv[0]+1, "memchk")) {
                 opts_memchk = true;
                 continue;
@@ -251,7 +298,7 @@ static bool options_parse(int argc, char **argv) {
                 case 'h':
                     usage();
                     exit(0);
-                    break;
+                    /* break; never reached because of exit(0) */
 
                 case 'E':
                     opts_pp_only = true;
@@ -260,7 +307,7 @@ static bool options_parse(int argc, char **argv) {
                 /* handle all -fflags */
                 case 'f':
                     util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
-                    if (!strcmp(argv[0]+2, "HELP")) {
+                    if (!strcmp(argv[0]+2, "HELP") || *(argv[0]+2) == '?') {
                         con_out("Possible flags:\n");
                         for (itr = 0; itr < COUNT_FLAGS; ++itr) {
                             util_strtononcmd(opts_flag_list[itr].name, buffer, sizeof(buffer));
@@ -281,7 +328,7 @@ static bool options_parse(int argc, char **argv) {
                     break;
                 case 'W':
                     util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
-                    if (!strcmp(argv[0]+2, "HELP")) {
+                    if (!strcmp(argv[0]+2, "HELP") || *(argv[0]+2) == '?') {
                         con_out("Possible warnings:\n");
                         for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
                             util_strtononcmd(opts_warn_list[itr].name, buffer, sizeof(buffer));
@@ -321,10 +368,37 @@ static bool options_parse(int argc, char **argv) {
 
                 case 'O':
                     if (!options_witharg(&argc, &argv, &argarg)) {
-                        con_out("option -O requires a numerical argument\n");
+                        con_out("option -O requires a numerical argument, or optimization name with an optional 'no-' prefix\n");
                         return false;
                     }
-                    opts_O = atoi(argarg);
+                    if (isdigit(argarg[0])) {
+                        opts_O = atoi(argarg);
+                        set_optimizations(opts_O);
+                    } else {
+                        util_strtocmd(argarg, argarg, strlen(argarg)+1);
+                        if (!strcmp(argarg, "HELP")) {
+                            con_out("Possible optimizations:\n");
+                            for (itr = 0; itr < COUNT_OPTIMIZATIONS; ++itr) {
+                                util_strtononcmd(opts_opt_list[itr].name, buffer, sizeof(buffer));
+                                con_out(" -O%-20s (-O%u)\n", buffer, opts_opt_oflag[itr]);
+                            }
+                            exit(0);
+                        }
+                        else if (!strcmp(argarg, "ALL"))
+                            set_optimizations(opts_O = 9999);
+                        else if (!strncmp(argarg, "NO_", 3)) {
+                            if (!options_setoptim(argarg+3, false)) {
+                                con_out("unknown optimization: %s\n", argarg+3);
+                                return false;
+                            }
+                        }
+                        else {
+                            if (!options_setoptim(argarg, true)) {
+                                con_out("unknown optimization: %s\n", argarg);
+                                return false;
+                            }
+                        }
+                    }
                     break;
 
                 case 'o':
@@ -379,7 +453,6 @@ static bool options_parse(int argc, char **argv) {
         else
         {
             /* it's a QC filename */
-            argitem item;
             item.filename = argv[0];
             item.type     = TYPE_QC;
             vec_push(items, item);
@@ -418,6 +491,7 @@ int main(int argc, char **argv) {
     size_t itr;
     int retval = 0;
     bool opts_output_free = false;
+    bool operators_free = false;
     bool progs_src = false;
     FILE *outfile = NULL;
 
@@ -442,9 +516,13 @@ int main(int argc, char **argv) {
     options_set(opts_warn, WARN_ASSIGN_FUNCTION_TYPES, true);
     options_set(opts_warn, WARN_PREPROCESSOR, true);
     options_set(opts_warn, WARN_MULTIFILE_IF, true);
+    options_set(opts_warn, WARN_DOUBLE_DECLARATION, true);
+    options_set(opts_warn, WARN_CONST_VAR, true);
+    options_set(opts_warn, WARN_MULTIBYTE_CHARACTER, true);
 
     options_set(opts_flags, ADJUST_VECTOR_FIELDS, true);
     options_set(opts_flags, FTEPP, false);
+    options_set(opts_flags, CORRECT_TERNARY, true);
 
     if (!options_parse(argc, argv)) {
         return usage();
@@ -454,11 +532,34 @@ int main(int argc, char **argv) {
     if (opts_standard == COMPILER_GMQCC) {
         operators = c_operators;
         operator_count = c_operator_count;
+    } else if (opts_standard == COMPILER_FTEQCC) {
+        operators = fte_operators;
+        operator_count = fte_operator_count;
     } else {
         operators = qcc_operators;
         operator_count = qcc_operator_count;
     }
 
+    if (operators == fte_operators) {
+        /* fix ternary? */
+        if (OPTS_FLAG(CORRECT_TERNARY)) {
+            oper_info *newops;
+            if (operators[operator_count-2].id != opid1(',') ||
+                operators[operator_count-1].id != opid2(':','?'))
+            {
+                con_err("internal error: operator precedence table wasn't updated correctly!\n");
+                exit(1);
+            }
+            operators_free = true;
+            newops = mem_a(sizeof(operators[0]) * operator_count);
+            memcpy(newops, operators, sizeof(operators[0]) * operator_count);
+            memcpy(&newops[operator_count-2], &operators[operator_count-1], sizeof(newops[0]));
+            memcpy(&newops[operator_count-1], &operators[operator_count-2], sizeof(newops[0]));
+            newops[operator_count-2].prec = newops[operator_count-1].prec+1;
+            operators = newops;
+        }
+    }
+
     if (opts_dump) {
         for (itr = 0; itr < COUNT_FLAGS; ++itr) {
             con_out("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr));
@@ -560,11 +661,14 @@ srcdone:
             }
 
             if (opts_pp_only) {
+                const char *out;
                 if (!ftepp_preprocess_file(items[itr].filename)) {
                     retval = 1;
                     goto cleanup;
                 }
-                fprintf(outfile, "%s", ftepp_get());
+                out = ftepp_get();
+                if (out)
+                    fprintf(outfile, "%s", out);
                 ftepp_flush();
             }
             else {
@@ -575,9 +679,11 @@ srcdone:
                         goto cleanup;
                     }
                     data = ftepp_get();
-                    if (!parser_compile_string_len(items[itr].filename, data, vec_size(data)-1)) {
-                        retval = 1;
-                        goto cleanup;
+                    if (vec_size(data)) {
+                        if (!parser_compile_string_len(items[itr].filename, data, vec_size(data))) {
+                            retval = 1;
+                            goto cleanup;
+                        }
                     }
                     ftepp_flush();
                 }
@@ -606,6 +712,14 @@ srcdone:
 
     /* stuff */
 
+    if (!opts_pp_only) {
+        for (itr = 0; itr < COUNT_OPTIMIZATIONS; ++itr) {
+            if (optimization_count[itr]) {
+                con_out("%s: %u\n", opts_opt_list[itr].name, (unsigned int)optimization_count[itr]);
+            }
+        }
+    }
+
 cleanup:
     util_debug("COM", "cleaning ...\n");
     ftepp_finish();
@@ -616,6 +730,8 @@ cleanup:
         parser_cleanup();
     if (opts_output_free)
         mem_d((char*)opts_output);
+    if (operators_free)
+        mem_d((void*)operators);
 
     lex_cleanup();
     util_meminfo();