d3bfe4decc
* config/i386/driver-i386.c (detect_caches_amd, detect_caches_intel, host_detect_local_cpu): Fix -Wc++-compat and/or -Wcast-qual warnings. *ggc-common.c (ggc_mark_roots, gt_pch_note_object, gt_pch_note_reorder, relocate_ptrs, write_pch_globals, gt_pch_save): Likewise. * ggc-page.c (push_depth, push_by_depth, alloc_anon, alloc_page, gt_ggc_m_S, clear_marks, ggc_pch_read): Likewise. * global.c (compute_regsets): Likewise. * graph.c (print_rtl_graph_with_bb, clean_graph_dump_file, finish_graph_dump_file): Likewise. * haifa-sched.c (schedule_block, extend_h_i_d, extend_ready, unlink_bb_notes): Likewise. * integrate.c (get_hard_reg_initial_val): Likewise. * ipa-prop.c (ipa_push_func_to_list): Likewise. * ipa-struct-reorg.c (gen_var_name, gen_cluster_name): Likewise. * local-alloc.c (update_equiv_regs): Likewise. * loop-invariant.c (check_invariant_table_size, hash_invariant_expr, eq_invariant_expr, find_or_insert_inv): Likewise. * loop-iv.c (check_iv_ref_table_size, analyzed_for_bivness_p, altered_reg_used, mark_altered): Likewise. * loop-unroll.c (si_info_eq, ve_info_eq, allocate_basic_variable, insert_var_expansion_initialization, combine_var_copies_in_loop_exit, apply_opt_in_copies, release_var_copies): Likewise. * matrix-reorg.c (mat_acc_phi_hash, mat_acc_phi_eq, mtt_info_eq, analyze_matrix_decl, add_allocation_site, analyze_transpose, analyze_accesses_for_phi_node, check_var_notmodified_p, check_allocation_function, find_sites_in_func, record_all_accesses_in_func, transform_access_sites, transform_allocation_sites): Likewise. * omp-low.c (new_omp_region, create_omp_child_function_name, check_omp_nesting_restrictions, check_combined_parallel, lower_omp_2, diagnose_sb_1, diagnose_sb_2): Likewise. * optabs.c (no_conflict_move_test, gen_libfunc, gen_fp_libfunc, gen_intv_fp_libfunc, gen_interclass_conv_libfunc, gen_intraclass_conv_libfunc, set_optab_libfunc, set_conv_libfunc): Likewise. * opts-common.c (prune_options): Likewise. * opts.c (add_input_filename, print_filtered_help, get_option_state): Likewise. * params.c (add_params): Likewise. * passes.c (set_pass_for_id, next_pass_1, do_per_function_toporder, pass_fini_dump_file): Likewise. * postreload.c (reload_cse_simplify_operands): Likewise. * predict.c (tree_predicted_by_p, tree_predict_edge, clear_bb_predictions, combine_predictions_for_bb): Likewise. From-SVN: r137134
237 lines
6.4 KiB
C
237 lines
6.4 KiB
C
/* Command line option handling.
|
|
Copyright (C) 2006, 2007 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 3, 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 COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#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, 'optc-gen.awk' 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 = XNEWVEC (int, argc);
|
|
char **argv = XNEWVEC (char *, argc);
|
|
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);
|
|
}
|