1 /* Command line option handling. 2 Copyright (C) 2006 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 2, 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 COPYING. If not, write to the Free 18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301, USA. */ 20 21 #include "config.h" 22 #include "system.h" 23 #include "intl.h" 24 #include "coretypes.h" 25 #include "opts.h" 26 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. 30 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". 35 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). 46 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) 53 { 54 size_t mn, mx, md, opt_len; 55 size_t match_wrong_lang; 56 int comp; 57 58 mn = 0; 59 mx = cl_options_count; 60 61 /* Find mn such this lexicographical inequality holds: 62 cl_options[mn] <= input < cl_options[mn + 1]. */ 63 while (mx - mn > 1) 64 { 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); 68 69 if (comp < 0) 70 mx = md; 71 else 72 mn = md; 73 } 74 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; 78 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. */ 82 do 83 { 84 const struct cl_option *opt = &cl_options[mn]; 85 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))) 90 { 91 /* If language is OK, return it. */ 92 if (opt->flags & lang_mask) 93 return mn; 94 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; 99 } 100 101 /* Try the next possibility. This is cl_options_count if there 102 are no more. */ 103 mn = opt->back_chain; 104 } 105 while (mn != cl_options_count); 106 107 /* Return the best wrong match, or cl_options_count if none. */ 108 return match_wrong_lang; 109 } 110 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. */ 113 114 static bool 115 cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx) 116 { 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; 121 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); 125 126 return false; 127 } 128 129 /* Filter out options canceled by the ones after them. */ 130 131 void 132 prune_options (int *argcp, char ***argvp) 133 { 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; 140 141 /* Scan all arguments. */ 142 for (i = 1; i < argc; i++) 143 { 144 int value = 1; 145 const char *opt = (*argvp) [i]; 146 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] == '-') 151 { 152 char *dup; 153 154 /* Drop the "no-" from negative switches. */ 155 size_t len = strlen (opt) - 3; 156 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); 165 } 166 167 if (opt_index == cl_options_count) 168 { 169 cont: 170 options [i] = 0; 171 continue; 172 } 173 174 option = &cl_options[opt_index]; 175 if (option->neg_index < 0) 176 goto cont; 177 178 /* Skip joined switches. */ 179 if ((option->flags & CL_JOINED)) 180 goto cont; 181 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; 186 187 options [i] = (int) opt_index; 188 need_prune |= options [i]; 189 } 190 191 if (!need_prune) 192 goto done; 193 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++) 198 { 199 int j, opt_idx; 200 201 opt_idx = options [i]; 202 if (opt_idx) 203 { 204 int next_opt_idx; 205 for (j = i + 1; j < argc; j++) 206 { 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; 212 } 213 } 214 else 215 goto keep; 216 217 if (j == argc) 218 { 219 keep: 220 argv [arg_count] = (*argvp) [i]; 221 arg_count++; 222 } 223 } 224 225 if (arg_count != argc) 226 { 227 *argcp = arg_count; 228 *argvp = argv; 229 } 230 else 231 { 232 done: 233 free (argv); 234 } 235 236 free (options); 237 } 238