+2019-07-03 Pedro Alves <palves@redhat.com>
+
+ * cli/cli-option.c (parse_option) <var_enum>: Don't return an
+ option_value with a null enumeration.
+ (complete_options): Save the option values in the context.
+ (save_option_value_in_ctx): New, factored out from ...
+ (process_options): ... here.
+ * cli/cli-utils.c (get_ulongest): Don't advance PP until the end
+ of the function.
+ * maint-test-options.c (test_options_opts::dump): New, factored
+ out from ...
+ (maintenance_test_options_command_mode): ... here.
+ (maintenance_test_options_command_completion_result): Delete.
+ (maintenance_test_options_command_completion_text): Update
+ comment.
+ (maintenance_show_test_options_completion_result): Change
+ prototype. Just print
+ maintenance_test_options_command_completion_text.
+ (save_completion_result): New.
+ (maintenance_test_options_completer_mode): Pass options context to
+ complete_options, and then save a dump.
+ (_initialize_maint_test_options): Use add_cmd to install "maint
+ show test-options-completion-result".
+
2019-07-03 Pedro Alves <palves@redhat.com>
* NEWS (New commands): Mention "with" and "maint with".
gdb::optional<option_value> value;
};
+static void save_option_value_in_ctx (gdb::optional<option_def_and_value> &ov);
+
/* Info passed around when handling completion. */
struct parse_option_completion_info
{
{
complete_on_enum (completion->tracker,
match->enums, *args, *args);
- *args = after_arg;
+ if (completion->tracker.have_completions ())
+ return {};
- option_value val;
- val.enumeration = nullptr;
- return option_def_and_value {*match, match_ctx, val};
+ /* If we don't have completions, let the
+ non-completion path throw on invalid enum value
+ below, so that completion processing stops. */
}
}
(*args - text);
return true;
}
+
+ /* If the caller passed in a context, then it is
+ interested in the option argument values. */
+ if (ov && ov->ctx != nullptr)
+ save_option_value_in_ctx (ov);
}
else
{
return false;
}
+/* Save the parsed value in the option's context. */
+
+static void
+save_option_value_in_ctx (gdb::optional<option_def_and_value> &ov)
+{
+ switch (ov->option.type)
+ {
+ case var_boolean:
+ {
+ bool value = ov->value.has_value () ? ov->value->boolean : true;
+ *ov->option.var_address.boolean (ov->option, ov->ctx) = value;
+ }
+ break;
+ case var_uinteger:
+ *ov->option.var_address.uinteger (ov->option, ov->ctx)
+ = ov->value->uinteger;
+ break;
+ case var_zuinteger_unlimited:
+ *ov->option.var_address.integer (ov->option, ov->ctx)
+ = ov->value->integer;
+ break;
+ case var_enum:
+ *ov->option.var_address.enumeration (ov->option, ov->ctx)
+ = ov->value->enumeration;
+ break;
+ default:
+ gdb_assert_not_reached ("unhandled option type");
+ }
+}
+
/* See cli-option.h. */
bool
processed_any = true;
- switch (ov->option.type)
- {
- case var_boolean:
- {
- bool value = ov->value.has_value () ? ov->value->boolean : true;
- *ov->option.var_address.boolean (ov->option, ov->ctx) = value;
- }
- break;
- case var_uinteger:
- *ov->option.var_address.uinteger (ov->option, ov->ctx)
- = ov->value->uinteger;
- break;
- case var_zuinteger_unlimited:
- *ov->option.var_address.integer (ov->option, ov->ctx)
- = ov->value->integer;
- break;
- case var_enum:
- *ov->option.var_address.enumeration (ov->option, ov->ctx)
- = ov->value->enumeration;
- break;
- default:
- gdb_assert_not_reached ("unhandled option type");
- }
+ save_option_value_in_ctx (ov);
}
}
}
else
{
- retval = strtoulst (p, pp, 0);
- if (p == *pp)
+ const char *end = p;
+ retval = strtoulst (p, &end, 0);
+ if (p == end)
{
/* There is no number here. (e.g. "cond a == b"). */
error (_("Expected integer at: %s"), p);
}
- p = *pp;
+ p = end;
}
if (!(isspace (*p) || *p == '\0' || *p == trailer))
const char *enum_opt = test_options_enum_values_xxx;
unsigned int uint_opt = 0;
int zuint_unl_opt = 0;
+
+ /* Dump the options to FILE. ARGS is the remainder unprocessed
+ arguments. */
+ void dump (ui_file *file, const char *args) const
+ {
+ fprintf_unfiltered (file,
+ _("-flag %d -xx1 %d -xx2 %d -bool %d "
+ "-enum %s -uint %s -zuint-unl %s -- %s\n"),
+ flag_opt,
+ xx1_opt,
+ xx2_opt,
+ boolean_opt,
+ enum_opt,
+ (uint_opt == UINT_MAX
+ ? "unlimited"
+ : pulongest (uint_opt)),
+ (zuint_unl_opt == -1
+ ? "unlimited"
+ : plongest (zuint_unl_opt)),
+ args);
+ }
};
/* Option definitions for the "maintenance test-options" commands. */
else
args = skip_spaces (args);
- printf_unfiltered (_("-flag %d -xx1 %d -xx2 %d -bool %d "
- "-enum %s -uint %s -zuint-unl %s -- %s\n"),
- opts.flag_opt,
- opts.xx1_opt,
- opts.xx2_opt,
- opts.boolean_opt,
- opts.enum_opt,
- (opts.uint_opt == UINT_MAX
- ? "unlimited"
- : pulongest (opts.uint_opt)),
- (opts.zuint_unl_opt == -1
- ? "unlimited"
- : plongest (opts.zuint_unl_opt)),
- args);
+ opts.dump (gdb_stdout, args);
}
-/* Variables used by the "maintenance show
- test-options-completion-result" command. These variables are
- stored by the completer of the "maint test-options"
- subcommands. */
+/* Variable used by the "maintenance show
+ test-options-completion-result" command. This variable is stored
+ by the completer of the "maint test-options" subcommands.
-/* The result of gdb::option::complete_options. */
-static int maintenance_test_options_command_completion_result;
-/* The text at the word point after gdb::option::complete_options
- returns. */
+ If the completer returned false, this includes the text at the word
+ point after gdb::option::complete_options returns. If true, then
+ this includes a dump of the processed options. */
static std::string maintenance_test_options_command_completion_text;
/* The "maintenance show test-options-completion-result" command. */
static void
-maintenance_show_test_options_completion_result
- (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
+maintenance_show_test_options_completion_result (const char *args,
+ int from_tty)
{
- if (maintenance_test_options_command_completion_result)
- fprintf_filtered (file, "1\n");
+ puts_filtered (maintenance_test_options_command_completion_text.c_str ());
+}
+
+/* Save the completion result in the global variables read by the
+ "maintenance test-options require-delimiter" command. */
+
+static void
+save_completion_result (const test_options_opts &opts, bool res,
+ const char *text)
+{
+ if (res)
+ {
+ string_file stream;
+
+ stream.puts ("1 ");
+ opts.dump (&stream, text);
+ maintenance_test_options_command_completion_text
+ = std::move (stream.string ());
+ }
else
- fprintf_filtered
- (file, _("0 %s\n"),
- maintenance_test_options_command_completion_text.c_str ());
+ {
+ maintenance_test_options_command_completion_text
+ = string_printf ("0 %s\n", text);
+ }
}
/* Implementation of completer for the "maintenance test-options
const char *text,
gdb::option::process_options_mode mode)
{
+ test_options_opts opts;
+
try
{
- maintenance_test_options_command_completion_result
- = gdb::option::complete_options
- (tracker, &text, mode,
- make_test_options_options_def_group (nullptr));
- maintenance_test_options_command_completion_text = text;
+ bool res = (gdb::option::complete_options
+ (tracker, &text, mode,
+ make_test_options_options_def_group (&opts)));
+
+ save_completion_result (opts, res, text);
}
catch (const gdb_exception_error &ex)
{
- maintenance_test_options_command_completion_result = 1;
+ save_completion_result (opts, true, text);
throw;
}
}
set_cmd_completer_handle_brkchars
(cmd, maintenance_test_options_unknown_is_operand_command_completer);
- add_setshow_zinteger_cmd ("test-options-completion-result", class_maintenance,
- &maintenance_test_options_command_completion_result,
- _("\
-Set maintenance test-options completion result."), _("\
-Show maintenance test-options completion result."), _("\
-Show the results of completing\n\
+ add_cmd ("test-options-completion-result", class_maintenance,
+ maintenance_show_test_options_completion_result,
+ _("\
+Show maintenance test-options completion result.\n\
+Shows the results of completing\n\
\"maint test-options require-delimiter\",\n\
\"maint test-options unknown-is-error\", or\n\
\"maint test-options unknown-is-operand\"."),
- NULL,
- maintenance_show_test_options_completion_result,
- &maintenance_set_cmdlist,
- &maintenance_show_cmdlist);
+ &maintenance_show_cmdlist);
}
+2019-07-03 Pedro Alves <palves@redhat.com>
+
+ * gdb.base/options.exp (test-misc, test-flag, test-boolean)
+ (test-uinteger, test-enum): Adjust res_test_gdb_... calls to pass
+ the expected output in the success.
+
2019-07-03 Pedro Alves <palves@redhat.com>
* lib/completion-support.exp (test_gdb_complete_tab_multiple):
}
# Completing at "-" should list all options.
- res_test_gdb_complete_multiple "1" "$cmd " "-" "" $all_options
+ res_test_gdb_complete_multiple \
+ "1 [expect_none "-"]" \
+ "$cmd " "-" "" $all_options
# Now with a double dash.
gdb_test "$cmd --" [expect_none ""]
# "--" is recognized by options completer, gdb auto-appends a
# space.
- test_completer_recognizes 1 "$cmd --"
+ test_completer_recognizes \
+ "1 [expect_none "--"]" \
+ "$cmd --"
# Now with a double dash, plus a dash as operand.
gdb_test "$cmd -- -" [expect_none "-"]
res_test_gdb_complete_none "0 -" "$cmd -- -"
# Completing an unambiguous option just appends an empty space.
- test_completer_recognizes 1 "$cmd -flag"
+ test_completer_recognizes \
+ "1 [expect_none "-flag"]" \
+ "$cmd -flag"
# Try running an ambiguous option.
if {$variant == "require-delimiter"} {
set cmd [make_cmd $variant]
# Completing a flag just appends a space.
- test_completer_recognizes 1 "$cmd -flag"
+ test_completer_recognizes \
+ "1 [expect_none "-flag"]" \
+ "$cmd -flag"
# Add a dash, and all options should be shown.
- test_gdb_complete_multiple "$cmd -flag " "-" "" $all_options
+ res_test_gdb_complete_multiple \
+ "1 [expect_flag "-"]" \
+ "$cmd -flag " "-" "" $all_options
# Basic smoke tests of accepted / not accepted values.
# "on/off".
if {$variant == "require-delimiter"} {
- res_test_gdb_complete_none "1" "$cmd -flag o"
+ res_test_gdb_complete_none \
+ "1 [expect_flag "o"]" \
+ "$cmd -flag o"
gdb_test "$cmd -flag o" [expect_none "-flag o"]
} else {
# E.g., "frame apply all -past-main COMMAND".
if {$variant == "require-delimiter"} {
- res_test_gdb_complete_multiple 1 "$cmd -bool " "" "" {
+ res_test_gdb_complete_multiple \
+ "1 [expect_none ""]" \
+ "$cmd -bool " "" "" {
"-bool"
"-enum"
"-flag"
}
# Add another dash, and "on/off" are no longer offered:
- res_test_gdb_complete_multiple 1 "$cmd -bool " "-" "" $all_options
+ res_test_gdb_complete_multiple \
+ "1 [expect_bool "-"]" \
+ "$cmd -bool " "-" "" $all_options
# Basic smoke tests of accepted / not accepted values.
# However, the completer does recognize them if you start typing
# the boolean value.
foreach value {"0" "1"} {
- test_completer_recognizes 1 "$cmd -bool $value"
+ test_completer_recognizes \
+ "1 [expect_none ""]" \
+ "$cmd -bool $value"
}
foreach value {"of" "off"} {
- res_test_gdb_complete_unique 1 \
+ res_test_gdb_complete_unique \
+ "1 [expect_none ""]" \
"$cmd -bool $value" \
"$cmd -bool off"
}
foreach value {"y" "ye" "yes"} {
- res_test_gdb_complete_unique 1 \
+ res_test_gdb_complete_unique \
+ "1 [expect_none ""]" \
"$cmd -bool $value" \
"$cmd -bool yes"
}
foreach value {"n" "no"} {
- res_test_gdb_complete_unique 1 \
+ res_test_gdb_complete_unique \
+ "1 [expect_none ""]" \
"$cmd -bool $value" \
"$cmd -bool no"
}
"enabl"
"enable"
} {
- res_test_gdb_complete_unique 1 \
+ res_test_gdb_complete_unique \
+ "1 [expect_none ""]" \
"$cmd -bool $value" \
"$cmd -bool enable"
}
"disabl"
"disable"
} {
- res_test_gdb_complete_unique 1 \
+ res_test_gdb_complete_unique \
+ "1 [expect_none ""]" \
"$cmd -bool $value" \
"$cmd -bool disable"
}
if {$variant == "require-delimiter"} {
- res_test_gdb_complete_none "1" "$cmd -bool xxx"
+ res_test_gdb_complete_none \
+ "1 [expect_none "xxx"]" \
+ "$cmd -bool xxx"
} else {
res_test_gdb_complete_none "0 xxx" "$cmd -bool xxx"
}
# Completing after a boolean option + "o" does list "on/off",
# though.
if {$variant == "require-delimiter"} {
- res_test_gdb_complete_multiple 1 "$cmd -bool " "o" "" {
+ res_test_gdb_complete_multiple \
+ "1 [expect_none "o"]" \
+ "$cmd -bool " "o" "" {
"off"
"on"
}
set cmd "[make_cmd $variant] -$option"
# Test completing a uinteger option:
- res_test_gdb_complete_multiple 1 "$cmd " "" "" {
+ res_test_gdb_complete_multiple \
+ "1 [expect_none ""]" \
+ "$cmd " "" "" {
"NUMBER"
"unlimited"
}
# NUMBER above is just a placeholder, make sure we don't complete
# it as a valid option.
- res_test_gdb_complete_none 1 "$cmd NU"
+ res_test_gdb_complete_none \
+ "1 [expect_none "NU"]" \
+ "$cmd NU"
# "unlimited" is valid though.
- res_test_gdb_complete_unique 1 \
+ res_test_gdb_complete_unique \
+ "1 [expect_none "u"]" \
"$cmd u" \
"$cmd unlimited"
# Don't offer completions until we're past the
# -uinteger/-zuinteger-unlimited argument.
- res_test_gdb_complete_none 1 "$cmd 1"
+ res_test_gdb_complete_none \
+ "1 [expect_none ""]" \
+ "$cmd 1"
# A number of invalid values.
foreach value {"x" "x " "1a" "1a " "1-" "1- " "unlimitedx"} {
- res_test_gdb_complete_none 1 "$cmd $value"
+ res_test_gdb_complete_none \
+ "1 [expect_none $value]" \
+ "$cmd $value"
}
# Try "-1".
if {$option == "uinteger"} {
# -1 is invalid uinteger.
foreach value {"-1" "-1 "} {
- res_test_gdb_complete_none 1 "$cmd $value"
+ res_test_gdb_complete_none \
+ "1 [expect_none ""]" \
+ "$cmd $value"
}
} else {
# -1 is valid for zuinteger-unlimited.
- res_test_gdb_complete_none 1 "$cmd -1"
+ res_test_gdb_complete_none \
+ "1 [expect_none ""]" \
+ "$cmd -1"
if {$variant == "require-delimiter"} {
- res_test_gdb_complete_multiple 1 "$cmd -1 " "" "-" $all_options
+ res_test_gdb_complete_multiple \
+ "1 [expect_integer $option "unlimited" ""]" \
+ "$cmd -1 " "" "-" $all_options
} else {
res_test_gdb_complete_none "0 " "$cmd -1 "
}
# - for !require-delimiter commands, completion offers nothing
# and returns false.
if {$variant == "require-delimiter"} {
- res_test_gdb_complete_multiple 1 "$cmd 1 " "" "-" $all_options
+ res_test_gdb_complete_multiple \
+ "1 [expect_integer $option 1 ""]" \
+ "$cmd 1 " "" "-" $all_options
} else {
res_test_gdb_complete_none "0 " "$cmd 1 "
}
# Test completing non-option arguments after "-uinteger 1 ".
foreach operand {"x" "x " "1a" "1a " "1-" "1- "} {
if {$variant == "require-delimiter"} {
- res_test_gdb_complete_none 1 "$cmd 1 $operand"
+ res_test_gdb_complete_none \
+ "1 [expect_integer $option 1 $operand]" \
+ "$cmd 1 $operand"
} else {
res_test_gdb_complete_none "0 $operand" "$cmd 1 $operand"
}
if {$variant == "unknown-is-operand"} {
res_test_gdb_complete_none "0 $operand" "$cmd 1 $operand"
} else {
- res_test_gdb_complete_none 1 "$cmd 1 $operand"
+ res_test_gdb_complete_none \
+ "1 [expect_integer $option 1 $operand]" \
+ "$cmd 1 $operand"
}
}
}
proc_with_prefix test-enum {variant} {
set cmd [make_cmd $variant]
- res_test_gdb_complete_multiple 1 "$cmd -enum " "" "" {
+ res_test_gdb_complete_multiple \
+ "1 [expect_none ""]" \
+ "$cmd -enum " "" "" {
"xxx"
"yyy"
"zzz"
# Check that "-" where a value is expected does not show the
# command's options. I.e., an enum's value is not optional.
# Check both completion and running the command.
- res_test_gdb_complete_none 1 "$cmd -enum -"
+ res_test_gdb_complete_none \
+ "1 [expect_none "-"]" \
+ "$cmd -enum -"
gdb_test "$cmd -enum --"\
"Requires an argument. Valid arguments are xxx, yyy, zzz\\."