1 /* Maintenance commands for testing the options framework.
3 Copyright (C) 2019 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 #include "cli/cli-option.h"
24 /* This file defines three "maintenance test-options" subcommands to
25 exercise TAB-completion and option processing:
27 (gdb) maint test-options require-delimiter
28 (gdb) maint test-options unknown-is-error
29 (gdb) maint test-options unknown-is-operand
31 And a fourth one to help with TAB-completion testing.
33 (gdb) maint show test-options-completion-result
35 Each of the test-options subcommands exercise
36 gdb::option::process_options with a different enum
37 process_options_mode value. Examples for commands they model:
39 - "print" and "compile print", are like "require-delimiter",
40 because they accept random expressions as argument.
42 - "backtrace" and "frame/thread apply" are like
43 "unknown-is-operand", because "-" is a valid command.
45 - "compile file" and "compile code" are like "unknown-is-error".
47 These commands allow exercising all aspects of option processing
48 without having to pick some existing command. That should be more
49 stable going forward than relying on an existing user command,
50 since if we picked say "print", that command or its options could
51 change in future, and then we'd be left with having to pick some
52 other command or option to exercise some non-command-specific
53 option processing detail. Also, actual user commands have side
54 effects that we're not interested in when we're focusing on unit
55 testing the options machinery. BTW, a maintenance command is used
56 as a sort of unit test driver instead of actual "maint selftest"
57 unit tests, since we need to go all the way via gdb including
58 readline, for proper testing of TAB completion.
60 These maintenance commands support options of all the different
61 available kinds of commands (boolean, enum, flag, uinteger):
63 (gdb) maint test-options require-delimiter -[TAB]
64 -bool -enum -flag -uinteger -xx1 -xx2
66 (gdb) maint test-options require-delimiter -bool o[TAB]
68 (gdb) maint test-options require-delimiter -enum [TAB]
70 (gdb) maint test-options require-delimiter -uinteger [TAB]
73 '-xx1' and '-xx2' are flag options too. They exist in order to
74 test ambiguous option names, like '-xx'.
76 Invoking the commands makes them print out the options parsed:
78 (gdb) maint test-options unknown-is-error -flag -enum yyy cmdarg
79 -flag 1 -xx1 0 -xx2 0 -bool 0 -enum yyy -uint 0 -zuint-unl 0 -- cmdarg
81 (gdb) maint test-options require-delimiter -flag -enum yyy cmdarg
82 -flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -- -flag -enum yyy cmdarg
83 (gdb) maint test-options require-delimiter -flag -enum yyy cmdarg --
84 Unrecognized option at: cmdarg --
85 (gdb) maint test-options require-delimiter -flag -enum yyy -- cmdarg
86 -flag 1 -xx1 0 -xx2 0 -bool 0 -enum yyy -uint 0 -zuint-unl 0 -- cmdarg
88 The "maint show test-options-completion-result" command exists in
89 order to do something similar for completion:
91 (gdb) maint test-options unknown-is-error -flag -b 0 -enum yyy OPERAND[TAB]
92 (gdb) maint show test-options-completion-result
95 (gdb) maint test-options unknown-is-error -flag -b 0 -enum yyy[TAB]
96 (gdb) maint show test-options-completion-result
99 (gdb) maint test-options require-dash -unknown[TAB]
100 (gdb) maint show test-options-completion-result
103 Here, "1" means the completion function processed the whole input
104 line, and that the command shouldn't do anything with the arguments,
105 since there are no operands. While "0" indicates that there are
106 operands after options. The text after "0" is the operands.
108 This level of detail is particularly important because getting the
109 completion function's entry point to return back to the caller the
110 right pointer into the operand is quite tricky in several
113 /* Enum values for the "maintenance test-options" commands. */
114 const char test_options_enum_values_xxx[] = "xxx";
115 const char test_options_enum_values_yyy[] = "yyy";
116 const char test_options_enum_values_zzz[] = "zzz";
117 static const char *const test_options_enum_values_choices[] =
119 test_options_enum_values_xxx,
120 test_options_enum_values_yyy,
121 test_options_enum_values_zzz,
125 /* Option data for the "maintenance test-options" commands. */
127 struct test_options_opts
133 const char *enum_opt = test_options_enum_values_xxx;
134 unsigned int uint_opt = 0;
135 int zuint_unl_opt = 0;
138 /* Option definitions for the "maintenance test-options" commands. */
140 static const gdb::option::option_def test_options_option_defs[] = {
143 gdb::option::flag_option_def<test_options_opts> {
145 [] (test_options_opts *opts) { return &opts->flag_opt; },
146 N_("A flag option."),
149 /* A couple flags with similar names, for "ambiguous option names"
151 gdb::option::flag_option_def<test_options_opts> {
153 [] (test_options_opts *opts) { return &opts->xx1_opt; },
154 N_("A flag option."),
156 gdb::option::flag_option_def<test_options_opts> {
158 [] (test_options_opts *opts) { return &opts->xx2_opt; },
159 N_("A flag option."),
162 /* A boolean option. */
163 gdb::option::boolean_option_def<test_options_opts> {
165 [] (test_options_opts *opts) { return &opts->boolean_opt; },
166 nullptr, /* show_cmd_cb */
167 N_("A boolean option."),
170 /* An enum option. */
171 gdb::option::enum_option_def<test_options_opts> {
173 test_options_enum_values_choices,
174 [] (test_options_opts *opts) { return &opts->enum_opt; },
175 nullptr, /* show_cmd_cb */
176 N_("An enum option."),
179 /* A uinteger option. */
180 gdb::option::uinteger_option_def<test_options_opts> {
182 [] (test_options_opts *opts) { return &opts->uint_opt; },
183 nullptr, /* show_cmd_cb */
184 N_("A uinteger option."),
185 nullptr, /* show_doc */
186 N_("A help doc that spawns\nmultiple lines."),
189 /* A zuinteger_unlimited option. */
190 gdb::option::zuinteger_unlimited_option_def<test_options_opts> {
191 "zuinteger-unlimited",
192 [] (test_options_opts *opts) { return &opts->zuint_unl_opt; },
193 nullptr, /* show_cmd_cb */
194 N_("A zuinteger-unlimited option."),
195 nullptr, /* show_doc */
196 nullptr, /* help_doc */
200 /* Create an option_def_group for the test_options_opts options, with
203 static inline gdb::option::option_def_group
204 make_test_options_options_def_group (test_options_opts *opts)
206 return {{test_options_option_defs}, opts};
209 /* Implementation of the "maintenance test-options
210 require-delimiter/unknown-is-error/unknown-is-operand" commands.
211 Each of the commands maps to a different enum process_options_mode
212 enumerator. The test strategy is simply processing the options in
213 a number of scenarios, and printing back the parsed result. */
216 maintenance_test_options_command_mode (const char *args,
217 gdb::option::process_options_mode mode)
219 test_options_opts opts;
221 gdb::option::process_options (&args, mode,
222 make_test_options_options_def_group (&opts));
227 args = skip_spaces (args);
229 printf_unfiltered (_("-flag %d -xx1 %d -xx2 %d -bool %d "
230 "-enum %s -uint %s -zuint-unl %s -- %s\n"),
236 (opts.uint_opt == UINT_MAX
238 : pulongest (opts.uint_opt)),
239 (opts.zuint_unl_opt == -1
241 : plongest (opts.zuint_unl_opt)),
245 /* Variables used by the "maintenance show
246 test-options-completion-result" command. These variables are
247 stored by the completer of the "maint test-options"
250 /* The result of gdb::option::complete_options. */
251 static int maintenance_test_options_command_completion_result;
252 /* The text at the word point after gdb::option::complete_options
254 static std::string maintenance_test_options_command_completion_text;
256 /* The "maintenance show test-options-completion-result" command. */
259 maintenance_show_test_options_completion_result
260 (struct ui_file *file, int from_tty,
261 struct cmd_list_element *c, const char *value)
263 if (maintenance_test_options_command_completion_result)
264 fprintf_filtered (file, "1\n");
268 maintenance_test_options_command_completion_text.c_str ());
271 /* Implementation of completer for the "maintenance test-options
272 require-delimiter/unknown-is-error/unknown-is-operand" commands.
273 Each of the commands maps to a different enum process_options_mode
277 maintenance_test_options_completer_mode (completion_tracker &tracker,
279 gdb::option::process_options_mode mode)
283 maintenance_test_options_command_completion_result
284 = gdb::option::complete_options
285 (tracker, &text, mode,
286 make_test_options_options_def_group (nullptr));
287 maintenance_test_options_command_completion_text = text;
289 catch (const gdb_exception_error &ex)
291 maintenance_test_options_command_completion_result = 1;
296 /* Implementation of the "maintenance test-options require-delimiter"
300 maintenance_test_options_require_delimiter_command (const char *args,
303 maintenance_test_options_command_mode
304 (args, gdb::option::PROCESS_OPTIONS_REQUIRE_DELIMITER);
307 /* Implementation of the "maintenance test-options
308 unknown-is-error" command. */
311 maintenance_test_options_unknown_is_error_command (const char *args,
314 maintenance_test_options_command_mode
315 (args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR);
318 /* Implementation of the "maintenance test-options
319 unknown-is-operand" command. */
322 maintenance_test_options_unknown_is_operand_command (const char *args,
325 maintenance_test_options_command_mode
326 (args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND);
329 /* Completer for the "maintenance test-options require-delimiter"
333 maintenance_test_options_require_delimiter_command_completer
334 (cmd_list_element *ignore, completion_tracker &tracker,
335 const char *text, const char *word)
337 maintenance_test_options_completer_mode
338 (tracker, text, gdb::option::PROCESS_OPTIONS_REQUIRE_DELIMITER);
341 /* Completer for the "maintenance test-options unknown-is-error"
345 maintenance_test_options_unknown_is_error_command_completer
346 (cmd_list_element *ignore, completion_tracker &tracker,
347 const char *text, const char *word)
349 maintenance_test_options_completer_mode
350 (tracker, text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR);
353 /* Completer for the "maintenance test-options unknown-is-operand"
357 maintenance_test_options_unknown_is_operand_command_completer
358 (cmd_list_element *ignore, completion_tracker &tracker,
359 const char *text, const char *word)
361 maintenance_test_options_completer_mode
362 (tracker, text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND);
365 /* Command list for maint test-options. */
366 struct cmd_list_element *maintenance_test_options_list;
368 /* The "maintenance test-options" prefix command. */
371 maintenance_test_options_command (const char *arg, int from_tty)
374 (_("\"maintenance test-options\" must be followed "
375 "by the name of a subcommand.\n"));
376 help_list (maintenance_test_options_list, "maintenance test-options ",
377 all_commands, gdb_stdout);
382 _initialize_maint_test_options ()
384 cmd_list_element *cmd;
386 add_prefix_cmd ("test-options", no_class, maintenance_test_options_command,
388 Generic command for testing the options infrastructure."),
389 &maintenance_test_options_list,
390 "maintenance test-options ", 0,
393 const auto def_group = make_test_options_options_def_group (nullptr);
395 static const std::string help_require_delim_str
396 = gdb::option::build_help (_("\
397 Command used for testing options processing.\n\
398 Usage: maint test-options require-delimiter [[OPTION]... --] [OPERAND]...\n\
403 If you specify any command option, you must use a double dash (\"--\")\n\
404 to mark the end of option processing."),
407 static const std::string help_unknown_is_error_str
408 = gdb::option::build_help (_("\
409 Command used for testing options processing.\n\
410 Usage: maint test-options unknown-is-error [OPTION]... [OPERAND]...\n\
417 static const std::string help_unknown_is_operand_str
418 = gdb::option::build_help (_("\
419 Command used for testing options processing.\n\
420 Usage: maint test-options unknown-is-operand [OPTION]... [OPERAND]...\n\
427 cmd = add_cmd ("require-delimiter", class_maintenance,
428 maintenance_test_options_require_delimiter_command,
429 help_require_delim_str.c_str (),
430 &maintenance_test_options_list);
431 set_cmd_completer_handle_brkchars
432 (cmd, maintenance_test_options_require_delimiter_command_completer);
434 cmd = add_cmd ("unknown-is-error", class_maintenance,
435 maintenance_test_options_unknown_is_error_command,
436 help_unknown_is_error_str.c_str (),
437 &maintenance_test_options_list);
438 set_cmd_completer_handle_brkchars
439 (cmd, maintenance_test_options_unknown_is_error_command_completer);
441 cmd = add_cmd ("unknown-is-operand", class_maintenance,
442 maintenance_test_options_unknown_is_operand_command,
443 help_unknown_is_operand_str.c_str (),
444 &maintenance_test_options_list);
445 set_cmd_completer_handle_brkchars
446 (cmd, maintenance_test_options_unknown_is_operand_command_completer);
448 add_setshow_zinteger_cmd ("test-options-completion-result", class_maintenance,
449 &maintenance_test_options_command_completion_result,
451 Set maintenance test-options completion result."), _("\
452 Show maintenance test-options completion result."), _("\
453 Show the results of completing\n\
454 \"maint test-options require-delimiter\",\n\
455 \"maint test-options unknown-is-error\", or\n\
456 \"maint test-options unknown-is-operand\"."),
458 maintenance_show_test_options_completion_result,
459 &maintenance_set_cmdlist,
460 &maintenance_show_cmdlist);