]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Move lists of compiler options' semantics into a separate compopt.c file
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 1 Sep 2010 20:49:41 +0000 (22:49 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Wed, 1 Sep 2010 20:50:05 +0000 (22:50 +0200)
Makefile.in
ccache.c
compopt.c [new file with mode: 0644]
compopt.h [new file with mode: 0644]
dev.mk.in
test/test_compopt.c [new file with mode: 0644]

index 9f4a910869d41679c95fa3424d59beb80bf42e41..b095e1c839580369c0929373949f6a7dfc5c4434 100644 (file)
@@ -22,7 +22,7 @@ base_sources = \
     ccache.c mdfour.c hash.c execute.c util.c args.c stats.c version.c \
     cleanup.c snprintf.c unify.c manifest.c hashtable.c hashtable_itr.c \
     murmurhashneutral2.c hashutil.c getopt_long.c exitfn.c lockfile.c \
-    counters.c language.c
+    counters.c language.c compopt.c
 base_objs = $(base_sources:.c=.o)
 
 ccache_sources = main.c $(base_sources)
index 41bb200c029914d16c187daae3a6336fb49dd19d..fa2f10ef89638de7a68ae10a94f5f01ddba6ff2c 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -20,6 +20,7 @@
  */
 
 #include "ccache.h"
+#include "compopt.h"
 #ifdef HAVE_GETOPT_LONG
 #include <getopt.h>
 #else
@@ -873,31 +874,11 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode)
                   the output of -E if they are going to have any effect at
                   all. For precompiled headers this might not be the case. */
                if (!direct_mode && !output_is_precompiled_header) {
-                       if (i < args->argc-1) {
-                               if (str_eq(args->argv[i], "-D") ||
-                                   str_eq(args->argv[i], "-I") ||
-                                   str_eq(args->argv[i], "-U") ||
-                                   str_eq(args->argv[i], "-idirafter") ||
-                                   str_eq(args->argv[i], "-imacros") ||
-                                   str_eq(args->argv[i], "-imultilib") ||
-                                   str_eq(args->argv[i], "-include") ||
-                                   str_eq(args->argv[i], "-iprefix") ||
-                                   str_eq(args->argv[i], "-iquote") ||
-                                   str_eq(args->argv[i], "-isysroot") ||
-                                   str_eq(args->argv[i], "-isystem") ||
-                                   str_eq(args->argv[i], "-iwithprefix") ||
-                                   str_eq(args->argv[i], "-iwithprefixbefore") ||
-                                   str_eq(args->argv[i], "-nostdinc") ||
-                                   str_eq(args->argv[i], "-nostdinc++")) {
-                                       /* Skip from hash. */
-                                       i++;
-                                       continue;
-                               }
+                       if (compopt_affects_cpp(args->argv[i])) {
+                               i++;
+                               continue;
                        }
-                       if (str_startswith(args->argv[i], "-D") ||
-                           str_startswith(args->argv[i], "-I") ||
-                           str_startswith(args->argv[i], "-U")) {
-                               /* Skip from hash. */
+                       if (compopt_short(compopt_affects_cpp, args->argv[i])) {
                                continue;
                        }
                }
@@ -1224,17 +1205,7 @@ cc_process_args(struct args *orig_args, struct args **preprocessor_args,
                }
 
                /* these are too hard */
-               if (str_startswith(argv[i], "@") ||
-                   str_eq(argv[i], "--coverage") ||
-                   str_eq(argv[i], "-M") ||
-                   str_eq(argv[i], "-MM") ||
-                   str_eq(argv[i], "-fbranch-probabilities") ||
-                   str_eq(argv[i], "-fprofile-arcs") ||
-                   str_eq(argv[i], "-fprofile-generate") ||
-                   str_eq(argv[i], "-fprofile-use") ||
-                   str_eq(argv[i], "-frepo") ||
-                   str_eq(argv[i], "-ftest-coverage") ||
-                   str_eq(argv[i], "-save-temps")) {
+               if (compopt_too_hard(argv[i]) || str_startswith(argv[i], "@")) {
                        cc_log("Compiler option %s is unsupported", argv[i]);
                        stats_update(STATS_UNSUPPORTED);
                        result = false;
@@ -1243,7 +1214,7 @@ cc_process_args(struct args *orig_args, struct args **preprocessor_args,
 
                /* These are too hard in direct mode. */
                if (enable_direct) {
-                       if (str_eq(argv[i], "-Xpreprocessor")) {
+                       if (compopt_too_hard_for_direct_mode(argv[i])) {
                                cc_log("Unsupported compiler option for direct mode: %s", argv[i]);
                                enable_direct = false;
                        }
@@ -1427,105 +1398,56 @@ cc_process_args(struct args *orig_args, struct args **preprocessor_args,
                 * is that paths in the standard error output produced by the
                 * compiler will be normalized.
                 */
-               {
-                       const char *opts[] = {
-                               "-I", "-idirafter", "-imacros", "-include",
-                               "-iprefix", "-isystem", NULL
-                       };
-                       int j;
+               if (compopt_takes_path(argv[i])) {
                        char *relpath;
                        char *pchpath;
-                       for (j = 0; opts[j]; j++) {
-                               if (str_eq(argv[i], opts[j])) {
-                                       if (i == argc-1) {
-                                               cc_log("Missing argument to %s", argv[i]);
-                                               stats_update(STATS_ARGS);
-                                               result = false;
-                                               goto out;
-                                       }
-
-                                       args_add(stripped_args, argv[i]);
-                                       relpath = make_relative_path(x_strdup(argv[i+1]));
-                                       args_add(stripped_args, relpath);
-
-                                       /* Try to be smart about detecting precompiled headers */
-                                       pchpath = format("%s.gch", argv[i+1]);
-                                       if (stat(pchpath, &st) == 0) {
-                                               found_pch = true;
-                                       }
-
-                                       free(pchpath);
-                                       free(relpath);
-                                       i++;
-                                       break;
-                               }
+                       if (i == argc-1) {
+                               cc_log("Missing argument to %s", argv[i]);
+                               stats_update(STATS_ARGS);
+                               result = false;
+                               goto out;
                        }
-                       if (opts[j]) {
-                               continue;
+
+                       args_add(stripped_args, argv[i]);
+                       relpath = make_relative_path(x_strdup(argv[i+1]));
+                       args_add(stripped_args, relpath);
+
+                       /* Try to be smart about detecting precompiled headers */
+                       pchpath = format("%s.gch", argv[i+1]);
+                       if (stat(pchpath, &st) == 0) {
+                               found_pch = true;
                        }
+
+                       free(pchpath);
+                       free(relpath);
+                       i++;
+                       continue;
                }
 
                /* Same as above but options with concatenated argument. */
-               {
-                       const char *opts[] = {"-I", NULL};
-                       int j;
+               if (compopt_short(compopt_takes_path, argv[i])) {
                        char *relpath;
                        char *option;
-                       for (j = 0; opts[j]; j++) {
-                               if (str_startswith(argv[i], opts[j])) {
-                                       relpath = make_relative_path(x_strdup(argv[i] + strlen(opts[j])));
-                                       option = format("%s%s", opts[j], relpath);
-                                       args_add(stripped_args, option);
-                                       free(relpath);
-                                       free(option);
-                                       break;
-                               }
-                       }
-                       if (opts[j]) {
-                               continue;
-                       }
+                       relpath = make_relative_path(x_strdup(argv[i] + 2));
+                       option = format("-%c%s", argv[i][1], relpath);
+                       args_add(stripped_args, option);
+                       free(relpath);
+                       free(option);
+                       continue;
                }
 
                /* options that take an argument */
-               {
-                       const char *opts[] = {
-                               "--param",
-                               "-A",
-                               "-D",
-                               "-G",
-                               "-L",
-                               "-MF",
-                               "-MQ",
-                               "-MT",
-                               "-U",
-                               "-V",
-                               "-Xassembler",
-                               "-Xlinker",
-                               "-aux-info",
-                               "-b",
-                               "-install_name", /* Darwin linker option */
-                               "-iwithprefix",
-                               "-iwithprefixbefore",
-                               "-u",
-                               NULL
-                       };
-                       int j;
-                       for (j = 0; opts[j]; j++) {
-                               if (str_eq(argv[i], opts[j])) {
-                                       if (i == argc-1) {
-                                               cc_log("Missing argument to %s", argv[i]);
-                                               stats_update(STATS_ARGS);
-                                               result = false;
-                                               goto out;
-                                       }
-
-                                       args_add(stripped_args, argv[i]);
-                                       args_add(stripped_args, argv[i+1]);
-                                       i++;
-                                       break;
-                               }
+               if (compopt_takes_arg(argv[i])) {
+                       if (i == argc-1) {
+                               cc_log("Missing argument to %s", argv[i]);
+                               stats_update(STATS_ARGS);
+                               result = false;
+                               goto out;
                        }
-                       if (opts[j]) continue;
+                       args_add(stripped_args, argv[i]);
+                       args_add(stripped_args, argv[i+1]);
+                       i++;
+                       continue;
                }
 
                /* other options */
diff --git a/compopt.c b/compopt.c
new file mode 100644 (file)
index 0000000..48cbb77
--- /dev/null
+++ b/compopt.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010 Joel Rosdahl
+ *
+ * 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 3 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., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "ccache.h"
+#include "compopt.h"
+
+#define TOO_HARD         (1 << 0)
+#define TOO_HARD_DIRECT  (1 << 1)
+#define TAKES_ARG        (1 << 2)
+#define TAKES_CONCAT_ARG (1 << 3)
+#define TAKES_PATH       (1 << 4)
+#define AFFECTS_CPP      (1 << 5)
+
+struct compopt {
+       const char *name;
+       int type;
+};
+
+static const struct compopt compopts[] = {
+       {"--coverage",      TOO_HARD},
+       {"--param",         TAKES_ARG},
+       {"-A",              TAKES_ARG},
+       {"-D",              AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
+       {"-G",              TAKES_ARG},
+       {"-I",              AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+       {"-L",              TAKES_ARG},
+       {"-M",              TOO_HARD},
+       {"-MF",             TAKES_ARG},
+       {"-MM",             TOO_HARD},
+       {"-MQ",             TAKES_ARG},
+       {"-MT",             TAKES_ARG},
+       {"-U",              AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
+       {"-V",              TAKES_ARG},
+       {"-Xassembler",     TAKES_ARG},
+       {"-Xlinker",        TAKES_ARG},
+       {"-Xpreprocessor",  TOO_HARD_DIRECT | TAKES_ARG},
+       {"-aux-info",       TAKES_ARG},
+       {"-b",              TAKES_ARG},
+       {"-fbranch-probabilities", TOO_HARD},
+       {"-fprofile-arcs",  TOO_HARD},
+       {"-fprofile-generate", TOO_HARD},
+       {"-fprofile-use",   TOO_HARD},
+       {"-frepo",          TOO_HARD},
+       {"-ftest-coverage", TOO_HARD},
+       {"-idirafter",      AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-imacros",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-imultilib",      AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-include",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-install_name",   TAKES_ARG}, /* Darwin linker option */
+       {"-iprefix",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-iquote",         AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-isysroot",       AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-isystem",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-iwithprefix",    AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-iwithprefixbefore", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+       {"-nostdinc",       AFFECTS_CPP},
+       {"-nostdinc++",     AFFECTS_CPP},
+       {"-save-temps",     TOO_HARD},
+       {"-u",              TAKES_ARG},
+};
+
+static int
+compare_compopts(const void *key1, const void *key2)
+{
+       const struct compopt *opt1 = (const struct compopt *)key1;
+       const struct compopt *opt2 = (const struct compopt *)key2;
+       return strcmp(opt1->name, opt2->name);
+}
+
+static const struct compopt *
+find(const char *option)
+{
+       struct compopt key;
+       key.name = option;
+       return bsearch(
+               &key, compopts, sizeof(compopts) / sizeof(compopts[0]),
+               sizeof(compopts[0]), compare_compopts);
+}
+
+/* Runs fn on the first two characters of option. */
+bool
+compopt_short(bool (*fn)(const char *), const char *option)
+{
+       char *short_opt = x_strndup(option, 2);
+       bool retval = fn(short_opt);
+       free(short_opt);
+       return retval;
+}
+
+/* For test purposes. */
+bool
+compopt_verify_sortedness(void)
+{
+       size_t i;
+       for (i = 1; i < sizeof(compopts)/sizeof(compopts[0]); i++) {
+               if (strcmp(compopts[i-1].name, compopts[i].name) >= 0) {
+                       fprintf(stderr,
+                               "compopt_verify_sortedness: %s >= %s\n",
+                               compopts[i-1].name,
+                               compopts[i].name);
+                       return false;
+               }
+       }
+       return true;
+}
+
+bool
+compopt_affects_cpp(const char *option)
+{
+       const struct compopt *co = find(option);
+       return co && (co->type & AFFECTS_CPP);
+}
+
+bool
+compopt_too_hard(const char *option)
+{
+       const struct compopt *co = find(option);
+       return co && (co->type & TOO_HARD);
+}
+
+bool
+compopt_too_hard_for_direct_mode(const char *option)
+{
+       const struct compopt *co = find(option);
+       return co && (co->type & TOO_HARD_DIRECT);
+}
+
+bool
+compopt_takes_path(const char *option)
+{
+       const struct compopt *co = find(option);
+       return co && (co->type & TAKES_PATH);
+}
+
+bool
+compopt_takes_arg(const char *option)
+{
+       const struct compopt *co = find(option);
+       return co && (co->type & TAKES_ARG);
+}
diff --git a/compopt.h b/compopt.h
new file mode 100644 (file)
index 0000000..8985ac3
--- /dev/null
+++ b/compopt.h
@@ -0,0 +1,13 @@
+#ifndef CCACHE_COMPOPT_H
+#define CCACHE_COMPOPT_H
+
+#include "system.h"
+
+bool compopt_short(bool (*fn)(const char *option), const char *option);
+bool compopt_affects_cpp(const char *option);
+bool compopt_too_hard(const char *option);
+bool compopt_too_hard_for_direct_mode(const char *option);
+bool compopt_takes_path(const char *option);
+bool compopt_takes_arg(const char *option);
+
+#endif /* CCACHE_COMPOPT_H */
index 5e31a8fc773b2b5101ff83e0c0c7a5d1b91cbac8..661786b6236d2db89f5383d3629c2aff8a250a5c 100644 (file)
--- a/dev.mk.in
+++ b/dev.mk.in
@@ -23,7 +23,7 @@ built_dist_files = $(generated_docs)
 headers = \
     ccache.h hashtable.h hashtable_itr.h hashtable_private.h hashutil.h \
     manifest.h mdfour.h counters.h murmurhashneutral2.h getopt_long.h \
-    language.h system.h \
+    language.h system.h compopt.h \
     test/framework.h test/suites.h test/util.h
 
 files_to_clean += *.tar.bz2 *.tar.gz *.xml .deps/*
diff --git a/test/test_compopt.c b/test/test_compopt.c
new file mode 100644 (file)
index 0000000..509825c
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 Joel Rosdahl
+ *
+ * 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 3 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., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * This file contains tests for the compopt_* functions.
+ */
+
+#include "ccache.h"
+#include "compopt.h"
+#include "test/framework.h"
+
+TEST_SUITE(compopt)
+
+TEST(option_table_should_be_sorted)
+{
+       bool compopt_verify_sortedness();
+       CHECK(compopt_verify_sortedness());
+}
+
+TEST(dash_I_affects_cpp)
+{
+       CHECK(compopt_affects_cpp("-I"));
+       CHECK(!compopt_affects_cpp("-Ifoo"));
+}
+
+TEST(compopt_short)
+{
+       CHECK(compopt_short(compopt_affects_cpp, "-Ifoo"));
+       CHECK(!compopt_short(compopt_affects_cpp, "-include"));
+}
+
+TEST(dash_V_doesnt_affect_cpp)
+{
+       CHECK(!compopt_affects_cpp("-V"));
+}
+
+TEST(dash_doesnexist_doesnt_affect_cpp)
+{
+       CHECK(!compopt_affects_cpp("-doesntexist"));
+}
+
+TEST(dash_MM_too_hard)
+{
+       CHECK(compopt_too_hard("-MM"));
+}
+
+TEST(dash_MD_not_too_hard)
+{
+       CHECK(!compopt_too_hard("-MD"));
+}
+
+TEST(dash_doesnexist_not_too_hard)
+{
+       CHECK(!compopt_too_hard("-doesntexist"));
+}
+
+TEST(dash_Xpreprocessor_too_hard_for_direct_mode)
+{
+       CHECK(compopt_too_hard_for_direct_mode("-Xpreprocessor"));
+}
+
+TEST(dash_nostdinc_not_too_hard_for_direct_mode)
+{
+       CHECK(!compopt_too_hard_for_direct_mode("-nostdinc"));
+}
+
+TEST(dash_I_takes_path)
+{
+       CHECK(compopt_takes_path("-I"));
+}
+
+TEST(dash_Xlinker_takes_arg)
+{
+       CHECK(compopt_takes_arg("-Xlinker"));
+}
+
+TEST(dash_xxx_doesnt_take_arg)
+{
+       CHECK(!compopt_takes_arg("-xxx"));
+}
+
+TEST_SUITE_END