aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.2.1-5666.3/gcc/opts-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.2.1-5666.3/gcc/opts-common.c')
-rw-r--r--gcc-4.2.1-5666.3/gcc/opts-common.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/gcc-4.2.1-5666.3/gcc/opts-common.c b/gcc-4.2.1-5666.3/gcc/opts-common.c
new file mode 100644
index 000000000..958e66773
--- /dev/null
+++ b/gcc-4.2.1-5666.3/gcc/opts-common.c
@@ -0,0 +1,237 @@
+/* Command line option handling.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "intl.h"
+#include "coretypes.h"
+#include "opts.h"
+
+/* Perform a binary search to find which option the command-line INPUT
+ matches. Returns its index in the option array, and N_OPTS
+ (cl_options_count) on failure.
+
+ This routine is quite subtle. A normal binary search is not good
+ enough because some options can be suffixed with an argument, and
+ multiple sub-matches can occur, e.g. input of "-pedantic" matching
+ the initial substring of "-pedantic-errors".
+
+ A more complicated example is -gstabs. It should match "-g" with
+ an argument of "stabs". Suppose, however, that the number and list
+ of switches are such that the binary search tests "-gen-decls"
+ before having tested "-g". This doesn't match, and as "-gen-decls"
+ is less than "-gstabs", it will become the lower bound of the
+ binary search range, and "-g" will never be seen. To resolve this
+ issue, opts.sh makes "-gen-decls" point, via the back_chain member,
+ to "-g" so that failed searches that end between "-gen-decls" and
+ the lexicographically subsequent switch know to go back and see if
+ "-g" causes a match (which it does in this example).
+
+ This search is done in such a way that the longest match for the
+ front end in question wins. If there is no match for the current
+ front end, the longest match for a different front end is returned
+ (or N_OPTS if none) and the caller emits an error message. */
+size_t
+find_opt (const char *input, int lang_mask)
+{
+ size_t mn, mx, md, opt_len;
+ size_t match_wrong_lang;
+ int comp;
+
+ mn = 0;
+ mx = cl_options_count;
+
+ /* Find mn such this lexicographical inequality holds:
+ cl_options[mn] <= input < cl_options[mn + 1]. */
+ while (mx - mn > 1)
+ {
+ md = (mn + mx) / 2;
+ opt_len = cl_options[md].opt_len;
+ comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
+
+ if (comp < 0)
+ mx = md;
+ else
+ mn = md;
+ }
+
+ /* This is the switch that is the best match but for a different
+ front end, or cl_options_count if there is no match at all. */
+ match_wrong_lang = cl_options_count;
+
+ /* Backtrace the chain of possible matches, returning the longest
+ one, if any, that fits best. With current GCC switches, this
+ loop executes at most twice. */
+ do
+ {
+ const struct cl_option *opt = &cl_options[mn];
+
+ /* Is the input either an exact match or a prefix that takes a
+ joined argument? */
+ if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
+ && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
+ {
+ /* If language is OK, return it. */
+ if (opt->flags & lang_mask)
+ return mn;
+
+ /* If we haven't remembered a prior match, remember this
+ one. Any prior match is necessarily better. */
+ if (match_wrong_lang == cl_options_count)
+ match_wrong_lang = mn;
+ }
+
+ /* Try the next possibility. This is cl_options_count if there
+ are no more. */
+ mn = opt->back_chain;
+ }
+ while (mn != cl_options_count);
+
+ /* Return the best wrong match, or cl_options_count if none. */
+ return match_wrong_lang;
+}
+
+/* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the
+ next one is the same as ORIG_NEXT_OPT_IDX. */
+
+static bool
+cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx)
+{
+ /* An option can be canceled by the same option or an option with
+ Negative. */
+ if (cl_options [next_opt_idx].neg_index == opt_idx)
+ return true;
+
+ if (cl_options [next_opt_idx].neg_index != orig_next_opt_idx)
+ return cancel_option (opt_idx, cl_options [next_opt_idx].neg_index,
+ orig_next_opt_idx);
+
+ return false;
+}
+
+/* Filter out options canceled by the ones after them. */
+
+void
+prune_options (int *argcp, char ***argvp)
+{
+ int argc = *argcp;
+ int *options = xmalloc (argc * sizeof (*options));
+ char **argv = xmalloc (argc * sizeof (char *));
+ int i, arg_count, need_prune = 0;
+ const struct cl_option *option;
+ size_t opt_index;
+
+ /* Scan all arguments. */
+ for (i = 1; i < argc; i++)
+ {
+ int value = 1;
+ const char *opt = (*argvp) [i];
+
+ opt_index = find_opt (opt + 1, -1);
+ if (opt_index == cl_options_count
+ && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm')
+ && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
+ {
+ char *dup;
+
+ /* Drop the "no-" from negative switches. */
+ size_t len = strlen (opt) - 3;
+
+ dup = XNEWVEC (char, len + 1);
+ dup[0] = '-';
+ dup[1] = opt[1];
+ memcpy (dup + 2, opt + 5, len - 2 + 1);
+ opt = dup;
+ value = 0;
+ opt_index = find_opt (opt + 1, -1);
+ free (dup);
+ }
+
+ if (opt_index == cl_options_count)
+ {
+cont:
+ options [i] = 0;
+ continue;
+ }
+
+ option = &cl_options[opt_index];
+ if (option->neg_index < 0)
+ goto cont;
+
+ /* Skip joined switches. */
+ if ((option->flags & CL_JOINED))
+ goto cont;
+
+ /* Reject negative form of switches that don't take negatives as
+ unrecognized. */
+ if (!value && (option->flags & CL_REJECT_NEGATIVE))
+ goto cont;
+
+ options [i] = (int) opt_index;
+ need_prune |= options [i];
+ }
+
+ if (!need_prune)
+ goto done;
+
+ /* Remove arguments which are negated by others after them. */
+ argv [0] = (*argvp) [0];
+ arg_count = 1;
+ for (i = 1; i < argc; i++)
+ {
+ int j, opt_idx;
+
+ opt_idx = options [i];
+ if (opt_idx)
+ {
+ int next_opt_idx;
+ for (j = i + 1; j < argc; j++)
+ {
+ next_opt_idx = options [j];
+ if (next_opt_idx
+ && cancel_option (opt_idx, next_opt_idx,
+ next_opt_idx))
+ break;
+ }
+ }
+ else
+ goto keep;
+
+ if (j == argc)
+ {
+keep:
+ argv [arg_count] = (*argvp) [i];
+ arg_count++;
+ }
+ }
+
+ if (arg_count != argc)
+ {
+ *argcp = arg_count;
+ *argvp = argv;
+ }
+ else
+ {
+done:
+ free (argv);
+ }
+
+ free (options);
+}