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