1/* Command line option handling.
2   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
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
8Software Foundation; either version 3, or (at your option) any later
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
17along with GCC; see the file COPYING3.  If not see
18<http://www.gnu.org/licenses/>.  */
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
41   issue, 'optc-gen.awk' makes "-gen-decls" point, via the back_chain member,
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);
124
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;
134  int *options = XNEWVEC (int, argc);
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.  */
139  char **argv = XNEWVEC (char *, argc);
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
181      /* Skip joined switches.  */
182      if ((option->flags & CL_JOINED))
183	goto cont;
184
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;
232      /* Add NULL-termination.  Guaranteed not to overflow because
233	 arg_count here can only be less than argc.  */
234      argv[arg_count] = 0;
235    }
236  else
237    {
238done:
239      free (argv);
240    }
241
242  free (options);
243}
244