2007-03-01 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / opts-common.c
blob958e667732254d172db6a43363777832ed6a6c07
1 /* Command line option handling.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "intl.h"
24 #include "coretypes.h"
25 #include "opts.h"
27 /* Perform a binary search to find which option the command-line INPUT
28 matches. Returns its index in the option array, and N_OPTS
29 (cl_options_count) on failure.
31 This routine is quite subtle. A normal binary search is not good
32 enough because some options can be suffixed with an argument, and
33 multiple sub-matches can occur, e.g. input of "-pedantic" matching
34 the initial substring of "-pedantic-errors".
36 A more complicated example is -gstabs. It should match "-g" with
37 an argument of "stabs". Suppose, however, that the number and list
38 of switches are such that the binary search tests "-gen-decls"
39 before having tested "-g". This doesn't match, and as "-gen-decls"
40 is less than "-gstabs", it will become the lower bound of the
41 binary search range, and "-g" will never be seen. To resolve this
42 issue, opts.sh makes "-gen-decls" point, via the back_chain member,
43 to "-g" so that failed searches that end between "-gen-decls" and
44 the lexicographically subsequent switch know to go back and see if
45 "-g" causes a match (which it does in this example).
47 This search is done in such a way that the longest match for the
48 front end in question wins. If there is no match for the current
49 front end, the longest match for a different front end is returned
50 (or N_OPTS if none) and the caller emits an error message. */
51 size_t
52 find_opt (const char *input, int lang_mask)
54 size_t mn, mx, md, opt_len;
55 size_t match_wrong_lang;
56 int comp;
58 mn = 0;
59 mx = cl_options_count;
61 /* Find mn such this lexicographical inequality holds:
62 cl_options[mn] <= input < cl_options[mn + 1]. */
63 while (mx - mn > 1)
65 md = (mn + mx) / 2;
66 opt_len = cl_options[md].opt_len;
67 comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
69 if (comp < 0)
70 mx = md;
71 else
72 mn = md;
75 /* This is the switch that is the best match but for a different
76 front end, or cl_options_count if there is no match at all. */
77 match_wrong_lang = cl_options_count;
79 /* Backtrace the chain of possible matches, returning the longest
80 one, if any, that fits best. With current GCC switches, this
81 loop executes at most twice. */
84 const struct cl_option *opt = &cl_options[mn];
86 /* Is the input either an exact match or a prefix that takes a
87 joined argument? */
88 if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
89 && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
91 /* If language is OK, return it. */
92 if (opt->flags & lang_mask)
93 return mn;
95 /* If we haven't remembered a prior match, remember this
96 one. Any prior match is necessarily better. */
97 if (match_wrong_lang == cl_options_count)
98 match_wrong_lang = mn;
101 /* Try the next possibility. This is cl_options_count if there
102 are no more. */
103 mn = opt->back_chain;
105 while (mn != cl_options_count);
107 /* Return the best wrong match, or cl_options_count if none. */
108 return match_wrong_lang;
111 /* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the
112 next one is the same as ORIG_NEXT_OPT_IDX. */
114 static bool
115 cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx)
117 /* An option can be canceled by the same option or an option with
118 Negative. */
119 if (cl_options [next_opt_idx].neg_index == opt_idx)
120 return true;
122 if (cl_options [next_opt_idx].neg_index != orig_next_opt_idx)
123 return cancel_option (opt_idx, cl_options [next_opt_idx].neg_index,
124 orig_next_opt_idx);
126 return false;
129 /* Filter out options canceled by the ones after them. */
131 void
132 prune_options (int *argcp, char ***argvp)
134 int argc = *argcp;
135 int *options = xmalloc (argc * sizeof (*options));
136 char **argv = xmalloc (argc * sizeof (char *));
137 int i, arg_count, need_prune = 0;
138 const struct cl_option *option;
139 size_t opt_index;
141 /* Scan all arguments. */
142 for (i = 1; i < argc; i++)
144 int value = 1;
145 const char *opt = (*argvp) [i];
147 opt_index = find_opt (opt + 1, -1);
148 if (opt_index == cl_options_count
149 && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm')
150 && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
152 char *dup;
154 /* Drop the "no-" from negative switches. */
155 size_t len = strlen (opt) - 3;
157 dup = XNEWVEC (char, len + 1);
158 dup[0] = '-';
159 dup[1] = opt[1];
160 memcpy (dup + 2, opt + 5, len - 2 + 1);
161 opt = dup;
162 value = 0;
163 opt_index = find_opt (opt + 1, -1);
164 free (dup);
167 if (opt_index == cl_options_count)
169 cont:
170 options [i] = 0;
171 continue;
174 option = &cl_options[opt_index];
175 if (option->neg_index < 0)
176 goto cont;
178 /* Skip joined switches. */
179 if ((option->flags & CL_JOINED))
180 goto cont;
182 /* Reject negative form of switches that don't take negatives as
183 unrecognized. */
184 if (!value && (option->flags & CL_REJECT_NEGATIVE))
185 goto cont;
187 options [i] = (int) opt_index;
188 need_prune |= options [i];
191 if (!need_prune)
192 goto done;
194 /* Remove arguments which are negated by others after them. */
195 argv [0] = (*argvp) [0];
196 arg_count = 1;
197 for (i = 1; i < argc; i++)
199 int j, opt_idx;
201 opt_idx = options [i];
202 if (opt_idx)
204 int next_opt_idx;
205 for (j = i + 1; j < argc; j++)
207 next_opt_idx = options [j];
208 if (next_opt_idx
209 && cancel_option (opt_idx, next_opt_idx,
210 next_opt_idx))
211 break;
214 else
215 goto keep;
217 if (j == argc)
219 keep:
220 argv [arg_count] = (*argvp) [i];
221 arg_count++;
225 if (arg_count != argc)
227 *argcp = arg_count;
228 *argvp = argv;
230 else
232 done:
233 free (argv);
236 free (options);