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