This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Generic .opt support for enumerated option arguments


This patch adds generic .opt support for options whose arguments come
from some enumerated set of strings.  Such options may now be marked
with Enum, and optionally Var to cause the generic option-processing
machinery to set a gcc_options field directly for the option; this is
accompanied by Enum and EnumValue entries to define the sets of option
arguments.

The opts.c options - apart from -fstack-check=, which is pending
review of <http://gcc.gnu.org/ml/gcc-patches/2010-11/msg02483.html> -
are converted to the new mechanism where they take such enumerated
arguments.  This means six options no longer need any special code
there, and one option just needs to set a diagnostic context field in
its code without first decoding strings.

If an invalid option argument is passed to such an option, generic
code will produce an error (some existing options used warnings, but I
think always using errors is appropriate, just like for unknown
options) and an informative note listing the valid arguments.

The --help code can report current values of these options with -Q
--help, and can also report the sets of possible values for such
options.  The latter isn't currently enabled for any option because
the common options already have the list of possible values in the
help text for the individual options.  I have however tested it, and
it will be useful for options such as -march= (where it will allow
removing the TARGET_HELP hook once ARM has been converted to the new
system; notice incidentally that TARGET_HELP only gets called for
--target-help, not for --help=target which is supposed to mean the
same thing or any other --help variant).

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  OK to
commit?

2010-11-26  Joseph Myers  <joseph@codesourcery.com>

	* doc/options.texi (Enum, EnumValue): Document new record types.
	(Enum): Document new option flag.
	* opt-functions.awk
	* optc-gen.awk: Handle enumerated option arguments.
	* opth-gen.awk: Handle enumerated option arguments.
	* opts-common.c (enum_arg_ok_for_language, enum_arg_to_value,
	enum_value_to_arg): New.
	(decode_cmdline_option): Handle enumerated arguments.
	(read_cmdline_option): Handle CL_ERR_ENUM_ARG.
	(set_option, option_enabled, get_option_state): Handle CLVC_ENUM.
	* opts.c (print_filtered_help, print_specific_help): Take
	lang_mask arguments.
	(print_filtered_help): Handle printing values of enumerated
	options.  Print possible arguments for enumerated options.
	(print_specific_help): Update call to print_filtered_help.
	(common_handle_option): Update calls to print_specific_help.  Use
	value rather than arg for OPT_fdiagnostics_show_location_.  Don't
	handle OPT_ffp_contract_, OPT_fexcess_precision_,
	OPT_fvisibility_, OPT_ftls_model_, OPT_fira_algorithm_ or
	OPT_fira_region_ here.
	* opts.h (enum cl_var_type): Add CLVC_ENUM.
	(struct cl_option): Add var_enum.
	(CL_ENUM_CANONICAL, CL_ENUM_DRIVER_ONLY, struct cl_enum_arg,
	struct cl_enum, cl_enums, cl_enums_count): New.
	(CL_ERR_ENUM_ARG): Define.
	(CL_ERR_NEGATIVE): Update value.
	(enum_value_to_arg): Declare.
	* common.opt (flag_ira_algorithm, flag_ira_region,
	flag_fp_contract_mode, flag_excess_precision_cmdline,
	default_visibility, flag_tls_default): Remove Variable entries.
	(help_enum_printed): New Variable.
	(fdiagnostics-show-location=): Use Enum.  Add associated
	SourceInclude, Enum and EnumValue entries.
	(fexcess-precision=, ffp-contract=, fira-algorithm=, fira-region=,
	ftls-model=, fvisibility=): Use Enum, Var and Init.  Add
	associated Enum and EnumValue entries.

po:
2010-11-26  Joseph Myers  <joseph@codesourcery.com>

	* exgettext: Handle UnknownError.

Index: gcc/doc/options.texi
===================================================================
--- gcc/doc/options.texi	(revision 167145)
+++ gcc/doc/options.texi	(working copy)
@@ -78,6 +78,63 @@ two fields: the string @samp{SourceInclu
 include file.
 
 @item
+An enumeration record to define a set of strings that may be used as
+arguments to an option or options.  These records have three fields:
+the string @samp{Enum}, a space-separated list of properties and help
+text used to describe the set of strings in @option{--help} output.
+Properties use the same format as option properties; the following are
+valid:
+@table @code
+@item Name(@var{name})
+This property is required; @var{name} must be a name (suitable for use
+in C identifiers) used to identify the set of strings in @code{Enum}
+option properties.
+
+@item Type(@var{type})
+This property is required; @var{type} is the C type for variables set
+by options using this enumeration together with @code{Var}.
+
+@item UnknownError(@var{message})
+The message @var{message} will be used as an error message if the
+argument is invalid; for enumerations without @code{UnknownError}, a
+generic error message is used.  @var{message} should contain a single
+@samp{%qs} format, which will be used to format the invalid argument.
+@end table
+
+@item
+An enumeration value record to define one of the strings in a set
+given in an @samp{Enum} record.  These records have two fields: the
+string @samp{EnumValue} and a space-separated list of properties.
+Properties use the same format as option properties; the following are
+valid:
+@table @code
+@item Enum(@var{name})
+This property is required; @var{name} says which @samp{Enum} record
+this @samp{EnumValue} record corresponds to.
+
+@item String(@var{string})
+This property is required; @var{string} is the string option argument
+being described by this record.
+
+@item Value(@var{value})
+This property is required; it says what value (representable as
+@code{int}) should be used for the given string.
+
+@item Canonical
+This property is optional.  If present, it says the present string is
+the canonical one among all those with the given value.  Other strings
+yielding that value will be mapped to this one so specs do not need to
+handle them.
+
+@item DriverOnly
+This property is optional.  If present, the present string will only
+be accepted by the driver.  This is used for cases such as
+@option{-march=native} that are processed by the driver so that
+@samp{gcc -v} shows how the options chosen depended on the system on
+which the compiler was run.
+@end table
+
+@item
 An option definition record.  These records have the following fields:
 @enumerate
 @item
@@ -227,6 +284,13 @@ If the option takes an argument and has 
 @var{var} is an integer variable that stores the value of the argument.
 
 @item
+If the option takes an argument and has the @code{Enum} property,
+@var{var} is a variable (type given in the @code{Type} property of the
+@samp{Enum} record whose @code{Name} property has the same argument as
+the @code{Enum} property of this option) that stores the value of the
+argument.
+
+@item
 If the option has the @code{Defer} property, @var{var} is a pointer to
 a @code{VEC(cl_deferred_option,heap)} that stores the option for later
 processing.  (@var{var} is declared with type @code{void *} and needs
@@ -287,6 +351,12 @@ The main purpose of this property is to 
 The first option should use @samp{Mask(@var{name})} and the others
 should use @samp{Mask(@var{name}) MaskExists}.
 
+@item Enum(@var{name})
+The option's argument is a string from the set of strings associated
+with the corresponding @samp{Enum} record.  The string is checked and
+converted to the integer specified in the corresponding
+@samp{EnumValue} record before being passed to option handlers.
+
 @item Defer
 The option should be stored in a vector, specified with @code{Var},
 for later processing.
Index: gcc/opts-common.c
===================================================================
--- gcc/opts-common.c	(revision 167145)
+++ gcc/opts-common.c	(working copy)
@@ -181,6 +181,70 @@ option_ok_for_language (const struct cl_
   return true;
 }
 
+/* Return whether ENUM_ARG is OK for the language given by
+   LANG_MASK.  */
+
+static bool
+enum_arg_ok_for_language (const struct cl_enum_arg *enum_arg,
+			  unsigned int lang_mask)
+{
+  return (lang_mask & CL_DRIVER) || !(enum_arg->flags & CL_ENUM_DRIVER_ONLY);
+}
+
+/* Look up ARG in ENUM_ARGS for language LANG_MASK, returning true and
+   storing the value in *VALUE if found, and returning false without
+   modifying *VALUE if not found.  */
+
+static bool
+enum_arg_to_value (const struct cl_enum_arg *enum_args,
+		   const char *arg, int *value, unsigned int lang_mask)
+{
+  unsigned int i;
+
+  for (i = 0; enum_args[i].arg != NULL; i++)
+    if (strcmp (arg, enum_args[i].arg) == 0
+	&& enum_arg_ok_for_language (&enum_args[i], lang_mask))
+      {
+	*value = enum_args[i].value;
+	return true;
+      }
+
+  return false;
+}
+
+/* Look of VALUE in ENUM_ARGS for language LANG_MASK and store the
+   corresponding string in *ARGP, returning true if the found string
+   was marked as canonical, false otherwise.  If VALUE is not found
+   (which may be the case for uninitialized values if the relevant
+   option has not been passed), set *ARGP to NULL and return
+   false.  */
+
+bool
+enum_value_to_arg (const struct cl_enum_arg *enum_args,
+		   const char **argp, int value, unsigned int lang_mask)
+{
+  unsigned int i;
+
+  for (i = 0; enum_args[i].arg != NULL; i++)
+    if (enum_args[i].value == value
+	&& (enum_args[i].flags & CL_ENUM_CANONICAL)
+	&& enum_arg_ok_for_language (&enum_args[i], lang_mask))
+      {
+	*argp = enum_args[i].arg;
+	return true;
+      }
+
+  for (i = 0; enum_args[i].arg != NULL; i++)
+    if (enum_args[i].value == value
+	&& enum_arg_ok_for_language (&enum_args[i], lang_mask))
+      {
+	*argp = enum_args[i].arg;
+	return false;
+      }
+
+  *argp = NULL;
+  return false;
+}
 
 /* Fill in the canonical option part of *DECODED with an option
    described by OPT_INDEX, ARG and VALUE.  */
@@ -508,6 +572,24 @@ decode_cmdline_option (const char **argv
 	errors |= CL_ERR_UINT_ARG;
     }
 
+  /* If the switch takes an enumerated argument, convert it.  */
+  if (arg && (option->var_type == CLVC_ENUM))
+    {
+      const struct cl_enum *e = &cl_enums[option->var_enum];
+
+      gcc_assert (value == 1);
+      if (enum_arg_to_value (e->values, arg, &value, lang_mask))
+	{
+	  const char *carg = NULL;
+
+	  if (enum_value_to_arg (e->values, &carg, value, lang_mask))
+	    arg = carg;
+	  gcc_assert (carg != NULL);
+	}
+      else
+	errors |= CL_ERR_ENUM_ARG;
+    }
+
  done:
   decoded->opt_index = opt_index;
   decoded->arg = arg;
@@ -900,6 +982,36 @@ read_cmdline_option (struct gcc_options 
       return;
     }
 
+  if (decoded->errors & CL_ERR_ENUM_ARG)
+    {
+      const struct cl_enum *e = &cl_enums[option->var_enum];
+      unsigned int i;
+      size_t len;
+      char *s, *p;
+
+      if (e->unknown_error)
+	error_at (loc, e->unknown_error, decoded->arg);
+      else
+	error_at (loc, "unrecognized argument in option %qs", opt);
+
+      len = 0;
+      for (i = 0; e->values[i].arg != NULL; i++)
+	len += strlen (e->values[i].arg) + 1;
+
+      s = XALLOCAVEC (char, len);
+      p = s;
+      for (i = 0; e->values[i].arg != NULL; i++)
+	{
+	  size_t arglen = strlen (e->values[i].arg);
+	  memcpy (p, e->values[i].arg, arglen);
+	  p[arglen] = ' ';
+	  p += arglen + 1;
+	}
+      p[-1] = 0;
+      inform (loc, "valid arguments to %qs are: %s", option->opt_text, s);
+      return;
+    }
+
   gcc_assert (!decoded->errors);
 
   if (!handle_option (opts, opts_set, decoded, lang_mask, DK_UNSPECIFIED,
@@ -959,6 +1071,16 @@ set_option (struct gcc_options *opts, st
 	  *(const char **) set_flag_var = "";
 	break;
 
+    case CLVC_ENUM:
+      {
+	const struct cl_enum *e = &cl_enums[option->var_enum];
+
+	e->set (flag_var, value);
+	if (set_flag_var)
+	  e->set (set_flag_var, 1);
+      }
+      break;
+
     case CLVC_DEFER:
 	{
 	  VEC(cl_deferred_option,heap) *vec
@@ -1020,6 +1142,7 @@ option_enabled (int opt_idx, void *opts)
 	return (*(int *) flag_var & option->var_value) != 0;
 
       case CLVC_STRING:
+      case CLVC_ENUM:
       case CLVC_DEFER:
 	break;
       }
@@ -1060,6 +1183,11 @@ get_option_state (struct gcc_options *op
       state->size = strlen ((const char *) state->data) + 1;
       break;
 
+    case CLVC_ENUM:
+      state->data = flag_var;
+      state->size = cl_enums[cl_options[option].var_enum].var_size;
+      break;
+
     case CLVC_DEFER:
       return false;
     }
Index: gcc/opts.c
===================================================================
--- gcc/opts.c	(revision 167145)
+++ gcc/opts.c	(working copy)
@@ -885,7 +885,8 @@ print_filtered_help (unsigned int includ
 		     unsigned int exclude_flags,
 		     unsigned int any_flags,
 		     unsigned int columns,
-		     struct gcc_options *opts)
+		     struct gcc_options *opts,
+		     unsigned int lang_mask)
 {
   unsigned int i;
   const char *help;
@@ -918,6 +919,9 @@ print_filtered_help (unsigned int includ
   if (!opts->x_help_printed)
     opts->x_help_printed = XCNEWVAR (char, cl_options_count);
 
+  if (!opts->x_help_enum_printed)
+    opts->x_help_enum_printed = XCNEWVAR (char, cl_enums_count);
+
   for (i = 0; i < cl_options_count; i++)
     {
       char new_help[128];
@@ -999,6 +1003,20 @@ print_filtered_help (unsigned int includ
 				  sizeof (new_help) - strlen (new_help),
 				  * (const char **) flag_var);
 		    }
+		  else if (option->var_type == CLVC_ENUM)
+		    {
+		      const struct cl_enum *e = &cl_enums[option->var_enum];
+		      int value;
+		      const char *arg = NULL;
+
+		      value = e->get (flag_var);
+		      enum_value_to_arg (e->values, &arg, value, lang_mask);
+		      if (arg == NULL)
+			arg = _("[default]");
+		      snprintf (new_help + strlen (new_help),
+				sizeof (new_help) - strlen (new_help),
+				arg);
+		    }
 		  else
 		    sprintf (new_help + strlen (new_help),
 			     "%#x", * (int *) flag_var);
@@ -1013,6 +1031,10 @@ print_filtered_help (unsigned int includ
 
       wrap_help (help, opt, len, columns);
       displayed = true;
+
+      if (option->var_type == CLVC_ENUM
+	  && opts->x_help_enum_printed[option->var_enum] != 2)
+	opts->x_help_enum_printed[option->var_enum] = 1;
     }
 
   if (! found)
@@ -1038,18 +1060,57 @@ print_filtered_help (unsigned int includ
     printf (_(" All options with the desired characteristics have already been displayed\n"));
 
   putchar ('\n');
+
+  /* Print details of enumerated option arguments, if those
+     enumerations have help text headings provided.  If no help text
+     is provided, presume that the possible values are listed in the
+     help text for the relevant options.  */
+  for (i = 0; i < cl_enums_count; i++)
+    {
+      unsigned int j, pos;
+
+      if (opts->x_help_enum_printed[i] != 1)
+	continue;
+      if (cl_enums[i].help == NULL)
+	continue;
+      printf ("  %s\n    ", _(cl_enums[i].help));
+      pos = 4;
+      for (j = 0; cl_enums[i].values[j].arg != NULL; j++)
+	{
+	  unsigned int len = strlen (cl_enums[i].values[j].arg);
+
+	  if (pos > 4 && pos + 1 + len <= columns)
+	    {
+	      printf (" %s", cl_enums[i].values[j].arg);
+	      pos += 1 + len;
+	    }
+	  else
+	    {
+	      if (pos > 4)
+		{
+		  printf ("\n    ");
+		  pos = 4;
+		}
+	      printf ("%s", cl_enums[i].values[j].arg);
+	      pos += len;
+	    }
+	}
+      printf ("\n\n");
+      opts->x_help_enum_printed[i] = 2;
+    }
 }
 
 /* Display help for a specified type of option.
    The options must have ALL of the INCLUDE_FLAGS set
    ANY of the flags in the ANY_FLAGS set
    and NONE of the EXCLUDE_FLAGS set.  The current option state is in
-   OPTS.  */
+   OPTS; LANG_MASK is used for interpreting enumerated option state.  */
 static void
 print_specific_help (unsigned int include_flags,
 		     unsigned int exclude_flags,
 		     unsigned int any_flags,
-		     struct gcc_options *opts)
+		     struct gcc_options *opts,
+		     unsigned int lang_mask)
 {
   unsigned int all_langs_mask = (1U << cl_lang_count) - 1;
   const char * description = NULL;
@@ -1145,7 +1206,7 @@ print_specific_help (unsigned int includ
 
   printf ("%s%s:\n", description, descrip_extra);
   print_filtered_help (include_flags, exclude_flags, any_flags,
-		       opts->x_help_columns, opts);
+		       opts->x_help_columns, opts, lang_mask);
 }
 
 /* Handle target- and language-independent options.  Return zero to
@@ -1187,19 +1248,20 @@ common_handle_option (struct gcc_options
 	/* First display any single language specific options.  */
 	for (i = 0; i < cl_lang_count; i++)
 	  print_specific_help
-	    (1U << i, (all_langs_mask & (~ (1U << i))) | undoc_mask, 0, opts);
+	    (1U << i, (all_langs_mask & (~ (1U << i))) | undoc_mask, 0, opts,
+	     lang_mask);
 	/* Next display any multi language specific options.  */
-	print_specific_help (0, undoc_mask, all_langs_mask, opts);
+	print_specific_help (0, undoc_mask, all_langs_mask, opts, lang_mask);
 	/* Then display any remaining, non-language options.  */
 	for (i = CL_MIN_OPTION_CLASS; i <= CL_MAX_OPTION_CLASS; i <<= 1)
 	  if (i != CL_DRIVER)
-	    print_specific_help (i, undoc_mask, 0, opts);
+	    print_specific_help (i, undoc_mask, 0, opts, lang_mask);
 	opts->x_exit_after_options = true;
 	break;
       }
 
     case OPT__target_help:
-      print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0, opts);
+      print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0, opts, lang_mask);
       opts->x_exit_after_options = true;
 
       /* Allow the target a chance to give the user some additional information.  */
@@ -1321,7 +1383,8 @@ common_handle_option (struct gcc_options
 	  }
 
 	if (include_flags)
-	  print_specific_help (include_flags, exclude_flags, 0, opts);
+	  print_specific_help (include_flags, exclude_flags, 0, opts,
+			       lang_mask);
 	opts->x_exit_after_options = true;
 	break;
       }
@@ -1405,13 +1468,7 @@ common_handle_option (struct gcc_options
       break;
 
     case OPT_fdiagnostics_show_location_:
-      if (!strcmp (arg, "once"))
-	diagnostic_prefixing_rule (dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
-      else if (!strcmp (arg, "every-line"))
-	diagnostic_prefixing_rule (dc)
-	  = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
-      else
-	return false;
+      diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value;
       break;
 
     case OPT_fdiagnostics_show_option:
@@ -1422,27 +1479,6 @@ common_handle_option (struct gcc_options
       /* Deferred.  */
       break;
 
-    case OPT_ffp_contract_:
-      if (!strcmp (arg, "on"))
-	/* Not implemented, fall back to conservative FP_CONTRACT_OFF.  */
-	opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF;
-      else if (!strcmp (arg, "off"))
-	opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF;
-      else if (!strcmp (arg, "fast"))
-	opts->x_flag_fp_contract_mode = FP_CONTRACT_FAST;
-      else
-	error_at (loc, "unknown floating point contraction style \"%s\"", arg);
-      break;
-
-    case OPT_fexcess_precision_:
-      if (!strcmp (arg, "fast"))
-	opts->x_flag_excess_precision_cmdline = EXCESS_PRECISION_FAST;
-      else if (!strcmp (arg, "standard"))
-	opts->x_flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD;
-      else
-	error_at (loc, "unknown excess precision style \"%s\"", arg);
-      break;
-
     case OPT_ffast_math:
       set_fast_math_flags (opts, value);
       break;
@@ -1542,21 +1578,6 @@ common_handle_option (struct gcc_options
       dc->show_column = value;
       break;
 
-    case OPT_fvisibility_:
-      {
-        if (!strcmp(arg, "default"))
-          opts->x_default_visibility = VISIBILITY_DEFAULT;
-        else if (!strcmp(arg, "internal"))
-          opts->x_default_visibility = VISIBILITY_INTERNAL;
-        else if (!strcmp(arg, "hidden"))
-          opts->x_default_visibility = VISIBILITY_HIDDEN;
-        else if (!strcmp(arg, "protected"))
-          opts->x_default_visibility = VISIBILITY_PROTECTED;
-        else
-          error_at (loc, "unrecognized visibility value \"%s\"", arg);
-      }
-      break;
-
     case OPT_frandom_seed:
       /* The real switch is -fno-random-seed.  */
       if (value)
@@ -1621,39 +1642,6 @@ common_handle_option (struct gcc_options
       vect_set_verbosity_level (opts, value);
       break;
 
-    case OPT_ftls_model_:
-      if (!strcmp (arg, "global-dynamic"))
-	opts->x_flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
-      else if (!strcmp (arg, "local-dynamic"))
-	opts->x_flag_tls_default = TLS_MODEL_LOCAL_DYNAMIC;
-      else if (!strcmp (arg, "initial-exec"))
-	opts->x_flag_tls_default = TLS_MODEL_INITIAL_EXEC;
-      else if (!strcmp (arg, "local-exec"))
-	opts->x_flag_tls_default = TLS_MODEL_LOCAL_EXEC;
-      else
-	warning_at (loc, 0, "unknown tls-model \"%s\"", arg);
-      break;
-
-    case OPT_fira_algorithm_:
-      if (!strcmp (arg, "CB"))
-	opts->x_flag_ira_algorithm = IRA_ALGORITHM_CB;
-      else if (!strcmp (arg, "priority"))
-	opts->x_flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
-      else
-	warning_at (loc, 0, "unknown ira algorithm \"%s\"", arg);
-      break;
-
-    case OPT_fira_region_:
-      if (!strcmp (arg, "one"))
-	opts->x_flag_ira_region = IRA_REGION_ONE;
-      else if (!strcmp (arg, "all"))
-	opts->x_flag_ira_region = IRA_REGION_ALL;
-      else if (!strcmp (arg, "mixed"))
-	opts->x_flag_ira_region = IRA_REGION_MIXED;
-      else
-	warning_at (loc, 0, "unknown ira region \"%s\"", arg);
-      break;
-
     case OPT_g:
       set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
 		       loc);
Index: gcc/opts.h
===================================================================
--- gcc/opts.h	(revision 167145)
+++ gcc/opts.h	(working copy)
@@ -42,6 +42,10 @@ enum cl_var_type {
      argument.  */
   CLVC_STRING,
 
+  /* The switch takes an enumerated argument (VAR_ENUM says what
+     enumeration) and FLAG_VAR points to that argument.  */
+  CLVC_ENUM,
+
   /* The switch should be stored in the VEC pointed to by FLAG_VAR for
      later processing.  */
   CLVC_DEFER
@@ -61,6 +65,7 @@ struct cl_option
   int neg_index;
   unsigned int flags;
   unsigned short flag_var_offset;
+  unsigned short var_enum;
   enum cl_var_type var_type;
   int var_value;
 };
@@ -111,6 +116,52 @@ extern const unsigned int cl_lang_count;
 #define CL_UINTEGER		(1 << 29) /* Argument is an integer >=0.  */
 #define CL_UNDOCUMENTED		(1 << 30) /* Do not output with --help.  */
 
+/* Flags for an enumerated option argument.  */
+#define CL_ENUM_CANONICAL	(1 << 0) /* Canonical for this value.  */
+#define CL_ENUM_DRIVER_ONLY	(1 << 1) /* Only accepted in the driver.  */
+
+/* Structure describing an enumerated option argument.  */
+
+struct cl_enum_arg
+{
+  /* The argument text, or NULL at the end of the array.  */
+  const char *arg;
+
+  /* The corresponding integer value.  */
+  int value;
+
+  /* Flags associated with this argument.  */
+  unsigned int flags;
+};
+
+/* Structure describing an enumerated set of option arguments.  */
+
+struct cl_enum
+{
+  /* Help text, or NULL if the values should not be listed in --help
+     output.  */
+  const char *help;
+
+  /* Error message for unknown arguments, or NULL to use a generic
+     error.  */
+  const char *unknown_error;
+
+  /* Array of possible values.  */
+  const struct cl_enum_arg *values;
+
+  /* The size of the type used to store a value.  */
+  size_t var_size;
+
+  /* Function to set a variable of this type.  */
+  void (*set) (void *var, int value);
+
+  /* Function to get the value of a variable of this type.  */
+  int (*get) (const void *var);
+};
+
+extern const struct cl_enum cl_enums[];
+extern const unsigned int cl_enums_count;
+
 /* Possible ways in which a command-line option may be erroneous.
    These do not include not being known at all; an option index of
    OPT_SPECIAL_unknown is used for that.  */
@@ -119,7 +170,8 @@ extern const unsigned int cl_lang_count;
 #define CL_ERR_MISSING_ARG	(1 << 1) /* Argument required but missing.  */
 #define CL_ERR_WRONG_LANG	(1 << 2) /* Option for wrong language.  */
 #define CL_ERR_UINT_ARG		(1 << 3) /* Bad unsigned integer argument.  */
-#define CL_ERR_NEGATIVE		(1 << 4) /* Negative form of option
+#define CL_ERR_ENUM_ARG		(1 << 4) /* Bad enumerated argument.  */
+#define CL_ERR_NEGATIVE		(1 << 5) /* Negative form of option
 					    not permitted (together
 					    with OPT_SPECIAL_unknown).  */
 
@@ -230,6 +282,9 @@ extern unsigned num_in_fnames;
 
 size_t find_opt (const char *input, int lang_mask);
 extern int integral_argument (const char *arg);
+extern bool enum_value_to_arg (const struct cl_enum_arg *enum_args,
+			       const char **argp, int value,
+			       unsigned int lang_mask);
 extern void decode_cmdline_options_to_array (unsigned int argc,
 					     const char **argv, 
 					     unsigned int lang_mask,
Index: gcc/optc-gen.awk
===================================================================
--- gcc/optc-gen.awk	(revision 167145)
+++ gcc/optc-gen.awk	(working copy)
@@ -34,6 +34,7 @@ BEGIN {
 	n_extra_target_vars = 0
 	n_extra_c_includes = 0
 	n_extra_h_includes = 0
+	n_enums = 0
 	quote = "\042"
 	comma = ","
 	FS=SUBSEP
@@ -80,6 +81,31 @@ BEGIN {
 		else if ($1 == "SourceInclude")  {
 			extra_c_includes[n_extra_c_includes++] = $2;
 		}
+		else if ($1 == "Enum") {
+			props = $2
+			name = opt_args("Name", props)
+			type = opt_args("Type", props)
+			unknown_error = opt_args("UnknownError", props)
+			enum_names[n_enums] = name
+			enum_type[name] = type
+			enum_index[name] = n_enums
+			enum_unknown_error[name] = unknown_error
+			enum_help[name] = $3
+			n_enums++
+		}
+		else if ($1 == "EnumValue")  {
+			props = $2
+			enum_name = opt_args("Enum", props)
+			string = opt_args("String", props)
+			value = opt_args("Value", props)
+			val_flags = "0"
+			val_flags = val_flags \
+			  test_flag("Canonical", props, "| CL_ENUM_CANONICAL") \
+			  test_flag("DriverOnly", props, "| CL_ENUM_DRIVER_ONLY")
+			enum_data[enum_name] = enum_data[enum_name] \
+			  "  { " quote string quote ", " value ", " val_flags \
+			  " },\n"
+		}
 		else {
 			name = opt_args("Mask", $1)
 			if (name == "") {
@@ -116,6 +142,56 @@ if (n_extra_c_includes > 0) {
 	print ""
 }
 
+for (i = 0; i < n_enums; i++) {
+	name = enum_names[i]
+	type = enum_type[name]
+	print "static const struct cl_enum_arg cl_enum_" name \
+	    "_data[] = "
+	print "{"
+	print enum_data[name] "  { NULL, 0, 0 }"
+	print "};"
+	print ""
+	print "static void"
+	print "cl_enum_" name "_set (void *var, int value)"
+	print "{"
+	print "  *((" type " *) var) = (" type ") value;"
+	print "}"
+	print ""
+	print "static int"
+	print "cl_enum_" name "_get (const void *var)"
+	print "{"
+	print "  return (int) *((const " type " *) var);"
+	print "}"
+	print ""
+}
+
+print "const struct cl_enum cl_enums[] ="
+print "{"
+for (i = 0; i < n_enums; i++) {
+	name = enum_names[i]
+	ehelp = enum_help[name]
+	if (ehelp == "")
+		ehelp = "NULL"
+	else
+		ehelp = quote ehelp quote
+	unknown_error = enum_unknown_error[name]
+	if (unknown_error == "")
+		unknown_error = "NULL"
+	else
+		unknown_error = quote unknown_error quote
+	print "  {"
+	print "    " ehelp ","
+	print "    " unknown_error ","
+	print "    cl_enum_" name "_data,"
+	print "    sizeof (" enum_type[name] "),"
+	print "    cl_enum_" name "_set,"
+	print "    cl_enum_" name "_get"
+	print "  },"
+}
+print "};"
+print "const unsigned int cl_enums_count = " n_enums ";"
+print ""
+
 have_save = 0;
 if (n_extra_target_vars)
 	have_save = 1
Index: gcc/opth-gen.awk
===================================================================
--- gcc/opth-gen.awk	(revision 167145)
+++ gcc/opth-gen.awk	(working copy)
@@ -77,6 +77,31 @@ BEGIN {
 		else if ($1 == "SourceInclude")  {
 			extra_c_includes[n_extra_c_includes++] = $2;
 		}
+		else if ($1 == "Enum")  {
+			props = $2
+			name = opt_args("Name", props)
+			type = opt_args("Type", props)
+			unknown_error = opt_args("UnknownError", props)
+			enum_names[n_enums] = name
+			enum_type[name] = type
+			enum_index[name] = n_enums
+			enum_unknown_error[name] = unknown_error
+			enum_help[name] = $3
+			n_enums++
+		}
+		else if ($1 == "EnumValue")  {
+			props = $2
+			enum_name = opt_args("Enum", props)
+			string = opt_args("String", props)
+			value = opt_args("Value", props)
+			val_flags = "0"
+			val_flags = val_flags \
+			  test_flag("Canonical", props, "| CL_ENUM_CANONICAL") \
+			  test_flag("DriverOnly", props, "| CL_ENUM_DRIVER_ONLY")
+			enum_data[enum_name] = enum_data[enum_name] \
+			  "  { " quote string quote ", " value ", " val_flags \
+			  " },\n"
+		}
 		else {
 			name = opt_args("Mask", $1)
 			if (name == "") {
Index: gcc/po/exgettext
===================================================================
--- gcc/po/exgettext	(revision 167145)
+++ gcc/po/exgettext	(working copy)
@@ -246,6 +246,17 @@ echo "scanning option files..." >&2
 		printf("#line %d \"%s\"\n", lineno, file)
 		printf("_(\"%s\")\n", line)
 	    }
+	    if ((field == 1) && /UnknownError/) {
+		line = $0
+		sub(".*UnknownError\\(", "", line)
+		if (line ~ "^{") {
+			sub("^{", "", line)
+			sub("}\\).*", "", line)
+		} else
+			sub("\\).*", "", line)
+		printf("#line %d \"%s\"\n", lineno, file)
+		printf("_(\"%s\")\n", line)
+	    }
 	    if ((field == 1) && /Warn\(/) {
 		line = $0
 		sub(".*Warn\\(", "", line)
Index: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 167145)
+++ gcc/common.opt	(working copy)
@@ -42,15 +42,6 @@ int flag_complex_method = 1
 Variable
 int flag_evaluation_order = 0
 
-; Set the default region and algorithm for the integrated register
-; allocator.
-
-Variable
-enum ira_algorithm flag_ira_algorithm = IRA_ALGORITHM_CB
-
-Variable
-enum ira_region flag_ira_region = IRA_REGION_MIXED
-
 ; Language specific warning pass for unused results.
 Variable
 bool flag_warn_unused_result = false
@@ -58,15 +49,6 @@ bool flag_warn_unused_result = false
 Variable
 int *param_values
 
-; Floating-point contraction mode, fast by default.
-Variable
-enum fp_contract_mode flag_fp_contract_mode = FP_CONTRACT_FAST
-
-; The excess precision specified on the command line, or defaulted by
-; the front end.
-Variable
-enum excess_precision flag_excess_precision_cmdline = EXCESS_PRECISION_DEFAULT
-
 ; Nonzero if we should write GIMPLE bytecode for link-time optimization.
 Variable
 int flag_generate_lto
@@ -97,14 +79,6 @@ int flag_gen_aux_info = 0
 Variable
 int flag_shlib
 
-; The default visibility for all symbols (unless overridden).
-Variable
-enum symbol_visibility default_visibility = VISIBILITY_DEFAULT
-
-; Set to the default thread-local storage (tls) model to use.
-Variable
-enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC
-
 ; These two are really VEC(char_p,heap) *.
 
 Variable
@@ -187,6 +161,12 @@ enum graph_dump_types graph_dump_format 
 Variable
 char *help_printed
 
+; Which enums have been printed by --help.  0 = not printed, no
+; relevant options seen, 1 = relevant option seen, not yet printed, 2
+; = printed.
+Variable
+char *help_enum_printed
+
 ; The number of columns for --help output.
 Variable
 unsigned int help_columns
@@ -897,9 +877,22 @@ Common Report Var(flag_delete_null_point
 Delete useless null pointer checks
 
 fdiagnostics-show-location=
-Common Joined RejectNegative
+Common Joined RejectNegative Enum(diagnostic_prefixing_rule)
 -fdiagnostics-show-location=[once|every-line]	How often to emit source location at the beginning of line-wrapped diagnostics
 
+; Required for these enum values.
+SourceInclude
+pretty-print.h
+
+Enum
+Name(diagnostic_prefixing_rule) Type(int)
+
+EnumValue
+Enum(diagnostic_prefixing_rule) String(once) Value(DIAGNOSTICS_SHOW_PREFIX_ONCE)
+
+EnumValue
+Enum(diagnostic_prefixing_rule) String(every-line) Value(DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE)
+
 fdiagnostics-show-option
 Common Var(flag_diagnostics_show_option) Init(1)
 Amend appropriate diagnostic messages with the command line option that controls them
@@ -972,9 +965,18 @@ Common Report Var(flag_expensive_optimiz
 Perform a number of minor, expensive optimizations
 
 fexcess-precision=
-Common Joined RejectNegative
+Common Joined RejectNegative Enum(excess_precision) Var(flag_excess_precision_cmdline) Init(EXCESS_PRECISION_DEFAULT)
 -fexcess-precision=[fast|standard]	Specify handling of excess floating-point precision
 
+Enum
+Name(excess_precision) Type(enum excess_precision) UnknownError(unknown excess precision style %qs)
+
+EnumValue
+Enum(excess_precision) String(fast) Value(EXCESS_PRECISION_FAST)
+
+EnumValue
+Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
+
 ffast-math
 Common
 
@@ -999,9 +1001,22 @@ Common Report Var(flag_forward_propagate
 Perform a forward propagation pass on RTL
 
 ffp-contract=
-Common Joined RejectNegative
+Common Joined RejectNegative Enum(fp_contract_mode) Var(flag_fp_contract_mode) Init(FP_CONTRACT_FAST)
 -ffp-contract=[off|on|fast] Perform floating-point expression contraction.
 
+Enum
+Name(fp_contract_mode) Type(enum fp_contract_mode) UnknownError(unknown floating point contraction style %qs)
+
+EnumValue
+Enum(fp_contract_mode) String(off) Value(FP_CONTRACT_OFF)
+
+; Not implemented, fall back to conservative FP_CONTRACT_OFF.
+EnumValue
+Enum(fp_contract_mode) String(on) Value(FP_CONTRACT_OFF)
+
+EnumValue
+Enum(fp_contract_mode) String(fast) Value(FP_CONTRACT_FAST)
+
 ; Nonzero means don't put addresses of constant functions in registers.
 ; Used for compiling the Unix kernel, where strange substitutions are
 ; done on the assembly output.
@@ -1183,13 +1198,34 @@ Perform structure layout optimizations b
 on profiling information.
 
 fira-algorithm=
-Common Joined RejectNegative
+Common Joined RejectNegative Enum(ira_algorithm) Var(flag_ira_algorithm) Init(IRA_ALGORITHM_CB)
 -fira-algorithm=[CB|priority] Set the used IRA algorithm
 
+Enum
+Name(ira_algorithm) Type(enum ira_algorithm) UnknownError(unknown IRA algorithm %qs)
+
+EnumValue
+Enum(ira_algorithm) String(CB) Value(IRA_ALGORITHM_CB)
+
+EnumValue
+Enum(ira_algorithm) String(priority) Value(IRA_ALGORITHM_PRIORITY)
+
 fira-region=
-Common Joined RejectNegative
+Common Joined RejectNegative Enum(ira_region) Var(flag_ira_region) Init(IRA_REGION_MIXED)
 -fira-region=[one|all|mixed] Set regions for IRA
 
+Enum
+Name(ira_region) Type(enum ira_region) UnknownError(unknown IRA region %qs)
+
+EnumValue
+Enum(ira_region) String(one) Value(IRA_REGION_ONE)
+
+EnumValue
+Enum(ira_region) String(all) Value(IRA_REGION_ALL)
+
+EnumValue
+Enum(ira_region) String(mixed) Value(IRA_REGION_MIXED)
+
 fira-loop-pressure
 Common Report Var(flag_ira_loop_pressure)
 Use IRA based register pressure calculation
@@ -1718,9 +1754,24 @@ Common Report Var(time_report)
 Report the time taken by each compiler pass
 
 ftls-model=
-Common Joined RejectNegative
+Common Joined RejectNegative Enum(tls_model) Var(flag_tls_default) Init(TLS_MODEL_GLOBAL_DYNAMIC)
 -ftls-model=[global-dynamic|local-dynamic|initial-exec|local-exec]	Set the default thread-local storage code generation model
 
+Enum
+Name(tls_model) Type(enum tls_model) UnknownError(unknown TLS model %qs)
+
+EnumValue
+Enum(tls_model) String(global-dynamic) Value(TLS_MODEL_GLOBAL_DYNAMIC)
+
+EnumValue
+Enum(tls_model) String(local-dynamic) Value(TLS_MODEL_LOCAL_DYNAMIC)
+
+EnumValue
+Enum(tls_model) String(initial-exec) Value(TLS_MODEL_INITIAL_EXEC)
+
+EnumValue
+Enum(tls_model) String(local-exec) Value(TLS_MODEL_LOCAL_EXEC)
+
 ftoplevel-reorder
 Common Report Var(flag_toplevel_reorder) Init(2) Optimization
 Reorder top level functions, variables, and asms
@@ -1973,9 +2024,23 @@ Common Report Var(flag_verbose_asm)
 Add extra commentary to assembler output
 
 fvisibility=
-Common Joined RejectNegative
+Common Joined RejectNegative Enum(symbol_visibility) Var(default_visibility) Init(VISIBILITY_DEFAULT)
 -fvisibility=[default|internal|hidden|protected]	Set the default symbol visibility
 
+Enum
+Name(symbol_visibility) Type(enum symbol_visibility) UnknownError(unrecognized visibility value %qs)
+
+EnumValue
+Enum(symbol_visibility) String(default) Value(VISIBILITY_DEFAULT)
+
+EnumValue
+Enum(symbol_visibility) String(internal) Value(VISIBILITY_INTERNAL)
+
+EnumValue
+Enum(symbol_visibility) String(hidden) Value(VISIBILITY_HIDDEN)
+
+EnumValue
+Enum(symbol_visibility) String(protected) Value(VISIBILITY_PROTECTED)
 
 fvpt
 Common Report Var(flag_value_profile_transformations) Optimization
Index: gcc/opt-functions.awk
===================================================================
--- gcc/opt-functions.awk	(revision 167145)
+++ gcc/opt-functions.awk	(working copy)
@@ -150,6 +150,10 @@ function var_type(flags)
 {
 	if (flag_set_p("Defer", flags))
 		return "void *"
+	else if (flag_set_p("Enum.*", flags)) {
+		en = opt_args("Enum", flags);
+		return enum_type[en] " "
+	}
 	else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags))
 		return "int "
 	else if (flag_set_p("UInteger", flags))
@@ -176,33 +180,37 @@ function var_type_struct(flags)
 }
 
 # Given that an option has flags FLAGS, return an initializer for the
-# "var_cond" and "var_value" fields of its cl_options[] entry.
+# "var_enum", "var_type" and "var_value" fields of its cl_options[] entry.
 function var_set(flags)
 {
 	if (flag_set_p("Defer", flags))
-		return "CLVC_DEFER, 0"
+		return "0, CLVC_DEFER, 0"
 	s = nth_arg(1, opt_args("Var", flags))
 	if (s != "")
-		return "CLVC_EQUAL, " s
+		return "0, CLVC_EQUAL, " s
 	s = opt_args("Mask", flags);
 	if (s != "") {
 		vn = var_name(flags);
 		if (vn)
-			return "CLVC_BIT_SET, OPTION_MASK_" s
+			return "0, CLVC_BIT_SET, OPTION_MASK_" s
 		else
-			return "CLVC_BIT_SET, MASK_" s
+			return "0, CLVC_BIT_SET, MASK_" s
 	}
 	s = nth_arg(0, opt_args("InverseMask", flags));
 	if (s != "") {
 		vn = var_name(flags);
 		if (vn)
-			return "CLVC_BIT_CLEAR, OPTION_MASK_" s
+			return "0, CLVC_BIT_CLEAR, OPTION_MASK_" s
 		else
-			return "CLVC_BIT_CLEAR, MASK_" s
+			return "0, CLVC_BIT_CLEAR, MASK_" s
+	}
+	if (flag_set_p("Enum.*", flags)) {
+		en = opt_args("Enum", flags);
+		return enum_index[en] ", CLVC_ENUM, 0"
 	}
 	if (var_type(flags) == "const char *")
-		return "CLVC_STRING, 0"
-	return "CLVC_BOOLEAN, 0"
+		return "0, CLVC_STRING, 0"
+	return "0, CLVC_BOOLEAN, 0"
 }
 
 # Given that an option called NAME has flags FLAGS, return an initializer

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]