summaryrefslogtreecommitdiff
path: root/gcc/opts-common.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2010-11-26 23:18:28 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2010-11-26 23:18:28 +0000
commite6d4b9841c35629de91c36ba40ed247fef749037 (patch)
tree36e9808ac190cda7d402aca282c7bbe11cbf8b71 /gcc/opts-common.c
parent8a1ffe230e5f07f6eef4bd30088f4245783109ec (diff)
downloadgcc-e6d4b9841c35629de91c36ba40ed247fef749037.tar.gz
options.texi (Enum, EnumValue): Document new record types.
* 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: * exgettext: Handle UnknownError. From-SVN: r167190
Diffstat (limited to 'gcc/opts-common.c')
-rw-r--r--gcc/opts-common.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 9a574024d37..e6cb552df13 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -181,6 +181,70 @@ option_ok_for_language (const struct cl_option *option,
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, unsigned int lang_mask,
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 *opts,
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, struct gcc_options *opts_set,
*(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 *opts, int option,
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;
}