Make gdb::option::complete_options save processed arguments too
[deliverable/binutils-gdb.git] / gdb / maint-test-options.c
CommitLineData
9d0faba9
PA
1/* Maintenance commands for testing the options framework.
2
3 Copyright (C) 2019 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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.
11
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.
16
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/>. */
19
20#include "defs.h"
21#include "gdbcmd.h"
22#include "cli/cli-option.h"
23
24/* This file defines three "maintenance test-options" subcommands to
25 exercise TAB-completion and option processing:
26
27 (gdb) maint test-options require-delimiter
28 (gdb) maint test-options unknown-is-error
29 (gdb) maint test-options unknown-is-operand
30
31 And a fourth one to help with TAB-completion testing.
32
33 (gdb) maint show test-options-completion-result
34
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:
38
39 - "print" and "compile print", are like "require-delimiter",
40 because they accept random expressions as argument.
41
42 - "backtrace" and "frame/thread apply" are like
43 "unknown-is-operand", because "-" is a valid command.
44
45 - "compile file" and "compile code" are like "unknown-is-error".
46
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.
59
60 These maintenance commands support options of all the different
61 available kinds of commands (boolean, enum, flag, uinteger):
62
63 (gdb) maint test-options require-delimiter -[TAB]
64 -bool -enum -flag -uinteger -xx1 -xx2
65
66 (gdb) maint test-options require-delimiter -bool o[TAB]
67 off on
68 (gdb) maint test-options require-delimiter -enum [TAB]
69 xxx yyy zzz
70 (gdb) maint test-options require-delimiter -uinteger [TAB]
71 NUMBER unlimited
72
73 '-xx1' and '-xx2' are flag options too. They exist in order to
74 test ambiguous option names, like '-xx'.
75
76 Invoking the commands makes them print out the options parsed:
77
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
80
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
87
88 The "maint show test-options-completion-result" command exists in
89 order to do something similar for completion:
90
91 (gdb) maint test-options unknown-is-error -flag -b 0 -enum yyy OPERAND[TAB]
92 (gdb) maint show test-options-completion-result
93 0 OPERAND
94
95 (gdb) maint test-options unknown-is-error -flag -b 0 -enum yyy[TAB]
96 (gdb) maint show test-options-completion-result
97 1
98
99 (gdb) maint test-options require-dash -unknown[TAB]
100 (gdb) maint show test-options-completion-result
101 1
102
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.
107
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
111 scenarios. */
112
113/* Enum values for the "maintenance test-options" commands. */
114const char test_options_enum_values_xxx[] = "xxx";
115const char test_options_enum_values_yyy[] = "yyy";
116const char test_options_enum_values_zzz[] = "zzz";
117static const char *const test_options_enum_values_choices[] =
118{
119 test_options_enum_values_xxx,
120 test_options_enum_values_yyy,
121 test_options_enum_values_zzz,
122 NULL
123};
124
125/* Option data for the "maintenance test-options" commands. */
126
127struct test_options_opts
128{
129 int flag_opt = 0;
130 int xx1_opt = 0;
131 int xx2_opt = 0;
132 int boolean_opt = 0;
133 const char *enum_opt = test_options_enum_values_xxx;
134 unsigned int uint_opt = 0;
135 int zuint_unl_opt = 0;
41fc454c
PA
136
137 /* Dump the options to FILE. ARGS is the remainder unprocessed
138 arguments. */
139 void dump (ui_file *file, const char *args) const
140 {
141 fprintf_unfiltered (file,
142 _("-flag %d -xx1 %d -xx2 %d -bool %d "
143 "-enum %s -uint %s -zuint-unl %s -- %s\n"),
144 flag_opt,
145 xx1_opt,
146 xx2_opt,
147 boolean_opt,
148 enum_opt,
149 (uint_opt == UINT_MAX
150 ? "unlimited"
151 : pulongest (uint_opt)),
152 (zuint_unl_opt == -1
153 ? "unlimited"
154 : plongest (zuint_unl_opt)),
155 args);
156 }
9d0faba9
PA
157};
158
159/* Option definitions for the "maintenance test-options" commands. */
160
161static const gdb::option::option_def test_options_option_defs[] = {
162
163 /* A flag option. */
164 gdb::option::flag_option_def<test_options_opts> {
165 "flag",
166 [] (test_options_opts *opts) { return &opts->flag_opt; },
167 N_("A flag option."),
168 },
169
170 /* A couple flags with similar names, for "ambiguous option names"
171 testing. */
172 gdb::option::flag_option_def<test_options_opts> {
173 "xx1",
174 [] (test_options_opts *opts) { return &opts->xx1_opt; },
175 N_("A flag option."),
176 },
177 gdb::option::flag_option_def<test_options_opts> {
178 "xx2",
179 [] (test_options_opts *opts) { return &opts->xx2_opt; },
180 N_("A flag option."),
181 },
182
183 /* A boolean option. */
184 gdb::option::boolean_option_def<test_options_opts> {
185 "bool",
186 [] (test_options_opts *opts) { return &opts->boolean_opt; },
187 nullptr, /* show_cmd_cb */
188 N_("A boolean option."),
189 },
190
191 /* An enum option. */
192 gdb::option::enum_option_def<test_options_opts> {
193 "enum",
194 test_options_enum_values_choices,
195 [] (test_options_opts *opts) { return &opts->enum_opt; },
196 nullptr, /* show_cmd_cb */
197 N_("An enum option."),
198 },
199
200 /* A uinteger option. */
201 gdb::option::uinteger_option_def<test_options_opts> {
202 "uinteger",
203 [] (test_options_opts *opts) { return &opts->uint_opt; },
204 nullptr, /* show_cmd_cb */
205 N_("A uinteger option."),
206 nullptr, /* show_doc */
207 N_("A help doc that spawns\nmultiple lines."),
208 },
209
210 /* A zuinteger_unlimited option. */
211 gdb::option::zuinteger_unlimited_option_def<test_options_opts> {
212 "zuinteger-unlimited",
213 [] (test_options_opts *opts) { return &opts->zuint_unl_opt; },
214 nullptr, /* show_cmd_cb */
215 N_("A zuinteger-unlimited option."),
216 nullptr, /* show_doc */
217 nullptr, /* help_doc */
218 },
219};
220
221/* Create an option_def_group for the test_options_opts options, with
222 OPTS as context. */
223
224static inline gdb::option::option_def_group
225make_test_options_options_def_group (test_options_opts *opts)
226{
227 return {{test_options_option_defs}, opts};
228}
229
230/* Implementation of the "maintenance test-options
231 require-delimiter/unknown-is-error/unknown-is-operand" commands.
232 Each of the commands maps to a different enum process_options_mode
233 enumerator. The test strategy is simply processing the options in
234 a number of scenarios, and printing back the parsed result. */
235
236static void
237maintenance_test_options_command_mode (const char *args,
238 gdb::option::process_options_mode mode)
239{
240 test_options_opts opts;
241
242 gdb::option::process_options (&args, mode,
243 make_test_options_options_def_group (&opts));
244
245 if (args == nullptr)
246 args = "";
247 else
248 args = skip_spaces (args);
249
41fc454c 250 opts.dump (gdb_stdout, args);
9d0faba9
PA
251}
252
41fc454c
PA
253/* Variable used by the "maintenance show
254 test-options-completion-result" command. This variable is stored
255 by the completer of the "maint test-options" subcommands.
9d0faba9 256
41fc454c
PA
257 If the completer returned false, this includes the text at the word
258 point after gdb::option::complete_options returns. If true, then
259 this includes a dump of the processed options. */
9d0faba9
PA
260static std::string maintenance_test_options_command_completion_text;
261
262/* The "maintenance show test-options-completion-result" command. */
263
264static void
41fc454c
PA
265maintenance_show_test_options_completion_result (const char *args,
266 int from_tty)
9d0faba9 267{
41fc454c
PA
268 puts_filtered (maintenance_test_options_command_completion_text.c_str ());
269}
270
271/* Save the completion result in the global variables read by the
272 "maintenance test-options require-delimiter" command. */
273
274static void
275save_completion_result (const test_options_opts &opts, bool res,
276 const char *text)
277{
278 if (res)
279 {
280 string_file stream;
281
282 stream.puts ("1 ");
283 opts.dump (&stream, text);
284 maintenance_test_options_command_completion_text
285 = std::move (stream.string ());
286 }
9d0faba9 287 else
41fc454c
PA
288 {
289 maintenance_test_options_command_completion_text
290 = string_printf ("0 %s\n", text);
291 }
9d0faba9
PA
292}
293
294/* Implementation of completer for the "maintenance test-options
295 require-delimiter/unknown-is-error/unknown-is-operand" commands.
296 Each of the commands maps to a different enum process_options_mode
297 enumerator. */
298
299static void
300maintenance_test_options_completer_mode (completion_tracker &tracker,
301 const char *text,
302 gdb::option::process_options_mode mode)
303{
41fc454c
PA
304 test_options_opts opts;
305
9d0faba9
PA
306 try
307 {
41fc454c
PA
308 bool res = (gdb::option::complete_options
309 (tracker, &text, mode,
310 make_test_options_options_def_group (&opts)));
311
312 save_completion_result (opts, res, text);
9d0faba9
PA
313 }
314 catch (const gdb_exception_error &ex)
315 {
41fc454c 316 save_completion_result (opts, true, text);
9d0faba9
PA
317 throw;
318 }
319}
320
321/* Implementation of the "maintenance test-options require-delimiter"
322 command. */
323
324static void
325maintenance_test_options_require_delimiter_command (const char *args,
326 int from_tty)
327{
328 maintenance_test_options_command_mode
329 (args, gdb::option::PROCESS_OPTIONS_REQUIRE_DELIMITER);
330}
331
332/* Implementation of the "maintenance test-options
333 unknown-is-error" command. */
334
335static void
336maintenance_test_options_unknown_is_error_command (const char *args,
337 int from_tty)
338{
339 maintenance_test_options_command_mode
340 (args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR);
341}
342
343/* Implementation of the "maintenance test-options
344 unknown-is-operand" command. */
345
346static void
347maintenance_test_options_unknown_is_operand_command (const char *args,
348 int from_tty)
349{
350 maintenance_test_options_command_mode
351 (args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND);
352}
353
354/* Completer for the "maintenance test-options require-delimiter"
355 command. */
356
357static void
358maintenance_test_options_require_delimiter_command_completer
359 (cmd_list_element *ignore, completion_tracker &tracker,
360 const char *text, const char *word)
361{
362 maintenance_test_options_completer_mode
363 (tracker, text, gdb::option::PROCESS_OPTIONS_REQUIRE_DELIMITER);
364}
365
366/* Completer for the "maintenance test-options unknown-is-error"
367 command. */
368
369static void
370maintenance_test_options_unknown_is_error_command_completer
371 (cmd_list_element *ignore, completion_tracker &tracker,
372 const char *text, const char *word)
373{
374 maintenance_test_options_completer_mode
375 (tracker, text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR);
376}
377
378/* Completer for the "maintenance test-options unknown-is-operand"
379 command. */
380
381static void
382maintenance_test_options_unknown_is_operand_command_completer
383 (cmd_list_element *ignore, completion_tracker &tracker,
384 const char *text, const char *word)
385{
386 maintenance_test_options_completer_mode
387 (tracker, text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND);
388}
389
390/* Command list for maint test-options. */
391struct cmd_list_element *maintenance_test_options_list;
392
393/* The "maintenance test-options" prefix command. */
394
395static void
396maintenance_test_options_command (const char *arg, int from_tty)
397{
398 printf_unfiltered
399 (_("\"maintenance test-options\" must be followed "
400 "by the name of a subcommand.\n"));
401 help_list (maintenance_test_options_list, "maintenance test-options ",
402 all_commands, gdb_stdout);
403}
404
405\f
406void
407_initialize_maint_test_options ()
408{
409 cmd_list_element *cmd;
410
411 add_prefix_cmd ("test-options", no_class, maintenance_test_options_command,
412 _("\
413Generic command for testing the options infrastructure."),
414 &maintenance_test_options_list,
415 "maintenance test-options ", 0,
416 &maintenancelist);
417
418 const auto def_group = make_test_options_options_def_group (nullptr);
419
420 static const std::string help_require_delim_str
421 = gdb::option::build_help (_("\
422Command used for testing options processing.\n\
423Usage: maint test-options require-delimiter [[OPTION]... --] [OPERAND]...\n\
424\n\
425Options:\n\
426\n\
427%OPTIONS%\n\
428If you specify any command option, you must use a double dash (\"--\")\n\
429to mark the end of option processing."),
430 def_group);
431
432 static const std::string help_unknown_is_error_str
433 = gdb::option::build_help (_("\
434Command used for testing options processing.\n\
435Usage: maint test-options unknown-is-error [OPTION]... [OPERAND]...\n\
436\n\
437Options:\n\
438\n\
439%OPTIONS%"),
440 def_group);
441
442 static const std::string help_unknown_is_operand_str
443 = gdb::option::build_help (_("\
444Command used for testing options processing.\n\
445Usage: maint test-options unknown-is-operand [OPTION]... [OPERAND]...\n\
446\n\
447Options:\n\
448\n\
449%OPTIONS%"),
450 def_group);
451
452 cmd = add_cmd ("require-delimiter", class_maintenance,
453 maintenance_test_options_require_delimiter_command,
454 help_require_delim_str.c_str (),
455 &maintenance_test_options_list);
456 set_cmd_completer_handle_brkchars
457 (cmd, maintenance_test_options_require_delimiter_command_completer);
458
459 cmd = add_cmd ("unknown-is-error", class_maintenance,
460 maintenance_test_options_unknown_is_error_command,
461 help_unknown_is_error_str.c_str (),
462 &maintenance_test_options_list);
463 set_cmd_completer_handle_brkchars
464 (cmd, maintenance_test_options_unknown_is_error_command_completer);
465
466 cmd = add_cmd ("unknown-is-operand", class_maintenance,
467 maintenance_test_options_unknown_is_operand_command,
468 help_unknown_is_operand_str.c_str (),
469 &maintenance_test_options_list);
470 set_cmd_completer_handle_brkchars
471 (cmd, maintenance_test_options_unknown_is_operand_command_completer);
472
41fc454c
PA
473 add_cmd ("test-options-completion-result", class_maintenance,
474 maintenance_show_test_options_completion_result,
475 _("\
476Show maintenance test-options completion result.\n\
477Shows the results of completing\n\
9d0faba9
PA
478\"maint test-options require-delimiter\",\n\
479\"maint test-options unknown-is-error\", or\n\
480\"maint test-options unknown-is-operand\"."),
41fc454c 481 &maintenance_show_cmdlist);
9d0faba9 482}
This page took 0.050826 seconds and 4 git commands to generate.