Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2010-2015 Joel Rosdahl
3 : : *
4 : : * This program is free software; you can redistribute it and/or modify it
5 : : * under the terms of the GNU General Public License as published by the Free
6 : : * Software Foundation; either version 3 of the License, or (at your option)
7 : : * any later version.
8 : : *
9 : : * This program is distributed in the hope that it will be useful, but WITHOUT
10 : : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 : : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 : : * more details.
13 : : *
14 : : * You should have received a copy of the GNU General Public License along with
15 : : * this program; if not, write to the Free Software Foundation, Inc., 51
16 : : * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 : : */
18 : :
19 : : #include "ccache.h"
20 : : #include "compopt.h"
21 : :
22 : : #define TOO_HARD (1 << 0)
23 : : #define TOO_HARD_DIRECT (1 << 1)
24 : : #define TAKES_ARG (1 << 2)
25 : : #define TAKES_CONCAT_ARG (1 << 3)
26 : : #define TAKES_PATH (1 << 4)
27 : : #define AFFECTS_CPP (1 << 5)
28 : :
29 : : struct compopt {
30 : : const char *name;
31 : : int type;
32 : : };
33 : :
34 : : static const struct compopt compopts[] = {
35 : : {"--param", TAKES_ARG},
36 : : {"--serialize-diagnostics", TAKES_ARG | TAKES_PATH},
37 : : {"-A", TAKES_ARG},
38 : : {"-D", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
39 : : {"-E", TOO_HARD},
40 : : {"-F", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
41 : : {"-G", TAKES_ARG},
42 : : {"-I", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
43 : : {"-L", TAKES_ARG},
44 : : {"-M", TOO_HARD},
45 : : {"-MF", TAKES_ARG},
46 : : {"-MM", TOO_HARD},
47 : : {"-MQ", TAKES_ARG},
48 : : {"-MT", TAKES_ARG},
49 : : {"-U", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
50 : : {"-V", TAKES_ARG},
51 : : {"-Xassembler", TAKES_ARG},
52 : : {"-Xclang", TAKES_ARG},
53 : : {"-Xlinker", TAKES_ARG},
54 : : {"-Xpreprocessor", AFFECTS_CPP | TOO_HARD_DIRECT | TAKES_ARG},
55 : : {"-arch", TAKES_ARG},
56 : : {"-aux-info", TAKES_ARG},
57 : : {"-b", TAKES_ARG},
58 : : {"-fmodules", TOO_HARD},
59 : : {"-fno-working-directory", AFFECTS_CPP},
60 : : {"-fplugin=libcc1plugin", TOO_HARD}, /* interaction with GDB */
61 : : {"-frepo", TOO_HARD},
62 : : {"-fworking-directory", AFFECTS_CPP},
63 : : {"-idirafter", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
64 : : {"-iframework", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
65 : : {"-imacros", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
66 : : {"-imultilib", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
67 : : {"-include", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
68 : : {"-include-pch", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
69 : : {"-install_name", TAKES_ARG}, /* Darwin linker option */
70 : : {"-iprefix", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
71 : : {"-iquote", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
72 : : {"-isysroot", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
73 : : {"-isystem", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
74 : : {"-iwithprefix", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
75 : : {"-iwithprefixbefore", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
76 : : {"-nostdinc", AFFECTS_CPP},
77 : : {"-nostdinc++", AFFECTS_CPP},
78 : : {"-remap", AFFECTS_CPP},
79 : : {"-save-temps", TOO_HARD},
80 : : {"-trigraphs", AFFECTS_CPP},
81 : : {"-u", TAKES_ARG},
82 : : };
83 : :
84 : :
85 : : static int
86 : 1799 : compare_compopts(const void *key1, const void *key2)
87 : : {
88 : 1799 : const struct compopt *opt1 = (const struct compopt *)key1;
89 : 1799 : const struct compopt *opt2 = (const struct compopt *)key2;
90 : 1799 : return strcmp(opt1->name, opt2->name);
91 : : }
92 : :
93 : : static int
94 : 18 : compare_prefix_compopts(const void *key1, const void *key2)
95 : : {
96 : 18 : const struct compopt *opt1 = (const struct compopt *)key1;
97 : 18 : const struct compopt *opt2 = (const struct compopt *)key2;
98 : 18 : return strncmp(opt1->name, opt2->name, strlen(opt2->name));
99 : : }
100 : :
101 : : static const struct compopt *
102 : 339 : find(const char *option)
103 : : {
104 : : struct compopt key;
105 : 339 : key.name = option;
106 : 339 : return bsearch(
107 : : &key, compopts, sizeof(compopts) / sizeof(compopts[0]),
108 : : sizeof(compopts[0]), compare_compopts);
109 : : }
110 : :
111 : : static const struct compopt *
112 : 4 : find_prefix(const char *option)
113 : : {
114 : : struct compopt key;
115 : 4 : key.name = option;
116 : 4 : return bsearch(
117 : : &key, compopts, sizeof(compopts) / sizeof(compopts[0]),
118 : : sizeof(compopts[0]), compare_prefix_compopts);
119 : : }
120 : :
121 : : /* Runs fn on the first two characters of option. */
122 : : bool
123 : 28 : compopt_short(bool (*fn)(const char *), const char *option)
124 : : {
125 : 28 : char *short_opt = x_strndup(option, 2);
126 : 28 : bool retval = fn(short_opt);
127 : 28 : free(short_opt);
128 : 28 : return retval;
129 : : }
130 : :
131 : : /* For test purposes. */
132 : : bool
133 : 1 : compopt_verify_sortedness(void)
134 : : {
135 : : size_t i;
136 [ + + ]: 47 : for (i = 1; i < sizeof(compopts)/sizeof(compopts[0]); i++) {
137 [ - + ]: 46 : if (strcmp(compopts[i-1].name, compopts[i].name) >= 0) {
138 : 0 : fprintf(stderr,
139 : : "compopt_verify_sortedness: %s >= %s\n",
140 : 0 : compopts[i-1].name,
141 : : compopts[i].name);
142 : 0 : return false;
143 : : }
144 : : }
145 : 1 : return true;
146 : : }
147 : :
148 : : bool
149 : 25 : compopt_affects_cpp(const char *option)
150 : : {
151 : 25 : const struct compopt *co = find(option);
152 [ + + ][ + + ]: 25 : return co && (co->type & AFFECTS_CPP);
153 : : }
154 : :
155 : : bool
156 : 118 : compopt_too_hard(const char *option)
157 : : {
158 : 118 : const struct compopt *co = find(option);
159 [ + + ][ + + ]: 118 : return co && (co->type & TOO_HARD);
160 : : }
161 : :
162 : : bool
163 : 112 : compopt_too_hard_for_direct_mode(const char *option)
164 : : {
165 : 112 : const struct compopt *co = find(option);
166 [ + + ][ + + ]: 112 : return co && (co->type & TOO_HARD_DIRECT);
167 : : }
168 : :
169 : : bool
170 : 60 : compopt_takes_path(const char *option)
171 : : {
172 : 60 : const struct compopt *co = find(option);
173 [ + + ][ + + ]: 60 : return co && (co->type & TAKES_PATH);
174 : : }
175 : :
176 : : bool
177 : 24 : compopt_takes_arg(const char *option)
178 : : {
179 : 24 : const struct compopt *co = find(option);
180 [ + + ][ + + ]: 24 : return co && (co->type & TAKES_ARG);
181 : : }
182 : :
183 : : /* Determines if argument takes a concatentated argument by comparing prefixes.
184 : : */
185 : : bool
186 : 0 : compopt_takes_concat_arg(const char *option)
187 : : {
188 : 0 : const struct compopt *co = find_prefix(option);
189 [ # # ][ # # ]: 0 : return co && (co->type & TAKES_CONCAT_ARG);
190 : : }
191 : :
192 : : /* Determines if the prefix of the option matches any option and affects the
193 : : * preprocessor.
194 : : */
195 : : bool
196 : 4 : compopt_prefix_affects_cpp(const char *option)
197 : : {
198 : : /* prefix options have to take concatentated args */
199 : 4 : const struct compopt *co = find_prefix(option);
200 [ + - ][ + - ]: 4 : return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_CPP);
[ + - ]
201 : : }
|