OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [opts-common.c] - Diff between revs 154 and 816

Only display areas with differences | Details | Blame | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.