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