1/* Maintenance commands for testing the options framework. 2 3 Copyright (C) 2019-2020 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, string, uinteger): 62 63 (gdb) maint test-options require-delimiter -[TAB] 64 -bool -enum -flag -string -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 bool flag_opt = false; 130 bool xx1_opt = false; 131 bool xx2_opt = false; 132 bool boolean_opt = false; 133 const char *enum_opt = test_options_enum_values_xxx; 134 unsigned int uint_opt = 0; 135 int zuint_unl_opt = 0; 136 char *string_opt = nullptr; 137 138 test_options_opts () = default; 139 140 DISABLE_COPY_AND_ASSIGN (test_options_opts); 141 142 ~test_options_opts () 143 { 144 xfree (string_opt); 145 } 146 147 /* Dump the options to FILE. ARGS is the remainder unprocessed 148 arguments. */ 149 void dump (ui_file *file, const char *args) const 150 { 151 fprintf_unfiltered (file, 152 _("-flag %d -xx1 %d -xx2 %d -bool %d " 153 "-enum %s -uint %s -zuint-unl %s -string '%s' -- %s\n"), 154 flag_opt, 155 xx1_opt, 156 xx2_opt, 157 boolean_opt, 158 enum_opt, 159 (uint_opt == UINT_MAX 160 ? "unlimited" 161 : pulongest (uint_opt)), 162 (zuint_unl_opt == -1 163 ? "unlimited" 164 : plongest (zuint_unl_opt)), 165 (string_opt != nullptr 166 ? string_opt 167 : ""), 168 args); 169 } 170}; 171 172/* Option definitions for the "maintenance test-options" commands. */ 173 174static const gdb::option::option_def test_options_option_defs[] = { 175 176 /* A flag option. */ 177 gdb::option::flag_option_def<test_options_opts> { 178 "flag", 179 [] (test_options_opts *opts) { return &opts->flag_opt; }, 180 N_("A flag option."), 181 }, 182 183 /* A couple flags with similar names, for "ambiguous option names" 184 testing. */ 185 gdb::option::flag_option_def<test_options_opts> { 186 "xx1", 187 [] (test_options_opts *opts) { return &opts->xx1_opt; }, 188 N_("A flag option."), 189 }, 190 gdb::option::flag_option_def<test_options_opts> { 191 "xx2", 192 [] (test_options_opts *opts) { return &opts->xx2_opt; }, 193 N_("A flag option."), 194 }, 195 196 /* A boolean option. */ 197 gdb::option::boolean_option_def<test_options_opts> { 198 "bool", 199 [] (test_options_opts *opts) { return &opts->boolean_opt; }, 200 nullptr, /* show_cmd_cb */ 201 N_("A boolean option."), 202 }, 203 204 /* An enum option. */ 205 gdb::option::enum_option_def<test_options_opts> { 206 "enum", 207 test_options_enum_values_choices, 208 [] (test_options_opts *opts) { return &opts->enum_opt; }, 209 nullptr, /* show_cmd_cb */ 210 N_("An enum option."), 211 }, 212 213 /* A uinteger option. */ 214 gdb::option::uinteger_option_def<test_options_opts> { 215 "uinteger", 216 [] (test_options_opts *opts) { return &opts->uint_opt; }, 217 nullptr, /* show_cmd_cb */ 218 N_("A uinteger option."), 219 nullptr, /* show_doc */ 220 N_("A help doc that spawns\nmultiple lines."), 221 }, 222 223 /* A zuinteger_unlimited option. */ 224 gdb::option::zuinteger_unlimited_option_def<test_options_opts> { 225 "zuinteger-unlimited", 226 [] (test_options_opts *opts) { return &opts->zuint_unl_opt; }, 227 nullptr, /* show_cmd_cb */ 228 N_("A zuinteger-unlimited option."), 229 nullptr, /* show_doc */ 230 nullptr, /* help_doc */ 231 }, 232 233 /* A string option. */ 234 gdb::option::string_option_def<test_options_opts> { 235 "string", 236 [] (test_options_opts *opts) { return &opts->string_opt; }, 237 nullptr, /* show_cmd_cb */ 238 N_("A string option."), 239 }, 240}; 241 242/* Create an option_def_group for the test_options_opts options, with 243 OPTS as context. */ 244 245static inline gdb::option::option_def_group 246make_test_options_options_def_group (test_options_opts *opts) 247{ 248 return {{test_options_option_defs}, opts}; 249} 250 251/* Implementation of the "maintenance test-options 252 require-delimiter/unknown-is-error/unknown-is-operand" commands. 253 Each of the commands maps to a different enum process_options_mode 254 enumerator. The test strategy is simply processing the options in 255 a number of scenarios, and printing back the parsed result. */ 256 257static void 258maintenance_test_options_command_mode (const char *args, 259 gdb::option::process_options_mode mode) 260{ 261 test_options_opts opts; 262 263 gdb::option::process_options (&args, mode, 264 make_test_options_options_def_group (&opts)); 265 266 if (args == nullptr) 267 args = ""; 268 else 269 args = skip_spaces (args); 270 271 opts.dump (gdb_stdout, args); 272} 273 274/* Variable used by the "maintenance show 275 test-options-completion-result" command. This variable is stored 276 by the completer of the "maint test-options" subcommands. 277 278 If the completer returned false, this includes the text at the word 279 point after gdb::option::complete_options returns. If true, then 280 this includes a dump of the processed options. */ 281static std::string maintenance_test_options_command_completion_text; 282 283/* The "maintenance show test-options-completion-result" command. */ 284 285static void 286maintenance_show_test_options_completion_result (const char *args, 287 int from_tty) 288{ 289 puts_filtered (maintenance_test_options_command_completion_text.c_str ()); 290} 291 292/* Save the completion result in the global variables read by the 293 "maintenance test-options require-delimiter" command. */ 294 295static void 296save_completion_result (const test_options_opts &opts, bool res, 297 const char *text) 298{ 299 if (res) 300 { 301 string_file stream; 302 303 stream.puts ("1 "); 304 opts.dump (&stream, text); 305 maintenance_test_options_command_completion_text 306 = std::move (stream.string ()); 307 } 308 else 309 { 310 maintenance_test_options_command_completion_text 311 = string_printf ("0 %s\n", text); 312 } 313} 314 315/* Implementation of completer for the "maintenance test-options 316 require-delimiter/unknown-is-error/unknown-is-operand" commands. 317 Each of the commands maps to a different enum process_options_mode 318 enumerator. */ 319 320static void 321maintenance_test_options_completer_mode (completion_tracker &tracker, 322 const char *text, 323 gdb::option::process_options_mode mode) 324{ 325 test_options_opts opts; 326 327 try 328 { 329 bool res = (gdb::option::complete_options 330 (tracker, &text, mode, 331 make_test_options_options_def_group (&opts))); 332 333 save_completion_result (opts, res, text); 334 } 335 catch (const gdb_exception_error &ex) 336 { 337 save_completion_result (opts, true, text); 338 throw; 339 } 340} 341 342/* Implementation of the "maintenance test-options require-delimiter" 343 command. */ 344 345static void 346maintenance_test_options_require_delimiter_command (const char *args, 347 int from_tty) 348{ 349 maintenance_test_options_command_mode 350 (args, gdb::option::PROCESS_OPTIONS_REQUIRE_DELIMITER); 351} 352 353/* Implementation of the "maintenance test-options 354 unknown-is-error" command. */ 355 356static void 357maintenance_test_options_unknown_is_error_command (const char *args, 358 int from_tty) 359{ 360 maintenance_test_options_command_mode 361 (args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR); 362} 363 364/* Implementation of the "maintenance test-options 365 unknown-is-operand" command. */ 366 367static void 368maintenance_test_options_unknown_is_operand_command (const char *args, 369 int from_tty) 370{ 371 maintenance_test_options_command_mode 372 (args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND); 373} 374 375/* Completer for the "maintenance test-options require-delimiter" 376 command. */ 377 378static void 379maintenance_test_options_require_delimiter_command_completer 380 (cmd_list_element *ignore, completion_tracker &tracker, 381 const char *text, const char *word) 382{ 383 maintenance_test_options_completer_mode 384 (tracker, text, gdb::option::PROCESS_OPTIONS_REQUIRE_DELIMITER); 385} 386 387/* Completer for the "maintenance test-options unknown-is-error" 388 command. */ 389 390static void 391maintenance_test_options_unknown_is_error_command_completer 392 (cmd_list_element *ignore, completion_tracker &tracker, 393 const char *text, const char *word) 394{ 395 maintenance_test_options_completer_mode 396 (tracker, text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR); 397} 398 399/* Completer for the "maintenance test-options unknown-is-operand" 400 command. */ 401 402static void 403maintenance_test_options_unknown_is_operand_command_completer 404 (cmd_list_element *ignore, completion_tracker &tracker, 405 const char *text, const char *word) 406{ 407 maintenance_test_options_completer_mode 408 (tracker, text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND); 409} 410 411/* Command list for maint test-options. */ 412struct cmd_list_element *maintenance_test_options_list; 413 414 415void _initialize_maint_test_options (); 416void 417_initialize_maint_test_options () 418{ 419 cmd_list_element *cmd; 420 421 add_basic_prefix_cmd ("test-options", no_class, 422 _("\ 423Generic command for testing the options infrastructure."), 424 &maintenance_test_options_list, 425 "maintenance test-options ", 0, 426 &maintenancelist); 427 428 const auto def_group = make_test_options_options_def_group (nullptr); 429 430 static const std::string help_require_delim_str 431 = gdb::option::build_help (_("\ 432Command used for testing options processing.\n\ 433Usage: maint test-options require-delimiter [[OPTION]... --] [OPERAND]...\n\ 434\n\ 435Options:\n\ 436%OPTIONS%\n\ 437\n\ 438If you specify any command option, you must use a double dash (\"--\")\n\ 439to mark the end of option processing."), 440 def_group); 441 442 static const std::string help_unknown_is_error_str 443 = gdb::option::build_help (_("\ 444Command used for testing options processing.\n\ 445Usage: maint test-options unknown-is-error [OPTION]... [OPERAND]...\n\ 446\n\ 447Options:\n\ 448%OPTIONS%"), 449 def_group); 450 451 static const std::string help_unknown_is_operand_str 452 = gdb::option::build_help (_("\ 453Command used for testing options processing.\n\ 454Usage: maint test-options unknown-is-operand [OPTION]... [OPERAND]...\n\ 455\n\ 456Options:\n\ 457%OPTIONS%"), 458 def_group); 459 460 cmd = add_cmd ("require-delimiter", class_maintenance, 461 maintenance_test_options_require_delimiter_command, 462 help_require_delim_str.c_str (), 463 &maintenance_test_options_list); 464 set_cmd_completer_handle_brkchars 465 (cmd, maintenance_test_options_require_delimiter_command_completer); 466 467 cmd = add_cmd ("unknown-is-error", class_maintenance, 468 maintenance_test_options_unknown_is_error_command, 469 help_unknown_is_error_str.c_str (), 470 &maintenance_test_options_list); 471 set_cmd_completer_handle_brkchars 472 (cmd, maintenance_test_options_unknown_is_error_command_completer); 473 474 cmd = add_cmd ("unknown-is-operand", class_maintenance, 475 maintenance_test_options_unknown_is_operand_command, 476 help_unknown_is_operand_str.c_str (), 477 &maintenance_test_options_list); 478 set_cmd_completer_handle_brkchars 479 (cmd, maintenance_test_options_unknown_is_operand_command_completer); 480 481 add_cmd ("test-options-completion-result", class_maintenance, 482 maintenance_show_test_options_completion_result, 483 _("\ 484Show maintenance test-options completion result.\n\ 485Shows the results of completing\n\ 486\"maint test-options require-delimiter\",\n\ 487\"maint test-options unknown-is-error\", or\n\ 488\"maint test-options unknown-is-operand\"."), 489 &maintenance_show_cmdlist); 490} 491