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