1 //===-- CommandObjectSource.cpp ---------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 #include "llvm/ADT/StringRef.h" 14 15 // Project includes 16 #include "CommandObjectCommands.h" 17 #include "CommandObjectHelp.h" 18 #include "lldb/Core/Debugger.h" 19 #include "lldb/Core/IOHandler.h" 20 #include "lldb/Core/StringList.h" 21 #include "lldb/Interpreter/Args.h" 22 #include "lldb/Interpreter/CommandHistory.h" 23 #include "lldb/Interpreter/CommandInterpreter.h" 24 #include "lldb/Interpreter/CommandObjectRegexCommand.h" 25 #include "lldb/Interpreter/CommandReturnObject.h" 26 #include "lldb/Interpreter/OptionValueBoolean.h" 27 #include "lldb/Interpreter/OptionValueUInt64.h" 28 #include "lldb/Interpreter/Options.h" 29 #include "lldb/Interpreter/ScriptInterpreter.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 //------------------------------------------------------------------------- 35 // CommandObjectCommandsSource 36 //------------------------------------------------------------------------- 37 38 class CommandObjectCommandsHistory : public CommandObjectParsed 39 { 40 public: 41 CommandObjectCommandsHistory(CommandInterpreter &interpreter) : 42 CommandObjectParsed(interpreter, 43 "command history", 44 "Dump the history of commands in this session.", 45 nullptr), 46 m_options (interpreter) 47 { 48 } 49 50 ~CommandObjectCommandsHistory() override = default; 51 52 Options * 53 GetOptions () override 54 { 55 return &m_options; 56 } 57 58 protected: 59 class CommandOptions : public Options 60 { 61 public: 62 CommandOptions (CommandInterpreter &interpreter) : 63 Options (interpreter), 64 m_start_idx(0), 65 m_stop_idx(0), 66 m_count(0), 67 m_clear(false) 68 { 69 } 70 71 ~CommandOptions() override = default; 72 73 Error 74 SetOptionValue (uint32_t option_idx, const char *option_arg) override 75 { 76 Error error; 77 const int short_option = m_getopt_table[option_idx].val; 78 79 switch (short_option) 80 { 81 case 'c': 82 error = m_count.SetValueFromString(option_arg,eVarSetOperationAssign); 83 break; 84 case 's': 85 if (option_arg && strcmp("end", option_arg) == 0) 86 { 87 m_start_idx.SetCurrentValue(UINT64_MAX); 88 m_start_idx.SetOptionWasSet(); 89 } 90 else 91 error = m_start_idx.SetValueFromString(option_arg,eVarSetOperationAssign); 92 break; 93 case 'e': 94 error = m_stop_idx.SetValueFromString(option_arg,eVarSetOperationAssign); 95 break; 96 case 'C': 97 m_clear.SetCurrentValue(true); 98 m_clear.SetOptionWasSet(); 99 break; 100 default: 101 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 102 break; 103 } 104 105 return error; 106 } 107 108 void 109 OptionParsingStarting () override 110 { 111 m_start_idx.Clear(); 112 m_stop_idx.Clear(); 113 m_count.Clear(); 114 m_clear.Clear(); 115 } 116 117 const OptionDefinition* 118 GetDefinitions () override 119 { 120 return g_option_table; 121 } 122 123 // Options table: Required for subclasses of Options. 124 125 static OptionDefinition g_option_table[]; 126 127 // Instance variables to hold the values for command options. 128 129 OptionValueUInt64 m_start_idx; 130 OptionValueUInt64 m_stop_idx; 131 OptionValueUInt64 m_count; 132 OptionValueBoolean m_clear; 133 }; 134 135 bool 136 DoExecute (Args& command, CommandReturnObject &result) override 137 { 138 if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet()) 139 { 140 m_interpreter.GetCommandHistory().Clear(); 141 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 142 } 143 else 144 { 145 if (m_options.m_start_idx.OptionWasSet() && m_options.m_stop_idx.OptionWasSet() && m_options.m_count.OptionWasSet()) 146 { 147 result.AppendError("--count, --start-index and --end-index cannot be all specified in the same invocation"); 148 result.SetStatus(lldb::eReturnStatusFailed); 149 } 150 else 151 { 152 std::pair<bool,uint64_t> start_idx(m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue()); 153 std::pair<bool,uint64_t> stop_idx(m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue()); 154 std::pair<bool,uint64_t> count(m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue()); 155 156 const CommandHistory& history(m_interpreter.GetCommandHistory()); 157 158 if (start_idx.first && start_idx.second == UINT64_MAX) 159 { 160 if (count.first) 161 { 162 start_idx.second = history.GetSize() - count.second; 163 stop_idx.second = history.GetSize() - 1; 164 } 165 else if (stop_idx.first) 166 { 167 start_idx.second = stop_idx.second; 168 stop_idx.second = history.GetSize() - 1; 169 } 170 else 171 { 172 start_idx.second = 0; 173 stop_idx.second = history.GetSize() - 1; 174 } 175 } 176 else 177 { 178 if (!start_idx.first && !stop_idx.first && !count.first) 179 { 180 start_idx.second = 0; 181 stop_idx.second = history.GetSize() - 1; 182 } 183 else if (start_idx.first) 184 { 185 if (count.first) 186 { 187 stop_idx.second = start_idx.second + count.second - 1; 188 } 189 else if (!stop_idx.first) 190 { 191 stop_idx.second = history.GetSize() - 1; 192 } 193 } 194 else if (stop_idx.first) 195 { 196 if (count.first) 197 { 198 if (stop_idx.second >= count.second) 199 start_idx.second = stop_idx.second - count.second + 1; 200 else 201 start_idx.second = 0; 202 } 203 } 204 else /* if (count.first) */ 205 { 206 start_idx.second = 0; 207 stop_idx.second = count.second - 1; 208 } 209 } 210 history.Dump(result.GetOutputStream(), start_idx.second, stop_idx.second); 211 } 212 } 213 return result.Succeeded(); 214 215 } 216 217 CommandOptions m_options; 218 }; 219 220 OptionDefinition 221 CommandObjectCommandsHistory::CommandOptions::g_option_table[] = 222 { 223 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print."}, 224 { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)."}, 225 { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."}, 226 { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history."}, 227 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 228 }; 229 230 //------------------------------------------------------------------------- 231 // CommandObjectCommandsSource 232 //------------------------------------------------------------------------- 233 234 class CommandObjectCommandsSource : public CommandObjectParsed 235 { 236 public: 237 CommandObjectCommandsSource(CommandInterpreter &interpreter) : 238 CommandObjectParsed(interpreter, 239 "command source", 240 "Read in debugger commands from the file <filename> and execute them.", 241 nullptr), 242 m_options (interpreter) 243 { 244 CommandArgumentEntry arg; 245 CommandArgumentData file_arg; 246 247 // Define the first (and only) variant of this arg. 248 file_arg.arg_type = eArgTypeFilename; 249 file_arg.arg_repetition = eArgRepeatPlain; 250 251 // There is only one variant this argument could be; put it into the argument entry. 252 arg.push_back (file_arg); 253 254 // Push the data for the first argument into the m_arguments vector. 255 m_arguments.push_back (arg); 256 } 257 258 ~CommandObjectCommandsSource() override = default; 259 260 const char* 261 GetRepeatCommand (Args ¤t_command_args, uint32_t index) override 262 { 263 return ""; 264 } 265 266 int 267 HandleArgumentCompletion (Args &input, 268 int &cursor_index, 269 int &cursor_char_position, 270 OptionElementVector &opt_element_vector, 271 int match_start_point, 272 int max_return_elements, 273 bool &word_complete, 274 StringList &matches) override 275 { 276 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 277 completion_str.erase (cursor_char_position); 278 279 CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter, 280 CommandCompletions::eDiskFileCompletion, 281 completion_str.c_str(), 282 match_start_point, 283 max_return_elements, 284 nullptr, 285 word_complete, 286 matches); 287 return matches.GetSize(); 288 } 289 290 Options * 291 GetOptions () override 292 { 293 return &m_options; 294 } 295 296 protected: 297 class CommandOptions : public Options 298 { 299 public: 300 CommandOptions (CommandInterpreter &interpreter) : 301 Options (interpreter), 302 m_stop_on_error (true), 303 m_silent_run (false), 304 m_stop_on_continue (true) 305 { 306 } 307 308 ~CommandOptions() override = default; 309 310 Error 311 SetOptionValue (uint32_t option_idx, const char *option_arg) override 312 { 313 Error error; 314 const int short_option = m_getopt_table[option_idx].val; 315 316 switch (short_option) 317 { 318 case 'e': 319 error = m_stop_on_error.SetValueFromString(option_arg); 320 break; 321 322 case 'c': 323 error = m_stop_on_continue.SetValueFromString(option_arg); 324 break; 325 326 case 's': 327 error = m_silent_run.SetValueFromString(option_arg); 328 break; 329 330 default: 331 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 332 break; 333 } 334 335 return error; 336 } 337 338 void 339 OptionParsingStarting () override 340 { 341 m_stop_on_error.Clear(); 342 m_silent_run.Clear(); 343 m_stop_on_continue.Clear(); 344 } 345 346 const OptionDefinition* 347 GetDefinitions () override 348 { 349 return g_option_table; 350 } 351 352 // Options table: Required for subclasses of Options. 353 354 static OptionDefinition g_option_table[]; 355 356 // Instance variables to hold the values for command options. 357 358 OptionValueBoolean m_stop_on_error; 359 OptionValueBoolean m_silent_run; 360 OptionValueBoolean m_stop_on_continue; 361 }; 362 363 bool 364 DoExecute(Args& command, CommandReturnObject &result) override 365 { 366 const size_t argc = command.GetArgumentCount(); 367 if (argc == 1) 368 { 369 const char *filename = command.GetArgumentAtIndex(0); 370 371 FileSpec cmd_file (filename, true); 372 ExecutionContext *exe_ctx = nullptr; // Just use the default context. 373 374 // If any options were set, then use them 375 if (m_options.m_stop_on_error.OptionWasSet() || 376 m_options.m_silent_run.OptionWasSet() || 377 m_options.m_stop_on_continue.OptionWasSet()) 378 { 379 // Use user set settings 380 CommandInterpreterRunOptions options; 381 options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); 382 options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue()); 383 options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue()); 384 options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue()); 385 386 m_interpreter.HandleCommandsFromFile (cmd_file, 387 exe_ctx, 388 options, 389 result); 390 } 391 else 392 { 393 // No options were set, inherit any settings from nested "command source" commands, 394 // or set to sane default settings... 395 CommandInterpreterRunOptions options; 396 m_interpreter.HandleCommandsFromFile (cmd_file, 397 exe_ctx, 398 options, 399 result); 400 } 401 } 402 else 403 { 404 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName()); 405 result.SetStatus (eReturnStatusFailed); 406 } 407 return result.Succeeded(); 408 } 409 410 CommandOptions m_options; 411 }; 412 413 OptionDefinition 414 CommandObjectCommandsSource::CommandOptions::g_option_table[] = 415 { 416 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error."}, 417 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue."}, 418 { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing."}, 419 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 420 }; 421 422 #pragma mark CommandObjectCommandsAlias 423 //------------------------------------------------------------------------- 424 // CommandObjectCommandsAlias 425 //------------------------------------------------------------------------- 426 427 static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 428 "You must define a Python function with this signature:\n" 429 "def my_command_impl(debugger, args, result, internal_dict):\n"; 430 431 class CommandObjectCommandsAlias : public CommandObjectRaw 432 { 433 public: 434 CommandObjectCommandsAlias (CommandInterpreter &interpreter) : 435 CommandObjectRaw(interpreter, 436 "command alias", 437 "Allow users to define their own debugger command abbreviations.", 438 nullptr) 439 { 440 SetHelpLong( 441 "'alias' allows the user to create a short-cut or abbreviation for long \ 442 commands, multi-word commands, and commands that take particular options. \ 443 Below are some simple examples of how one might use the 'alias' command:" R"( 444 445 (lldb) command alias sc script 446 447 Creates the abbreviation 'sc' for the 'script' command. 448 449 (lldb) command alias bp breakpoint 450 451 )" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 452 breakpoint commands are two-word commands, the user would still need to \ 453 enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"( 454 455 (lldb) command alias bpl breakpoint list 456 457 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 458 459 )" "An alias can include some options for the command, with the values either \ 460 filled in at the time the alias is created, or specified as positional \ 461 arguments, to be filled in when the alias is invoked. The following example \ 462 shows how to create aliases with options:" R"( 463 464 (lldb) command alias bfl breakpoint set -f %1 -l %2 465 466 )" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 467 options already part of the alias. So if the user wants to set a breakpoint \ 468 by file and line without explicitly having to use the -f and -l options, the \ 469 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 470 for the actual arguments that will be passed when the alias command is used. \ 471 The number in the placeholder refers to the position/order the actual value \ 472 occupies when the alias is used. All the occurrences of '%1' in the alias \ 473 will be replaced with the first argument, all the occurrences of '%2' in the \ 474 alias will be replaced with the second argument, and so on. This also allows \ 475 actual arguments to be used multiple times within an alias (see 'process \ 476 launch' example below)." R"( 477 478 )" "Note: the positional arguments must substitute as whole words in the resultant \ 479 command, so you can't at present do something like this to append the file extension \ 480 \".cpp\":" R"( 481 482 (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 483 484 )" "For more complex aliasing, use the \"command regex\" command instead. In the \ 485 'bfl' case above, the actual file value will be filled in with the first argument \ 486 following 'bfl' and the actual line number value will be filled in with the second \ 487 argument. The user would use this alias as follows:" R"( 488 489 (lldb) command alias bfl breakpoint set -f %1 -l %2 490 (lldb) bfl my-file.c 137 491 492 This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 493 494 Another example: 495 496 (lldb) command alias pltty process launch -s -o %1 -e %1 497 (lldb) pltty /dev/tty0 498 499 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 500 501 )" "If the user always wanted to pass the same value to a particular option, the \ 502 alias could be defined with that value directly in the alias as a constant, \ 503 rather than using a positional placeholder:" R"( 504 505 (lldb) command alias bl3 breakpoint set -f %1 -l 3 506 507 Always sets a breakpoint on line 3 of whatever file is indicated.)" 508 ); 509 510 CommandArgumentEntry arg1; 511 CommandArgumentEntry arg2; 512 CommandArgumentEntry arg3; 513 CommandArgumentData alias_arg; 514 CommandArgumentData cmd_arg; 515 CommandArgumentData options_arg; 516 517 // Define the first (and only) variant of this arg. 518 alias_arg.arg_type = eArgTypeAliasName; 519 alias_arg.arg_repetition = eArgRepeatPlain; 520 521 // There is only one variant this argument could be; put it into the argument entry. 522 arg1.push_back (alias_arg); 523 524 // Define the first (and only) variant of this arg. 525 cmd_arg.arg_type = eArgTypeCommandName; 526 cmd_arg.arg_repetition = eArgRepeatPlain; 527 528 // There is only one variant this argument could be; put it into the argument entry. 529 arg2.push_back (cmd_arg); 530 531 // Define the first (and only) variant of this arg. 532 options_arg.arg_type = eArgTypeAliasOptions; 533 options_arg.arg_repetition = eArgRepeatOptional; 534 535 // There is only one variant this argument could be; put it into the argument entry. 536 arg3.push_back (options_arg); 537 538 // Push the data for the first argument into the m_arguments vector. 539 m_arguments.push_back (arg1); 540 m_arguments.push_back (arg2); 541 m_arguments.push_back (arg3); 542 } 543 544 ~CommandObjectCommandsAlias() override = default; 545 546 protected: 547 bool 548 DoExecute (const char *raw_command_line, CommandReturnObject &result) override 549 { 550 Args args (raw_command_line); 551 std::string raw_command_string (raw_command_line); 552 553 size_t argc = args.GetArgumentCount(); 554 555 if (argc < 2) 556 { 557 result.AppendError ("'alias' requires at least two arguments"); 558 result.SetStatus (eReturnStatusFailed); 559 return false; 560 } 561 562 // Get the alias command. 563 564 const std::string alias_command = args.GetArgumentAtIndex (0); 565 566 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which 567 // does the stripping itself. 568 size_t pos = raw_command_string.find (alias_command); 569 if (pos == 0) 570 { 571 raw_command_string = raw_command_string.substr (alias_command.size()); 572 pos = raw_command_string.find_first_not_of (' '); 573 if ((pos != std::string::npos) && (pos > 0)) 574 raw_command_string = raw_command_string.substr (pos); 575 } 576 else 577 { 578 result.AppendError ("Error parsing command string. No alias created."); 579 result.SetStatus (eReturnStatusFailed); 580 return false; 581 } 582 583 584 // Verify that the command is alias-able. 585 if (m_interpreter.CommandExists (alias_command.c_str())) 586 { 587 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 588 alias_command.c_str()); 589 result.SetStatus (eReturnStatusFailed); 590 return false; 591 } 592 593 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string. 594 // raw_command_string is returned with the name of the command object stripped off the front. 595 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string); 596 597 if (!cmd_obj) 598 { 599 result.AppendErrorWithFormat ("invalid command given to 'alias'. '%s' does not begin with a valid command." 600 " No alias created.", raw_command_string.c_str()); 601 result.SetStatus (eReturnStatusFailed); 602 return false; 603 } 604 else if (!cmd_obj->WantsRawCommandString ()) 605 { 606 // Note that args was initialized with the original command, and has not been updated to this point. 607 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias. 608 return HandleAliasingNormalCommand (args, result); 609 } 610 else 611 { 612 return HandleAliasingRawCommand (alias_command, raw_command_string, *cmd_obj, result); 613 } 614 return result.Succeeded(); 615 } 616 617 bool 618 HandleAliasingRawCommand (const std::string &alias_command, std::string &raw_command_string, CommandObject &cmd_obj, CommandReturnObject &result) 619 { 620 // Verify & handle any options/arguments passed to the alias command 621 622 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 623 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 624 625 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj.GetCommandName(), false); 626 627 if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp)) 628 { 629 result.AppendError ("Unable to create requested alias.\n"); 630 result.SetStatus (eReturnStatusFailed); 631 return false; 632 } 633 634 // Create the alias 635 if (m_interpreter.AliasExists (alias_command.c_str()) 636 || m_interpreter.UserCommandExists (alias_command.c_str())) 637 { 638 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str())); 639 if (temp_option_arg_sp) 640 { 641 if (option_arg_vector->empty()) 642 m_interpreter.RemoveAliasOptions (alias_command.c_str()); 643 } 644 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 645 alias_command.c_str()); 646 } 647 648 if (cmd_obj_sp) 649 { 650 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp); 651 if (!option_arg_vector->empty()) 652 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp); 653 result.SetStatus (eReturnStatusSuccessFinishNoResult); 654 } 655 else 656 { 657 result.AppendError ("Unable to create requested alias.\n"); 658 result.SetStatus (eReturnStatusFailed); 659 } 660 return result.Succeeded (); 661 } 662 663 bool 664 HandleAliasingNormalCommand (Args& args, CommandReturnObject &result) 665 { 666 size_t argc = args.GetArgumentCount(); 667 668 if (argc < 2) 669 { 670 result.AppendError ("'alias' requires at least two arguments"); 671 result.SetStatus (eReturnStatusFailed); 672 return false; 673 } 674 675 const std::string alias_command = args.GetArgumentAtIndex(0); 676 const std::string actual_command = args.GetArgumentAtIndex(1); 677 678 args.Shift(); // Shift the alias command word off the argument vector. 679 args.Shift(); // Shift the old command word off the argument vector. 680 681 // Verify that the command is alias'able, and get the appropriate command object. 682 683 if (m_interpreter.CommandExists (alias_command.c_str())) 684 { 685 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 686 alias_command.c_str()); 687 result.SetStatus (eReturnStatusFailed); 688 } 689 else 690 { 691 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true)); 692 CommandObjectSP subcommand_obj_sp; 693 bool use_subcommand = false; 694 if (command_obj_sp) 695 { 696 CommandObject *cmd_obj = command_obj_sp.get(); 697 CommandObject *sub_cmd_obj = nullptr; 698 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 699 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 700 701 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) 702 { 703 if (argc >= 3) 704 { 705 const std::string sub_command = args.GetArgumentAtIndex(0); 706 assert (sub_command.length() != 0); 707 subcommand_obj_sp = cmd_obj->GetSubcommandSP (sub_command.c_str()); 708 if (subcommand_obj_sp) 709 { 710 sub_cmd_obj = subcommand_obj_sp.get(); 711 use_subcommand = true; 712 args.Shift(); // Shift the sub_command word off the argument vector. 713 cmd_obj = sub_cmd_obj; 714 } 715 else 716 { 717 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. " 718 "Unable to create alias.\n", 719 sub_command.c_str(), actual_command.c_str()); 720 result.SetStatus (eReturnStatusFailed); 721 return false; 722 } 723 } 724 } 725 726 // Verify & handle any options/arguments passed to the alias command 727 728 if (args.GetArgumentCount () > 0) 729 { 730 CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false); 731 if (use_subcommand) 732 tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false); 733 734 std::string args_string; 735 args.GetCommandString (args_string); 736 737 if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp)) 738 { 739 result.AppendError ("Unable to create requested alias.\n"); 740 result.SetStatus (eReturnStatusFailed); 741 return false; 742 } 743 } 744 745 // Create the alias. 746 747 if (m_interpreter.AliasExists (alias_command.c_str()) 748 || m_interpreter.UserCommandExists (alias_command.c_str())) 749 { 750 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str())); 751 if (tmp_option_arg_sp) 752 { 753 if (option_arg_vector->empty()) 754 m_interpreter.RemoveAliasOptions (alias_command.c_str()); 755 } 756 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 757 alias_command.c_str()); 758 } 759 760 if (use_subcommand) 761 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp); 762 else 763 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp); 764 if (!option_arg_vector->empty()) 765 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp); 766 result.SetStatus (eReturnStatusSuccessFinishNoResult); 767 } 768 else 769 { 770 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str()); 771 result.SetStatus (eReturnStatusFailed); 772 return false; 773 } 774 } 775 776 return result.Succeeded(); 777 } 778 }; 779 780 #pragma mark CommandObjectCommandsUnalias 781 //------------------------------------------------------------------------- 782 // CommandObjectCommandsUnalias 783 //------------------------------------------------------------------------- 784 785 class CommandObjectCommandsUnalias : public CommandObjectParsed 786 { 787 public: 788 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) : 789 CommandObjectParsed(interpreter, 790 "command unalias", 791 "Allow the user to remove/delete a user-defined command abbreviation.", 792 nullptr) 793 { 794 CommandArgumentEntry arg; 795 CommandArgumentData alias_arg; 796 797 // Define the first (and only) variant of this arg. 798 alias_arg.arg_type = eArgTypeAliasName; 799 alias_arg.arg_repetition = eArgRepeatPlain; 800 801 // There is only one variant this argument could be; put it into the argument entry. 802 arg.push_back (alias_arg); 803 804 // Push the data for the first argument into the m_arguments vector. 805 m_arguments.push_back (arg); 806 } 807 808 ~CommandObjectCommandsUnalias() override = default; 809 810 protected: 811 bool 812 DoExecute (Args& args, CommandReturnObject &result) override 813 { 814 CommandObject::CommandMap::iterator pos; 815 CommandObject *cmd_obj; 816 817 if (args.GetArgumentCount() != 0) 818 { 819 const char *command_name = args.GetArgumentAtIndex(0); 820 cmd_obj = m_interpreter.GetCommandObject(command_name); 821 if (cmd_obj) 822 { 823 if (m_interpreter.CommandExists (command_name)) 824 { 825 if (cmd_obj->IsRemovable()) 826 { 827 result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n", 828 command_name); 829 } 830 else 831 { 832 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", 833 command_name); 834 } 835 result.SetStatus (eReturnStatusFailed); 836 } 837 else 838 { 839 if (!m_interpreter.RemoveAlias(command_name)) 840 { 841 if (m_interpreter.AliasExists (command_name)) 842 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n", 843 command_name); 844 else 845 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name); 846 result.SetStatus (eReturnStatusFailed); 847 } 848 else 849 result.SetStatus (eReturnStatusSuccessFinishNoResult); 850 } 851 } 852 else 853 { 854 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a " 855 "current list of commands.\n", 856 command_name); 857 result.SetStatus (eReturnStatusFailed); 858 } 859 } 860 else 861 { 862 result.AppendError ("must call 'unalias' with a valid alias"); 863 result.SetStatus (eReturnStatusFailed); 864 } 865 866 return result.Succeeded(); 867 } 868 }; 869 870 #pragma mark CommandObjectCommandsDelete 871 //------------------------------------------------------------------------- 872 // CommandObjectCommandsDelete 873 //------------------------------------------------------------------------- 874 875 class CommandObjectCommandsDelete : public CommandObjectParsed 876 { 877 public: 878 CommandObjectCommandsDelete (CommandInterpreter &interpreter) : 879 CommandObjectParsed(interpreter, 880 "command delete", 881 "Allow the user to delete user-defined regular expression, python or multi-word commands.", 882 nullptr) 883 { 884 CommandArgumentEntry arg; 885 CommandArgumentData alias_arg; 886 887 // Define the first (and only) variant of this arg. 888 alias_arg.arg_type = eArgTypeCommandName; 889 alias_arg.arg_repetition = eArgRepeatPlain; 890 891 // There is only one variant this argument could be; put it into the argument entry. 892 arg.push_back (alias_arg); 893 894 // Push the data for the first argument into the m_arguments vector. 895 m_arguments.push_back (arg); 896 } 897 898 ~CommandObjectCommandsDelete() override = default; 899 900 protected: 901 bool 902 DoExecute (Args& args, CommandReturnObject &result) override 903 { 904 CommandObject::CommandMap::iterator pos; 905 906 if (args.GetArgumentCount() != 0) 907 { 908 const char *command_name = args.GetArgumentAtIndex(0); 909 if (m_interpreter.CommandExists (command_name)) 910 { 911 if (m_interpreter.RemoveCommand (command_name)) 912 { 913 result.SetStatus (eReturnStatusSuccessFinishNoResult); 914 } 915 else 916 { 917 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", 918 command_name); 919 result.SetStatus (eReturnStatusFailed); 920 } 921 } 922 else 923 { 924 StreamString error_msg_stream; 925 const bool generate_apropos = true; 926 const bool generate_type_lookup = false; 927 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, 928 command_name, 929 nullptr, 930 nullptr, 931 generate_apropos, 932 generate_type_lookup); 933 result.AppendErrorWithFormat ("%s", error_msg_stream.GetData()); 934 result.SetStatus (eReturnStatusFailed); 935 } 936 } 937 else 938 { 939 result.AppendErrorWithFormat ("must call '%s' with one or more valid user defined regular expression, python or multi-word command names", GetCommandName ()); 940 result.SetStatus (eReturnStatusFailed); 941 } 942 943 return result.Succeeded(); 944 } 945 }; 946 947 //------------------------------------------------------------------------- 948 // CommandObjectCommandsAddRegex 949 //------------------------------------------------------------------------- 950 #pragma mark CommandObjectCommandsAddRegex 951 952 class CommandObjectCommandsAddRegex : 953 public CommandObjectParsed, 954 public IOHandlerDelegateMultiline 955 { 956 public: 957 CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) : 958 CommandObjectParsed (interpreter, 959 "command regex", 960 "Allow the user to create a regular expression command.", 961 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 962 IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand), 963 m_options (interpreter) 964 { 965 SetHelpLong(R"( 966 )" "This command allows the user to create powerful regular expression commands \ 967 with substitutions. The regular expressions and substitutions are specified \ 968 using the regular expression substitution format of:" R"( 969 970 s/<regex>/<subst>/ 971 972 )" "<regex> is a regular expression that can use parenthesis to capture regular \ 973 expression input and substitute the captured matches in the output using %1 \ 974 for the first match, %2 for the second, and so on." R"( 975 976 )" "The regular expressions can all be specified on the command line if more than \ 977 one argument is provided. If just the command name is provided on the command \ 978 line, then the regular expressions and substitutions can be entered on separate \ 979 lines, followed by an empty line to terminate the command definition." R"( 980 981 EXAMPLES 982 983 )" "The following example will define a regular expression command named 'f' that \ 984 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 985 a number follows 'f':" R"( 986 987 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')" 988 ); 989 } 990 991 ~CommandObjectCommandsAddRegex() override = default; 992 993 protected: 994 void 995 IOHandlerActivated (IOHandler &io_handler) override 996 { 997 StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 998 if (output_sp) 999 { 1000 output_sp->PutCString("Enter one of more sed substitution commands in the form: 's/<regex>/<subst>/'.\nTerminate the substitution list with an empty line.\n"); 1001 output_sp->Flush(); 1002 } 1003 } 1004 1005 void 1006 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 1007 { 1008 io_handler.SetIsDone(true); 1009 if (m_regex_cmd_ap) 1010 { 1011 StringList lines; 1012 if (lines.SplitIntoLines (data)) 1013 { 1014 const size_t num_lines = lines.GetSize(); 1015 bool check_only = false; 1016 for (size_t i=0; i<num_lines; ++i) 1017 { 1018 llvm::StringRef bytes_strref (lines[i]); 1019 Error error = AppendRegexSubstitution (bytes_strref, check_only); 1020 if (error.Fail()) 1021 { 1022 if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) 1023 { 1024 StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream(); 1025 out_stream->Printf("error: %s\n", error.AsCString()); 1026 } 1027 } 1028 } 1029 } 1030 if (m_regex_cmd_ap->HasRegexEntries()) 1031 { 1032 CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); 1033 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1034 } 1035 } 1036 } 1037 1038 bool 1039 DoExecute (Args& command, CommandReturnObject &result) override 1040 { 1041 const size_t argc = command.GetArgumentCount(); 1042 if (argc == 0) 1043 { 1044 result.AppendError ("usage: 'command regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 1045 result.SetStatus (eReturnStatusFailed); 1046 } 1047 else 1048 { 1049 Error error; 1050 const char *name = command.GetArgumentAtIndex(0); 1051 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter, 1052 name, 1053 m_options.GetHelp (), 1054 m_options.GetSyntax (), 1055 10, 1056 0, 1057 true)); 1058 1059 if (argc == 1) 1060 { 1061 Debugger &debugger = m_interpreter.GetDebugger(); 1062 bool color_prompt = debugger.GetUseColor(); 1063 const bool multiple_lines = true; // Get multiple lines 1064 IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger, 1065 IOHandler::Type::Other, 1066 "lldb-regex", // Name of input reader for history 1067 "> ", // Prompt 1068 nullptr, // Continuation prompt 1069 multiple_lines, 1070 color_prompt, 1071 0, // Don't show line numbers 1072 *this)); 1073 1074 if (io_handler_sp) 1075 { 1076 debugger.PushIOHandler(io_handler_sp); 1077 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1078 } 1079 } 1080 else 1081 { 1082 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) 1083 { 1084 llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx)); 1085 bool check_only = false; 1086 error = AppendRegexSubstitution (arg_strref, check_only); 1087 if (error.Fail()) 1088 break; 1089 } 1090 1091 if (error.Success()) 1092 { 1093 AddRegexCommandToInterpreter(); 1094 } 1095 } 1096 if (error.Fail()) 1097 { 1098 result.AppendError (error.AsCString()); 1099 result.SetStatus (eReturnStatusFailed); 1100 } 1101 } 1102 1103 return result.Succeeded(); 1104 } 1105 1106 Error 1107 AppendRegexSubstitution (const llvm::StringRef ®ex_sed, bool check_only) 1108 { 1109 Error error; 1110 1111 if (!m_regex_cmd_ap) 1112 { 1113 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'", 1114 (int)regex_sed.size(), 1115 regex_sed.data()); 1116 return error; 1117 } 1118 1119 size_t regex_sed_size = regex_sed.size(); 1120 1121 if (regex_sed_size <= 1) 1122 { 1123 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'", 1124 (int)regex_sed.size(), 1125 regex_sed.data()); 1126 return error; 1127 } 1128 1129 if (regex_sed[0] != 's') 1130 { 1131 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'", 1132 (int)regex_sed.size(), 1133 regex_sed.data()); 1134 return error; 1135 } 1136 const size_t first_separator_char_pos = 1; 1137 // use the char that follows 's' as the regex separator character 1138 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 1139 const char separator_char = regex_sed[first_separator_char_pos]; 1140 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1); 1141 1142 if (second_separator_char_pos == std::string::npos) 1143 { 1144 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'", 1145 separator_char, 1146 (int)(regex_sed.size() - first_separator_char_pos - 1), 1147 regex_sed.data() + (first_separator_char_pos + 1), 1148 (int)regex_sed.size(), 1149 regex_sed.data()); 1150 return error; 1151 } 1152 1153 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1); 1154 1155 if (third_separator_char_pos == std::string::npos) 1156 { 1157 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'", 1158 separator_char, 1159 (int)(regex_sed.size() - second_separator_char_pos - 1), 1160 regex_sed.data() + (second_separator_char_pos + 1), 1161 (int)regex_sed.size(), 1162 regex_sed.data()); 1163 return error; 1164 } 1165 1166 if (third_separator_char_pos != regex_sed_size - 1) 1167 { 1168 // Make sure that everything that follows the last regex 1169 // separator char 1170 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos) 1171 { 1172 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'", 1173 (int)third_separator_char_pos + 1, 1174 regex_sed.data(), 1175 (int)(regex_sed.size() - third_separator_char_pos - 1), 1176 regex_sed.data() + (third_separator_char_pos + 1)); 1177 return error; 1178 } 1179 } 1180 else if (first_separator_char_pos + 1 == second_separator_char_pos) 1181 { 1182 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1183 separator_char, 1184 separator_char, 1185 separator_char, 1186 (int)regex_sed.size(), 1187 regex_sed.data()); 1188 return error; 1189 } 1190 else if (second_separator_char_pos + 1 == third_separator_char_pos) 1191 { 1192 error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1193 separator_char, 1194 separator_char, 1195 separator_char, 1196 (int)regex_sed.size(), 1197 regex_sed.data()); 1198 return error; 1199 } 1200 1201 if (!check_only) 1202 { 1203 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1)); 1204 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1)); 1205 m_regex_cmd_ap->AddRegexCommand (regex.c_str(), 1206 subst.c_str()); 1207 } 1208 return error; 1209 } 1210 1211 void 1212 AddRegexCommandToInterpreter() 1213 { 1214 if (m_regex_cmd_ap) 1215 { 1216 if (m_regex_cmd_ap->HasRegexEntries()) 1217 { 1218 CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); 1219 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1220 } 1221 } 1222 } 1223 1224 private: 1225 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; 1226 1227 class CommandOptions : public Options 1228 { 1229 public: 1230 CommandOptions (CommandInterpreter &interpreter) : 1231 Options (interpreter) 1232 { 1233 } 1234 1235 ~CommandOptions() override = default; 1236 1237 Error 1238 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1239 { 1240 Error error; 1241 const int short_option = m_getopt_table[option_idx].val; 1242 1243 switch (short_option) 1244 { 1245 case 'h': 1246 m_help.assign (option_arg); 1247 break; 1248 case 's': 1249 m_syntax.assign (option_arg); 1250 break; 1251 default: 1252 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1253 break; 1254 } 1255 1256 return error; 1257 } 1258 1259 void 1260 OptionParsingStarting () override 1261 { 1262 m_help.clear(); 1263 m_syntax.clear(); 1264 } 1265 1266 const OptionDefinition* 1267 GetDefinitions () override 1268 { 1269 return g_option_table; 1270 } 1271 1272 // Options table: Required for subclasses of Options. 1273 1274 static OptionDefinition g_option_table[]; 1275 1276 const char * 1277 GetHelp() 1278 { 1279 return (m_help.empty() ? nullptr : m_help.c_str()); 1280 } 1281 1282 const char * 1283 GetSyntax () 1284 { 1285 return (m_syntax.empty() ? nullptr : m_syntax.c_str()); 1286 } 1287 1288 protected: 1289 // Instance variables to hold the values for command options. 1290 1291 std::string m_help; 1292 std::string m_syntax; 1293 }; 1294 1295 Options * 1296 GetOptions () override 1297 { 1298 return &m_options; 1299 } 1300 1301 CommandOptions m_options; 1302 }; 1303 1304 OptionDefinition 1305 CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = 1306 { 1307 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command."}, 1308 { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."}, 1309 { 0 , false, nullptr , 0 , 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr } 1310 }; 1311 1312 class CommandObjectPythonFunction : public CommandObjectRaw 1313 { 1314 public: 1315 CommandObjectPythonFunction (CommandInterpreter &interpreter, 1316 std::string name, 1317 std::string funct, 1318 std::string help, 1319 ScriptedCommandSynchronicity synch) : 1320 CommandObjectRaw(interpreter, 1321 name.c_str(), 1322 nullptr, 1323 nullptr), 1324 m_function_name(funct), 1325 m_synchro(synch), 1326 m_fetched_help_long(false) 1327 { 1328 if (!help.empty()) 1329 SetHelp(help.c_str()); 1330 else 1331 { 1332 StreamString stream; 1333 stream.Printf("For more information run 'help %s'",name.c_str()); 1334 SetHelp(stream.GetData()); 1335 } 1336 } 1337 1338 ~CommandObjectPythonFunction() override = default; 1339 1340 bool 1341 IsRemovable () const override 1342 { 1343 return true; 1344 } 1345 1346 const std::string& 1347 GetFunctionName () 1348 { 1349 return m_function_name; 1350 } 1351 1352 ScriptedCommandSynchronicity 1353 GetSynchronicity () 1354 { 1355 return m_synchro; 1356 } 1357 1358 const char * 1359 GetHelpLong () override 1360 { 1361 if (!m_fetched_help_long) 1362 { 1363 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1364 if (scripter) 1365 { 1366 std::string docstring; 1367 m_fetched_help_long = scripter->GetDocumentationForItem(m_function_name.c_str(),docstring); 1368 if (!docstring.empty()) 1369 SetHelpLong(docstring); 1370 } 1371 } 1372 return CommandObjectRaw::GetHelpLong(); 1373 } 1374 1375 protected: 1376 bool 1377 DoExecute (const char *raw_command_line, CommandReturnObject &result) override 1378 { 1379 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1380 1381 Error error; 1382 1383 result.SetStatus(eReturnStatusInvalid); 1384 1385 if (!scripter || !scripter->RunScriptBasedCommand(m_function_name.c_str(), 1386 raw_command_line, 1387 m_synchro, 1388 result, 1389 error, 1390 m_exe_ctx)) 1391 { 1392 result.AppendError(error.AsCString()); 1393 result.SetStatus(eReturnStatusFailed); 1394 } 1395 else 1396 { 1397 // Don't change the status if the command already set it... 1398 if (result.GetStatus() == eReturnStatusInvalid) 1399 { 1400 if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0') 1401 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1402 else 1403 result.SetStatus(eReturnStatusSuccessFinishResult); 1404 } 1405 } 1406 1407 return result.Succeeded(); 1408 } 1409 1410 private: 1411 std::string m_function_name; 1412 ScriptedCommandSynchronicity m_synchro; 1413 bool m_fetched_help_long; 1414 }; 1415 1416 class CommandObjectScriptingObject : public CommandObjectRaw 1417 { 1418 public: 1419 CommandObjectScriptingObject (CommandInterpreter &interpreter, 1420 std::string name, 1421 StructuredData::GenericSP cmd_obj_sp, 1422 ScriptedCommandSynchronicity synch) : 1423 CommandObjectRaw(interpreter, 1424 name.c_str(), 1425 nullptr, 1426 nullptr), 1427 m_cmd_obj_sp(cmd_obj_sp), 1428 m_synchro(synch), 1429 m_fetched_help_short(false), 1430 m_fetched_help_long(false) 1431 { 1432 StreamString stream; 1433 stream.Printf("For more information run 'help %s'",name.c_str()); 1434 SetHelp(stream.GetData()); 1435 if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter()) 1436 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 1437 } 1438 1439 ~CommandObjectScriptingObject() override = default; 1440 1441 bool 1442 IsRemovable () const override 1443 { 1444 return true; 1445 } 1446 1447 StructuredData::GenericSP 1448 GetImplementingObject () 1449 { 1450 return m_cmd_obj_sp; 1451 } 1452 1453 ScriptedCommandSynchronicity 1454 GetSynchronicity () 1455 { 1456 return m_synchro; 1457 } 1458 1459 const char * 1460 GetHelp () override 1461 { 1462 if (!m_fetched_help_short) 1463 { 1464 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1465 if (scripter) 1466 { 1467 std::string docstring; 1468 m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring); 1469 if (!docstring.empty()) 1470 SetHelp(docstring); 1471 } 1472 } 1473 return CommandObjectRaw::GetHelp(); 1474 } 1475 1476 const char * 1477 GetHelpLong () override 1478 { 1479 if (!m_fetched_help_long) 1480 { 1481 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1482 if (scripter) 1483 { 1484 std::string docstring; 1485 m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring); 1486 if (!docstring.empty()) 1487 SetHelpLong(docstring); 1488 } 1489 } 1490 return CommandObjectRaw::GetHelpLong(); 1491 } 1492 1493 protected: 1494 bool 1495 DoExecute (const char *raw_command_line, CommandReturnObject &result) override 1496 { 1497 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1498 1499 Error error; 1500 1501 result.SetStatus(eReturnStatusInvalid); 1502 1503 if (!scripter || !scripter->RunScriptBasedCommand(m_cmd_obj_sp, 1504 raw_command_line, 1505 m_synchro, 1506 result, 1507 error, 1508 m_exe_ctx)) 1509 { 1510 result.AppendError(error.AsCString()); 1511 result.SetStatus(eReturnStatusFailed); 1512 } 1513 else 1514 { 1515 // Don't change the status if the command already set it... 1516 if (result.GetStatus() == eReturnStatusInvalid) 1517 { 1518 if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0') 1519 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1520 else 1521 result.SetStatus(eReturnStatusSuccessFinishResult); 1522 } 1523 } 1524 1525 return result.Succeeded(); 1526 } 1527 1528 private: 1529 StructuredData::GenericSP m_cmd_obj_sp; 1530 ScriptedCommandSynchronicity m_synchro; 1531 bool m_fetched_help_short: 1; 1532 bool m_fetched_help_long: 1; 1533 }; 1534 1535 //------------------------------------------------------------------------- 1536 // CommandObjectCommandsScriptImport 1537 //------------------------------------------------------------------------- 1538 1539 class CommandObjectCommandsScriptImport : public CommandObjectParsed 1540 { 1541 public: 1542 CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) : 1543 CommandObjectParsed(interpreter, 1544 "command script import", 1545 "Import a scripting module in LLDB.", 1546 nullptr), 1547 m_options(interpreter) 1548 { 1549 CommandArgumentEntry arg1; 1550 CommandArgumentData cmd_arg; 1551 1552 // Define the first (and only) variant of this arg. 1553 cmd_arg.arg_type = eArgTypeFilename; 1554 cmd_arg.arg_repetition = eArgRepeatPlus; 1555 1556 // There is only one variant this argument could be; put it into the argument entry. 1557 arg1.push_back (cmd_arg); 1558 1559 // Push the data for the first argument into the m_arguments vector. 1560 m_arguments.push_back (arg1); 1561 } 1562 1563 ~CommandObjectCommandsScriptImport() override = default; 1564 1565 int 1566 HandleArgumentCompletion (Args &input, 1567 int &cursor_index, 1568 int &cursor_char_position, 1569 OptionElementVector &opt_element_vector, 1570 int match_start_point, 1571 int max_return_elements, 1572 bool &word_complete, 1573 StringList &matches) override 1574 { 1575 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 1576 completion_str.erase (cursor_char_position); 1577 1578 CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter, 1579 CommandCompletions::eDiskFileCompletion, 1580 completion_str.c_str(), 1581 match_start_point, 1582 max_return_elements, 1583 nullptr, 1584 word_complete, 1585 matches); 1586 return matches.GetSize(); 1587 } 1588 1589 Options * 1590 GetOptions () override 1591 { 1592 return &m_options; 1593 } 1594 1595 protected: 1596 class CommandOptions : public Options 1597 { 1598 public: 1599 CommandOptions (CommandInterpreter &interpreter) : 1600 Options (interpreter) 1601 { 1602 } 1603 1604 ~CommandOptions() override = default; 1605 1606 Error 1607 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1608 { 1609 Error error; 1610 const int short_option = m_getopt_table[option_idx].val; 1611 1612 switch (short_option) 1613 { 1614 case 'r': 1615 m_allow_reload = true; 1616 break; 1617 default: 1618 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1619 break; 1620 } 1621 1622 return error; 1623 } 1624 1625 void 1626 OptionParsingStarting () override 1627 { 1628 m_allow_reload = true; 1629 } 1630 1631 const OptionDefinition* 1632 GetDefinitions () override 1633 { 1634 return g_option_table; 1635 } 1636 1637 // Options table: Required for subclasses of Options. 1638 1639 static OptionDefinition g_option_table[]; 1640 1641 // Instance variables to hold the values for command options. 1642 1643 bool m_allow_reload; 1644 }; 1645 1646 bool 1647 DoExecute (Args& command, CommandReturnObject &result) override 1648 { 1649 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) 1650 { 1651 result.AppendError ("only scripting language supported for module importing is currently Python"); 1652 result.SetStatus (eReturnStatusFailed); 1653 return false; 1654 } 1655 1656 size_t argc = command.GetArgumentCount(); 1657 if (0 == argc) 1658 { 1659 result.AppendError("command script import needs one or more arguments"); 1660 result.SetStatus (eReturnStatusFailed); 1661 return false; 1662 } 1663 1664 for (size_t i = 0; 1665 i < argc; 1666 i++) 1667 { 1668 std::string path = command.GetArgumentAtIndex(i); 1669 Error error; 1670 1671 const bool init_session = true; 1672 // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that 1673 // commands won't ever be recursively invoked, but it's actually possible to craft 1674 // a Python script that does other "command script imports" in __lldb_init_module 1675 // the real fix is to have recursive commands possible with a CommandInvocation object 1676 // separate from the CommandObject itself, so that recursive command invocations 1677 // won't stomp on each other (wrt to execution contents, options, and more) 1678 m_exe_ctx.Clear(); 1679 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(), 1680 m_options.m_allow_reload, 1681 init_session, 1682 error)) 1683 { 1684 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1685 } 1686 else 1687 { 1688 result.AppendErrorWithFormat("module importing failed: %s", error.AsCString()); 1689 result.SetStatus (eReturnStatusFailed); 1690 } 1691 } 1692 1693 return result.Succeeded(); 1694 } 1695 1696 CommandOptions m_options; 1697 }; 1698 1699 OptionDefinition 1700 CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] = 1701 { 1702 { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."}, 1703 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1704 }; 1705 1706 //------------------------------------------------------------------------- 1707 // CommandObjectCommandsScriptAdd 1708 //------------------------------------------------------------------------- 1709 1710 class CommandObjectCommandsScriptAdd : 1711 public CommandObjectParsed, 1712 public IOHandlerDelegateMultiline 1713 { 1714 public: 1715 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) : 1716 CommandObjectParsed(interpreter, 1717 "command script add", 1718 "Add a scripted function as an LLDB command.", 1719 nullptr), 1720 IOHandlerDelegateMultiline ("DONE"), 1721 m_options (interpreter) 1722 { 1723 CommandArgumentEntry arg1; 1724 CommandArgumentData cmd_arg; 1725 1726 // Define the first (and only) variant of this arg. 1727 cmd_arg.arg_type = eArgTypeCommandName; 1728 cmd_arg.arg_repetition = eArgRepeatPlain; 1729 1730 // There is only one variant this argument could be; put it into the argument entry. 1731 arg1.push_back (cmd_arg); 1732 1733 // Push the data for the first argument into the m_arguments vector. 1734 m_arguments.push_back (arg1); 1735 } 1736 1737 ~CommandObjectCommandsScriptAdd() override = default; 1738 1739 Options * 1740 GetOptions () override 1741 { 1742 return &m_options; 1743 } 1744 1745 protected: 1746 class CommandOptions : public Options 1747 { 1748 public: 1749 CommandOptions (CommandInterpreter &interpreter) : 1750 Options (interpreter), 1751 m_class_name(), 1752 m_funct_name(), 1753 m_short_help(), 1754 m_synchronicity(eScriptedCommandSynchronicitySynchronous) 1755 { 1756 } 1757 1758 ~CommandOptions() override = default; 1759 1760 Error 1761 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1762 { 1763 Error error; 1764 const int short_option = m_getopt_table[option_idx].val; 1765 1766 switch (short_option) 1767 { 1768 case 'f': 1769 if (option_arg) 1770 m_funct_name.assign(option_arg); 1771 break; 1772 case 'c': 1773 if (option_arg) 1774 m_class_name.assign(option_arg); 1775 break; 1776 case 'h': 1777 if (option_arg) 1778 m_short_help.assign(option_arg); 1779 break; 1780 case 's': 1781 m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); 1782 if (!error.Success()) 1783 error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg); 1784 break; 1785 default: 1786 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1787 break; 1788 } 1789 1790 return error; 1791 } 1792 1793 void 1794 OptionParsingStarting () override 1795 { 1796 m_class_name.clear(); 1797 m_funct_name.clear(); 1798 m_short_help.clear(); 1799 m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1800 } 1801 1802 const OptionDefinition* 1803 GetDefinitions () override 1804 { 1805 return g_option_table; 1806 } 1807 1808 // Options table: Required for subclasses of Options. 1809 1810 static OptionDefinition g_option_table[]; 1811 1812 // Instance variables to hold the values for command options. 1813 1814 std::string m_class_name; 1815 std::string m_funct_name; 1816 std::string m_short_help; 1817 ScriptedCommandSynchronicity m_synchronicity; 1818 }; 1819 1820 void 1821 IOHandlerActivated (IOHandler &io_handler) override 1822 { 1823 StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 1824 if (output_sp) 1825 { 1826 output_sp->PutCString(g_python_command_instructions); 1827 output_sp->Flush(); 1828 } 1829 } 1830 1831 1832 void 1833 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 1834 { 1835 StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 1836 1837 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1838 if (interpreter) 1839 { 1840 1841 StringList lines; 1842 lines.SplitIntoLines(data); 1843 if (lines.GetSize() > 0) 1844 { 1845 std::string funct_name_str; 1846 if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str)) 1847 { 1848 if (funct_name_str.empty()) 1849 { 1850 error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n"); 1851 error_sp->Flush(); 1852 } 1853 else 1854 { 1855 // everything should be fine now, let's add this alias 1856 1857 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter, 1858 m_cmd_name, 1859 funct_name_str.c_str(), 1860 m_short_help, 1861 m_synchronicity)); 1862 1863 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true)) 1864 { 1865 error_sp->Printf ("error: unable to add selected command, didn't add python command.\n"); 1866 error_sp->Flush(); 1867 } 1868 } 1869 } 1870 else 1871 { 1872 error_sp->Printf ("error: unable to create function, didn't add python command.\n"); 1873 error_sp->Flush(); 1874 } 1875 } 1876 else 1877 { 1878 error_sp->Printf ("error: empty function, didn't add python command.\n"); 1879 error_sp->Flush(); 1880 } 1881 } 1882 else 1883 { 1884 error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); 1885 error_sp->Flush(); 1886 } 1887 1888 io_handler.SetIsDone(true); 1889 } 1890 1891 protected: 1892 bool 1893 DoExecute (Args& command, CommandReturnObject &result) override 1894 { 1895 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) 1896 { 1897 result.AppendError ("only scripting language supported for scripted commands is currently Python"); 1898 result.SetStatus (eReturnStatusFailed); 1899 return false; 1900 } 1901 1902 size_t argc = command.GetArgumentCount(); 1903 1904 if (argc != 1) 1905 { 1906 result.AppendError ("'command script add' requires one argument"); 1907 result.SetStatus (eReturnStatusFailed); 1908 return false; 1909 } 1910 1911 // Store the options in case we get multi-line input 1912 m_cmd_name = command.GetArgumentAtIndex(0); 1913 m_short_help.assign(m_options.m_short_help); 1914 m_synchronicity = m_options.m_synchronicity; 1915 1916 if (m_options.m_class_name.empty()) 1917 { 1918 if (m_options.m_funct_name.empty()) 1919 { 1920 m_interpreter.GetPythonCommandsFromIOHandler(" ", // Prompt 1921 *this, // IOHandlerDelegate 1922 true, // Run IOHandler in async mode 1923 nullptr); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 1924 } 1925 else 1926 { 1927 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, 1928 m_cmd_name, 1929 m_options.m_funct_name, 1930 m_options.m_short_help, 1931 m_synchronicity)); 1932 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) 1933 { 1934 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1935 } 1936 else 1937 { 1938 result.AppendError("cannot add command"); 1939 result.SetStatus (eReturnStatusFailed); 1940 } 1941 } 1942 } 1943 else 1944 { 1945 ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter(); 1946 if (!interpreter) 1947 { 1948 result.AppendError("cannot find ScriptInterpreter"); 1949 result.SetStatus(eReturnStatusFailed); 1950 return false; 1951 } 1952 1953 auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str()); 1954 if (!cmd_obj_sp) 1955 { 1956 result.AppendError("cannot create helper object"); 1957 result.SetStatus(eReturnStatusFailed); 1958 return false; 1959 } 1960 1961 CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter, 1962 m_cmd_name, 1963 cmd_obj_sp, 1964 m_synchronicity)); 1965 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) 1966 { 1967 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1968 } 1969 else 1970 { 1971 result.AppendError("cannot add command"); 1972 result.SetStatus (eReturnStatusFailed); 1973 } 1974 } 1975 1976 return result.Succeeded(); 1977 } 1978 1979 CommandOptions m_options; 1980 std::string m_cmd_name; 1981 std::string m_short_help; 1982 ScriptedCommandSynchronicity m_synchronicity; 1983 }; 1984 1985 static OptionEnumValueElement g_script_synchro_type[] = 1986 { 1987 { eScriptedCommandSynchronicitySynchronous, "synchronous", "Run synchronous"}, 1988 { eScriptedCommandSynchronicityAsynchronous, "asynchronous", "Run asynchronous"}, 1989 { eScriptedCommandSynchronicityCurrentValue, "current", "Do not alter current setting"}, 1990 { 0, nullptr, nullptr } 1991 }; 1992 1993 OptionDefinition 1994 CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = 1995 { 1996 { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, 1997 { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name."}, 1998 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command."}, 1999 { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, 2000 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2001 }; 2002 2003 //------------------------------------------------------------------------- 2004 // CommandObjectCommandsScriptList 2005 //------------------------------------------------------------------------- 2006 2007 class CommandObjectCommandsScriptList : public CommandObjectParsed 2008 { 2009 public: 2010 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) : 2011 CommandObjectParsed(interpreter, 2012 "command script list", 2013 "List defined scripted commands.", 2014 nullptr) 2015 { 2016 } 2017 2018 ~CommandObjectCommandsScriptList() override = default; 2019 2020 bool 2021 DoExecute (Args& command, CommandReturnObject &result) override 2022 { 2023 m_interpreter.GetHelp(result, 2024 CommandInterpreter::eCommandTypesUserDef); 2025 2026 result.SetStatus (eReturnStatusSuccessFinishResult); 2027 2028 return true; 2029 } 2030 }; 2031 2032 //------------------------------------------------------------------------- 2033 // CommandObjectCommandsScriptClear 2034 //------------------------------------------------------------------------- 2035 2036 class CommandObjectCommandsScriptClear : public CommandObjectParsed 2037 { 2038 public: 2039 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) : 2040 CommandObjectParsed(interpreter, 2041 "command script clear", 2042 "Delete all scripted commands.", 2043 nullptr) 2044 { 2045 } 2046 2047 ~CommandObjectCommandsScriptClear() override = default; 2048 2049 protected: 2050 bool 2051 DoExecute (Args& command, CommandReturnObject &result) override 2052 { 2053 m_interpreter.RemoveAllUser(); 2054 2055 result.SetStatus (eReturnStatusSuccessFinishResult); 2056 2057 return true; 2058 } 2059 }; 2060 2061 //------------------------------------------------------------------------- 2062 // CommandObjectCommandsScriptDelete 2063 //------------------------------------------------------------------------- 2064 2065 class CommandObjectCommandsScriptDelete : public CommandObjectParsed 2066 { 2067 public: 2068 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) : 2069 CommandObjectParsed(interpreter, 2070 "command script delete", 2071 "Delete a scripted command.", 2072 nullptr) 2073 { 2074 CommandArgumentEntry arg1; 2075 CommandArgumentData cmd_arg; 2076 2077 // Define the first (and only) variant of this arg. 2078 cmd_arg.arg_type = eArgTypeCommandName; 2079 cmd_arg.arg_repetition = eArgRepeatPlain; 2080 2081 // There is only one variant this argument could be; put it into the argument entry. 2082 arg1.push_back (cmd_arg); 2083 2084 // Push the data for the first argument into the m_arguments vector. 2085 m_arguments.push_back (arg1); 2086 } 2087 2088 ~CommandObjectCommandsScriptDelete() override = default; 2089 2090 protected: 2091 bool 2092 DoExecute (Args& command, CommandReturnObject &result) override 2093 { 2094 2095 size_t argc = command.GetArgumentCount(); 2096 2097 if (argc != 1) 2098 { 2099 result.AppendError ("'command script delete' requires one argument"); 2100 result.SetStatus (eReturnStatusFailed); 2101 return false; 2102 } 2103 2104 const char* cmd_name = command.GetArgumentAtIndex(0); 2105 2106 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name)) 2107 { 2108 m_interpreter.RemoveUser(cmd_name); 2109 result.SetStatus (eReturnStatusSuccessFinishResult); 2110 } 2111 else 2112 { 2113 result.AppendErrorWithFormat ("command %s not found", cmd_name); 2114 result.SetStatus (eReturnStatusFailed); 2115 } 2116 2117 return result.Succeeded(); 2118 } 2119 }; 2120 2121 #pragma mark CommandObjectMultiwordCommandsScript 2122 2123 //------------------------------------------------------------------------- 2124 // CommandObjectMultiwordCommandsScript 2125 //------------------------------------------------------------------------- 2126 2127 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword 2128 { 2129 public: 2130 CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) : 2131 CommandObjectMultiword (interpreter, 2132 "command script", 2133 "A set of commands for managing or customizing script commands.", 2134 "command script <subcommand> [<subcommand-options>]") 2135 { 2136 LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter))); 2137 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); 2138 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); 2139 LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter))); 2140 LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); 2141 } 2142 2143 ~CommandObjectMultiwordCommandsScript() override = default; 2144 }; 2145 2146 #pragma mark CommandObjectMultiwordCommands 2147 2148 //------------------------------------------------------------------------- 2149 // CommandObjectMultiwordCommands 2150 //------------------------------------------------------------------------- 2151 2152 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) : 2153 CommandObjectMultiword (interpreter, 2154 "command", 2155 "A set of commands for managing or customizing the debugger commands.", 2156 "command <subcommand> [<subcommand-options>]") 2157 { 2158 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter))); 2159 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter))); 2160 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); 2161 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsDelete (interpreter))); 2162 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter))); 2163 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); 2164 LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter))); 2165 } 2166 2167 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 2168