]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/opts-common.c
re PR target/44481 (__builtin_parity() causes ICE in trunc_int_for_mode())
[thirdparty/gcc.git] / gcc / opts-common.c
CommitLineData
14c7833c 1/* Command line option handling.
66647d44 2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
14c7833c
L
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
9dcd6f09 8Software Foundation; either version 3, or (at your option) any later
14c7833c
L
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
14c7833c
L
19
20#include "config.h"
21#include "system.h"
22#include "intl.h"
23#include "coretypes.h"
24#include "opts.h"
25
26/* Perform a binary search to find which option the command-line INPUT
27 matches. Returns its index in the option array, and N_OPTS
28 (cl_options_count) on failure.
29
30 This routine is quite subtle. A normal binary search is not good
31 enough because some options can be suffixed with an argument, and
32 multiple sub-matches can occur, e.g. input of "-pedantic" matching
33 the initial substring of "-pedantic-errors".
34
35 A more complicated example is -gstabs. It should match "-g" with
36 an argument of "stabs". Suppose, however, that the number and list
37 of switches are such that the binary search tests "-gen-decls"
38 before having tested "-g". This doesn't match, and as "-gen-decls"
39 is less than "-gstabs", it will become the lower bound of the
40 binary search range, and "-g" will never be seen. To resolve this
af47e6ac 41 issue, 'optc-gen.awk' makes "-gen-decls" point, via the back_chain member,
14c7833c
L
42 to "-g" so that failed searches that end between "-gen-decls" and
43 the lexicographically subsequent switch know to go back and see if
44 "-g" causes a match (which it does in this example).
45
46 This search is done in such a way that the longest match for the
47 front end in question wins. If there is no match for the current
48 front end, the longest match for a different front end is returned
49 (or N_OPTS if none) and the caller emits an error message. */
50size_t
51find_opt (const char *input, int lang_mask)
52{
53 size_t mn, mx, md, opt_len;
54 size_t match_wrong_lang;
55 int comp;
56
57 mn = 0;
58 mx = cl_options_count;
59
60 /* Find mn such this lexicographical inequality holds:
61 cl_options[mn] <= input < cl_options[mn + 1]. */
62 while (mx - mn > 1)
63 {
64 md = (mn + mx) / 2;
65 opt_len = cl_options[md].opt_len;
66 comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
67
68 if (comp < 0)
69 mx = md;
70 else
71 mn = md;
72 }
73
74 /* This is the switch that is the best match but for a different
75 front end, or cl_options_count if there is no match at all. */
76 match_wrong_lang = cl_options_count;
77
78 /* Backtrace the chain of possible matches, returning the longest
79 one, if any, that fits best. With current GCC switches, this
80 loop executes at most twice. */
81 do
82 {
83 const struct cl_option *opt = &cl_options[mn];
84
85 /* Is the input either an exact match or a prefix that takes a
86 joined argument? */
87 if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
88 && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
89 {
90 /* If language is OK, return it. */
91 if (opt->flags & lang_mask)
92 return mn;
93
94 /* If we haven't remembered a prior match, remember this
95 one. Any prior match is necessarily better. */
96 if (match_wrong_lang == cl_options_count)
97 match_wrong_lang = mn;
98 }
99
100 /* Try the next possibility. This is cl_options_count if there
101 are no more. */
102 mn = opt->back_chain;
103 }
104 while (mn != cl_options_count);
105
106 /* Return the best wrong match, or cl_options_count if none. */
107 return match_wrong_lang;
108}
109
110/* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the
111 next one is the same as ORIG_NEXT_OPT_IDX. */
112
113static bool
114cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx)
115{
116 /* An option can be canceled by the same option or an option with
117 Negative. */
118 if (cl_options [next_opt_idx].neg_index == opt_idx)
119 return true;
120
121 if (cl_options [next_opt_idx].neg_index != orig_next_opt_idx)
122 return cancel_option (opt_idx, cl_options [next_opt_idx].neg_index,
123 orig_next_opt_idx);
b8698a0f 124
14c7833c
L
125 return false;
126}
127
128/* Filter out options canceled by the ones after them. */
129
130void
131prune_options (int *argcp, char ***argvp)
132{
133 int argc = *argcp;
d3bfe4de 134 int *options = XNEWVEC (int, argc);
807303cf
DK
135 /* We will only return this replacement argv if we remove at least
136 one argument, so it does not need to be size (argc + 1) to
137 make room for the terminating NULL because we will always have
138 freed up at least one slot when we end up using it at all. */
d3bfe4de 139 char **argv = XNEWVEC (char *, argc);
14c7833c
L
140 int i, arg_count, need_prune = 0;
141 const struct cl_option *option;
142 size_t opt_index;
143
144 /* Scan all arguments. */
145 for (i = 1; i < argc; i++)
146 {
147 int value = 1;
148 const char *opt = (*argvp) [i];
149
150 opt_index = find_opt (opt + 1, -1);
151 if (opt_index == cl_options_count
152 && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm')
153 && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
154 {
155 char *dup;
156
157 /* Drop the "no-" from negative switches. */
158 size_t len = strlen (opt) - 3;
159
160 dup = XNEWVEC (char, len + 1);
161 dup[0] = '-';
162 dup[1] = opt[1];
163 memcpy (dup + 2, opt + 5, len - 2 + 1);
164 opt = dup;
165 value = 0;
166 opt_index = find_opt (opt + 1, -1);
167 free (dup);
168 }
169
170 if (opt_index == cl_options_count)
171 {
172cont:
173 options [i] = 0;
174 continue;
175 }
176
177 option = &cl_options[opt_index];
178 if (option->neg_index < 0)
179 goto cont;
180
faa88843
L
181 /* Skip joined switches. */
182 if ((option->flags & CL_JOINED))
183 goto cont;
184
14c7833c
L
185 /* Reject negative form of switches that don't take negatives as
186 unrecognized. */
187 if (!value && (option->flags & CL_REJECT_NEGATIVE))
188 goto cont;
189
190 options [i] = (int) opt_index;
191 need_prune |= options [i];
192 }
193
194 if (!need_prune)
195 goto done;
196
197 /* Remove arguments which are negated by others after them. */
198 argv [0] = (*argvp) [0];
199 arg_count = 1;
200 for (i = 1; i < argc; i++)
201 {
202 int j, opt_idx;
203
204 opt_idx = options [i];
205 if (opt_idx)
206 {
207 int next_opt_idx;
208 for (j = i + 1; j < argc; j++)
209 {
210 next_opt_idx = options [j];
211 if (next_opt_idx
212 && cancel_option (opt_idx, next_opt_idx,
213 next_opt_idx))
214 break;
215 }
216 }
217 else
218 goto keep;
219
220 if (j == argc)
221 {
222keep:
223 argv [arg_count] = (*argvp) [i];
224 arg_count++;
225 }
226 }
227
228 if (arg_count != argc)
229 {
230 *argcp = arg_count;
231 *argvp = argv;
807303cf
DK
232 /* Add NULL-termination. Guaranteed not to overflow because
233 arg_count here can only be less than argc. */
234 argv[arg_count] = 0;
14c7833c
L
235 }
236 else
237 {
238done:
239 free (argv);
240 }
241
242 free (options);
243}