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