]>
Commit | Line | Data |
---|---|---|
2772ef3e NB |
1 | /* Command line option handling. |
2 | Copyright (C) 2002, 2003 Free Software Foundation, Inc. | |
3 | Contributed by Neil Booth. | |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 2, or (at your option) any later | |
10 | version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING. If not, write to the Free | |
19 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
20 | 02111-1307, USA. */ | |
21 | ||
22 | #include "config.h" | |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
25 | #include "tm.h" | |
26 | #include "tree.h" | |
27 | #include "langhooks.h" | |
28 | #include "opts.h" | |
d7b42618 NB |
29 | #include "options.h" |
30 | #include "flags.h" | |
31 | #include "toplev.h" | |
2772ef3e | 32 | |
35399bdc | 33 | static size_t find_opt (const char *, int); |
d7b42618 | 34 | static int common_handle_option (size_t scode, const char *arg, int value); |
2772ef3e NB |
35 | |
36 | /* Perform a binary search to find which option the command-line INPUT | |
37 | matches. Returns its index in the option array, and N_OPTS on | |
38 | failure. | |
39 | ||
40 | Complications arise since some options can be suffixed with an | |
41 | argument, and multiple complete matches can occur, e.g. -pedantic | |
42 | and -pedantic-errors. Also, some options are only accepted by some | |
43 | languages. If a switch matches for a different language and | |
44 | doesn't match any alternatives for the true front end, the index of | |
45 | the matched switch is returned anyway. The caller should check for | |
46 | this case. */ | |
35399bdc | 47 | static size_t |
2772ef3e NB |
48 | find_opt (const char *input, int lang_mask) |
49 | { | |
50 | size_t md, mn, mx; | |
51 | size_t opt_len; | |
35399bdc | 52 | size_t result = cl_options_count; |
2772ef3e NB |
53 | int comp; |
54 | ||
55 | mn = 0; | |
35399bdc | 56 | mx = cl_options_count; |
2772ef3e NB |
57 | |
58 | while (mx > mn) | |
59 | { | |
60 | md = (mn + mx) / 2; | |
61 | ||
62 | opt_len = cl_options[md].opt_len; | |
63 | comp = strncmp (input, cl_options[md].opt_text, opt_len); | |
64 | ||
65 | if (comp < 0) | |
66 | mx = md; | |
67 | else if (comp > 0) | |
68 | mn = md + 1; | |
69 | else | |
70 | { | |
71 | /* The switch matches. It it an exact match? */ | |
72 | if (input[opt_len] == '\0') | |
73 | return md; | |
74 | else | |
75 | { | |
76 | mn = md + 1; | |
77 | ||
78 | /* If the switch takes no arguments this is not a proper | |
79 | match, so we continue the search (e.g. input="stdc++" | |
80 | match was "stdc"). */ | |
81 | if (!(cl_options[md].flags & CL_JOINED)) | |
82 | continue; | |
83 | ||
84 | /* Is this switch valid for this front end? */ | |
85 | if (!(cl_options[md].flags & lang_mask)) | |
86 | { | |
87 | /* If subsequently we don't find a better match, | |
88 | return this and let the caller report it as a bad | |
89 | match. */ | |
35399bdc | 90 | result = md; |
2772ef3e NB |
91 | continue; |
92 | } | |
93 | ||
94 | /* Two scenarios remain: we have the switch's argument, | |
95 | or we match a longer option. This can happen with | |
96 | -iwithprefix and -withprefixbefore. The longest | |
97 | possible option match succeeds. | |
98 | ||
99 | Scan forwards, and return an exact match. Otherwise | |
100 | return the longest valid option-accepting match (mx). | |
101 | This loops at most twice with current options. */ | |
102 | mx = md; | |
35399bdc | 103 | for (md = md + 1; md < cl_options_count; md++) |
2772ef3e NB |
104 | { |
105 | opt_len = cl_options[md].opt_len; | |
106 | if (strncmp (input, cl_options[md].opt_text, opt_len)) | |
107 | break; | |
108 | if (input[opt_len] == '\0') | |
109 | return md; | |
110 | if (cl_options[md].flags & lang_mask | |
111 | && cl_options[md].flags & CL_JOINED) | |
112 | mx = md; | |
113 | } | |
114 | ||
115 | return mx; | |
116 | } | |
117 | } | |
118 | } | |
119 | ||
120 | return result; | |
121 | } | |
122 | ||
123 | /* Handle the switch beginning at ARGV, with ARGC remaining. */ | |
124 | int | |
7fb26bb0 | 125 | handle_option (int argc ATTRIBUTE_UNUSED, char **argv, int lang_mask) |
2772ef3e NB |
126 | { |
127 | size_t opt_index; | |
128 | const char *opt, *arg = 0; | |
129 | char *dup = 0; | |
130 | bool on = true; | |
131 | int result = 0, temp; | |
132 | const struct cl_option *option; | |
133 | ||
2772ef3e NB |
134 | opt = argv[0]; |
135 | ||
136 | /* Interpret "-" or a non-switch as a file name. */ | |
137 | if (opt[0] != '-' || opt[1] == '\0') | |
138 | { | |
35399bdc | 139 | opt_index = cl_options_count; |
2772ef3e | 140 | arg = opt; |
d7b42618 NB |
141 | main_input_filename = opt; |
142 | result = (*lang_hooks.handle_option) (opt_index, arg, on); | |
2772ef3e NB |
143 | } |
144 | else | |
145 | { | |
146 | /* Drop the "no-" from negative switches. */ | |
147 | if ((opt[1] == 'W' || opt[1] == 'f') | |
148 | && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') | |
149 | { | |
150 | size_t len = strlen (opt) - 3; | |
151 | ||
152 | dup = xmalloc (len + 1); | |
153 | dup[0] = '-'; | |
154 | dup[1] = opt[1]; | |
155 | memcpy (dup + 2, opt + 5, len - 2 + 1); | |
156 | opt = dup; | |
157 | on = false; | |
158 | } | |
159 | ||
d7b42618 | 160 | opt_index = find_opt (opt + 1, lang_mask | CL_COMMON); |
35399bdc | 161 | if (opt_index == cl_options_count) |
2772ef3e NB |
162 | goto done; |
163 | ||
164 | option = &cl_options[opt_index]; | |
165 | ||
166 | /* Reject negative form of switches that don't take negatives. */ | |
167 | if (!on && (option->flags & CL_REJECT_NEGATIVE)) | |
168 | goto done; | |
169 | ||
6356f892 | 170 | /* We've recognized this switch. */ |
2772ef3e NB |
171 | result = 1; |
172 | ||
173 | /* Sort out any argument the switch takes. */ | |
174 | if (option->flags & (CL_JOINED | CL_SEPARATE)) | |
175 | { | |
176 | if (option->flags & CL_JOINED) | |
177 | { | |
178 | /* Have arg point to the original switch. This is because | |
179 | some code, such as disable_builtin_function, expects its | |
180 | argument to be persistent until the program exits. */ | |
181 | arg = argv[0] + cl_options[opt_index].opt_len + 1; | |
182 | if (!on) | |
183 | arg += strlen ("no-"); | |
184 | } | |
185 | ||
186 | /* If we don't have an argument, and CL_SEPARATE, try the next | |
187 | argument in the vector. */ | |
188 | if (!arg || (*arg == '\0' && option->flags & CL_SEPARATE)) | |
189 | { | |
190 | arg = argv[1]; | |
191 | result = 2; | |
192 | } | |
193 | ||
194 | /* Canonicalize missing arguments as NULL for the handler. */ | |
195 | if (*arg == '\0') | |
196 | arg = NULL; | |
197 | } | |
2772ef3e | 198 | |
d7b42618 NB |
199 | if (option->flags & lang_mask) |
200 | { | |
201 | temp = (*lang_hooks.handle_option) (opt_index, arg, on); | |
202 | if (temp <= 0) | |
203 | result = temp; | |
204 | } | |
205 | ||
206 | if (result > 0 && (option->flags & CL_COMMON)) | |
207 | { | |
208 | if (common_handle_option (opt_index, arg, on) == 0) | |
209 | result = 0; | |
210 | } | |
211 | } | |
2772ef3e NB |
212 | |
213 | done: | |
214 | if (dup) | |
215 | free (dup); | |
216 | return result; | |
217 | } | |
d7b42618 NB |
218 | |
219 | /* Handle target- and language-independent options. Return zero to | |
220 | generate an "unknown option" message. */ | |
221 | static int | |
222 | common_handle_option (size_t scode, const char *arg, | |
223 | int value ATTRIBUTE_UNUSED) | |
224 | { | |
225 | const struct cl_option *option = &cl_options[scode]; | |
226 | enum opt_code code = (enum opt_code) scode; | |
227 | ||
228 | if (arg == NULL && (option->flags & (CL_JOINED | CL_SEPARATE))) | |
229 | { | |
230 | error ("missing argument to \"-%s\"", option->opt_text); | |
231 | return 1; | |
232 | } | |
233 | ||
234 | switch (code) | |
235 | { | |
236 | default: | |
237 | abort (); | |
238 | ||
239 | case OPT_quiet: | |
240 | quiet_flag = 1; | |
241 | break; | |
242 | } | |
243 | ||
244 | return 1; | |
245 | } |