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