From: Joel Rosdahl Date: Wed, 1 Sep 2010 20:49:41 +0000 (+0200) Subject: Move lists of compiler options' semantics into a separate compopt.c file X-Git-Tag: v3.1~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2c2b582266fc08f6a18fdba7576b21d7a310e289;p=thirdparty%2Fccache.git Move lists of compiler options' semantics into a separate compopt.c file --- diff --git a/Makefile.in b/Makefile.in index 9f4a91086..b095e1c83 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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) diff --git a/ccache.c b/ccache.c index 41bb200c0..fa2f10ef8 100644 --- a/ccache.c +++ b/ccache.c @@ -20,6 +20,7 @@ */ #include "ccache.h" +#include "compopt.h" #ifdef HAVE_GETOPT_LONG #include #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 index 000000000..48cbb77ae --- /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 index 000000000..8985ac3d7 --- /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 */ diff --git a/dev.mk.in b/dev.mk.in index 5e31a8fc7..661786b62 100644 --- 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 index 000000000..509825c8d --- /dev/null +++ b/test/test_compopt.c @@ -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