Imported Upstream version 3.2.6
[platform/upstream/ccache.git] / compopt.c
1 /*
2  * Copyright (C) 2010-2016 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         {"--save-temps",    TOO_HARD},
37         {"--serialize-diagnostics", TAKES_ARG | TAKES_PATH},
38         {"-A",              TAKES_ARG},
39         {"-D",              AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
40         {"-E",              TOO_HARD},
41         {"-F",              AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
42         {"-G",              TAKES_ARG},
43         {"-I",              AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
44         {"-L",              TAKES_ARG},
45         {"-M",              TOO_HARD},
46         {"-MF",             TAKES_ARG},
47         {"-MM",             TOO_HARD},
48         {"-MQ",             TAKES_ARG},
49         {"-MT",             TAKES_ARG},
50         {"-U",              AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
51         {"-V",              TAKES_ARG},
52         {"-Xassembler",     TAKES_ARG},
53         {"-Xclang",         TAKES_ARG},
54         {"-Xlinker",        TAKES_ARG},
55         {"-Xpreprocessor",  AFFECTS_CPP | TOO_HARD_DIRECT | TAKES_ARG},
56         {"-arch",           TAKES_ARG},
57         {"-aux-info",       TAKES_ARG},
58         {"-b",              TAKES_ARG},
59         {"-fmodules",       TOO_HARD},
60         {"-fno-working-directory", AFFECTS_CPP},
61         {"-fplugin=libcc1plugin", TOO_HARD}, /* interaction with GDB */
62         {"-frepo",          TOO_HARD},
63         {"-fstack-usage",   TOO_HARD},
64         {"-fworking-directory", AFFECTS_CPP},
65         {"-idirafter",      AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
66         {"-iframework",     AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
67         {"-imacros",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
68         {"-imultilib",      AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
69         {"-include",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
70         {"-include-pch",    AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
71         {"-install_name",   TAKES_ARG}, /* Darwin linker option */
72         {"-iprefix",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
73         {"-iquote",         AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
74         {"-isysroot",       AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
75         {"-isystem",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
76         {"-iwithprefix",    AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
77         {"-iwithprefixbefore", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
78         {"-nostdinc",       AFFECTS_CPP},
79         {"-nostdinc++",     AFFECTS_CPP},
80         {"-remap",          AFFECTS_CPP},
81         {"-save-temps",     TOO_HARD},
82         {"-stdlib=",        AFFECTS_CPP | TAKES_CONCAT_ARG},
83         {"-trigraphs",      AFFECTS_CPP},
84         {"-u",              TAKES_ARG},
85 };
86
87
88 static int
89 compare_compopts(const void *key1, const void *key2)
90 {
91         const struct compopt *opt1 = (const struct compopt *)key1;
92         const struct compopt *opt2 = (const struct compopt *)key2;
93         return strcmp(opt1->name, opt2->name);
94 }
95
96 static int
97 compare_prefix_compopts(const void *key1, const void *key2)
98 {
99         const struct compopt *opt1 = (const struct compopt *)key1;
100         const struct compopt *opt2 = (const struct compopt *)key2;
101         return strncmp(opt1->name, opt2->name, strlen(opt2->name));
102 }
103
104 static const struct compopt *
105 find(const char *option)
106 {
107         struct compopt key;
108         key.name = option;
109         return bsearch(
110                  &key, compopts, sizeof(compopts) / sizeof(compopts[0]),
111                  sizeof(compopts[0]), compare_compopts);
112 }
113
114 static const struct compopt *
115 find_prefix(const char *option)
116 {
117         struct compopt key;
118         key.name = option;
119         return bsearch(
120                  &key, compopts, sizeof(compopts) / sizeof(compopts[0]),
121                  sizeof(compopts[0]), compare_prefix_compopts);
122 }
123
124 /* Runs fn on the first two characters of option. */
125 bool
126 compopt_short(bool (*fn)(const char *), const char *option)
127 {
128         char *short_opt = x_strndup(option, 2);
129         bool retval = fn(short_opt);
130         free(short_opt);
131         return retval;
132 }
133
134 /* For test purposes. */
135 bool
136 compopt_verify_sortedness(void)
137 {
138         size_t i;
139         for (i = 1; i < sizeof(compopts)/sizeof(compopts[0]); i++) {
140                 if (strcmp(compopts[i-1].name, compopts[i].name) >= 0) {
141                         fprintf(stderr,
142                                 "compopt_verify_sortedness: %s >= %s\n",
143                                 compopts[i-1].name,
144                                 compopts[i].name);
145                         return false;
146                 }
147         }
148         return true;
149 }
150
151 bool
152 compopt_affects_cpp(const char *option)
153 {
154         const struct compopt *co = find(option);
155         return co && (co->type & AFFECTS_CPP);
156 }
157
158 bool
159 compopt_too_hard(const char *option)
160 {
161         const struct compopt *co = find(option);
162         return co && (co->type & TOO_HARD);
163 }
164
165 bool
166 compopt_too_hard_for_direct_mode(const char *option)
167 {
168         const struct compopt *co = find(option);
169         return co && (co->type & TOO_HARD_DIRECT);
170 }
171
172 bool
173 compopt_takes_path(const char *option)
174 {
175         const struct compopt *co = find(option);
176         return co && (co->type & TAKES_PATH);
177 }
178
179 bool
180 compopt_takes_arg(const char *option)
181 {
182         const struct compopt *co = find(option);
183         return co && (co->type & TAKES_ARG);
184 }
185
186 /* Determines if the prefix of the option matches any option and affects the
187  * preprocessor.
188  */
189 bool
190 compopt_prefix_affects_cpp(const char *option)
191 {
192         /* prefix options have to take concatentated args */
193         const struct compopt *co = find_prefix(option);
194         return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_CPP);
195 }