1 //===-- CommandObjectSettings.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 "CommandObjectSettings.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/Interpreter/CommandCompletions.h" 19 #include "lldb/Interpreter/CommandInterpreter.h" 20 #include "lldb/Interpreter/CommandReturnObject.h" 21 #include "lldb/Interpreter/OptionValueProperties.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 //------------------------------------------------------------------------- 27 // CommandObjectSettingsSet 28 //------------------------------------------------------------------------- 29 30 class CommandObjectSettingsSet : public CommandObjectRaw { 31 public: 32 CommandObjectSettingsSet(CommandInterpreter &interpreter) 33 : CommandObjectRaw(interpreter, "settings set", 34 "Set the value of the specified debugger setting.", 35 nullptr), 36 m_options() { 37 CommandArgumentEntry arg1; 38 CommandArgumentEntry arg2; 39 CommandArgumentData var_name_arg; 40 CommandArgumentData value_arg; 41 42 // Define the first (and only) variant of this arg. 43 var_name_arg.arg_type = eArgTypeSettingVariableName; 44 var_name_arg.arg_repetition = eArgRepeatPlain; 45 46 // There is only one variant this argument could be; put it into the 47 // argument entry. 48 arg1.push_back(var_name_arg); 49 50 // Define the first (and only) variant of this arg. 51 value_arg.arg_type = eArgTypeValue; 52 value_arg.arg_repetition = eArgRepeatPlain; 53 54 // There is only one variant this argument could be; put it into the 55 // argument entry. 56 arg2.push_back(value_arg); 57 58 // Push the data for the first argument into the m_arguments vector. 59 m_arguments.push_back(arg1); 60 m_arguments.push_back(arg2); 61 62 SetHelpLong( 63 "\nWhen setting a dictionary or array variable, you can set multiple entries \ 64 at once by giving the values to the set command. For example:" 65 R"( 66 67 (lldb) settings set target.run-args value1 value2 value3 68 (lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345 69 70 (lldb) settings show target.run-args 71 [0]: 'value1' 72 [1]: 'value2' 73 [3]: 'value3' 74 (lldb) settings show target.env-vars 75 'MYPATH=~/.:/usr/bin' 76 'SOME_ENV_VAR=12345' 77 78 )" 79 "Warning: The 'set' command re-sets the entire array or dictionary. If you \ 80 just want to add, remove or update individual values (or add something to \ 81 the end), use one of the other settings sub-commands: append, replace, \ 82 insert-before or insert-after."); 83 } 84 85 ~CommandObjectSettingsSet() override = default; 86 87 // Overrides base class's behavior where WantsCompletion = 88 // !WantsRawCommandString. 89 bool WantsCompletion() override { return true; } 90 91 Options *GetOptions() override { return &m_options; } 92 93 class CommandOptions : public Options { 94 public: 95 CommandOptions() : Options(), m_global(false) {} 96 97 ~CommandOptions() override = default; 98 99 Error SetOptionValue(uint32_t option_idx, const char *option_arg, 100 ExecutionContext *execution_context) override { 101 Error error; 102 const int short_option = m_getopt_table[option_idx].val; 103 104 switch (short_option) { 105 case 'g': 106 m_global = true; 107 break; 108 default: 109 error.SetErrorStringWithFormat("unrecognized options '%c'", 110 short_option); 111 break; 112 } 113 114 return error; 115 } 116 117 void OptionParsingStarting(ExecutionContext *execution_context) override { 118 m_global = false; 119 } 120 121 const OptionDefinition *GetDefinitions() override { return g_option_table; } 122 123 // Options table: Required for subclasses of Options. 124 125 static OptionDefinition g_option_table[]; 126 127 // Instance variables to hold the values for command options. 128 129 bool m_global; 130 }; 131 132 int HandleArgumentCompletion(Args &input, int &cursor_index, 133 int &cursor_char_position, 134 OptionElementVector &opt_element_vector, 135 int match_start_point, int max_return_elements, 136 bool &word_complete, 137 StringList &matches) override { 138 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 139 cursor_char_position); 140 141 const size_t argc = input.GetArgumentCount(); 142 const char *arg = nullptr; 143 int setting_var_idx; 144 for (setting_var_idx = 1; setting_var_idx < static_cast<int>(argc); 145 ++setting_var_idx) { 146 arg = input.GetArgumentAtIndex(setting_var_idx); 147 if (arg && arg[0] != '-') 148 break; // We found our setting variable name index 149 } 150 if (cursor_index == setting_var_idx) { 151 // Attempting to complete setting variable name 152 CommandCompletions::InvokeCommonCompletionCallbacks( 153 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 154 completion_str.c_str(), match_start_point, max_return_elements, 155 nullptr, word_complete, matches); 156 } else { 157 arg = input.GetArgumentAtIndex(cursor_index); 158 159 if (arg) { 160 if (arg[0] == '-') { 161 // Complete option name 162 } else { 163 // Complete setting value 164 const char *setting_var_name = 165 input.GetArgumentAtIndex(setting_var_idx); 166 Error error; 167 lldb::OptionValueSP value_sp( 168 m_interpreter.GetDebugger().GetPropertyValue( 169 &m_exe_ctx, setting_var_name, false, error)); 170 if (value_sp) { 171 value_sp->AutoComplete(m_interpreter, completion_str.c_str(), 172 match_start_point, max_return_elements, 173 word_complete, matches); 174 } 175 } 176 } 177 } 178 return matches.GetSize(); 179 } 180 181 protected: 182 bool DoExecute(const char *command, CommandReturnObject &result) override { 183 Args cmd_args(command); 184 185 // Process possible options. 186 if (!ParseOptions(cmd_args, result)) 187 return false; 188 189 const size_t argc = cmd_args.GetArgumentCount(); 190 if ((argc < 2) && (!m_options.m_global)) { 191 result.AppendError("'settings set' takes more arguments"); 192 result.SetStatus(eReturnStatusFailed); 193 return false; 194 } 195 196 const char *var_name = cmd_args.GetArgumentAtIndex(0); 197 if ((var_name == nullptr) || (var_name[0] == '\0')) { 198 result.AppendError( 199 "'settings set' command requires a valid variable name"); 200 result.SetStatus(eReturnStatusFailed); 201 return false; 202 } 203 204 // Split the raw command into var_name and value pair. 205 llvm::StringRef raw_str(command); 206 std::string var_value_string = raw_str.split(var_name).second.str(); 207 const char *var_value_cstr = 208 Args::StripSpaces(var_value_string, true, false, false); 209 210 Error error; 211 if (m_options.m_global) { 212 error = m_interpreter.GetDebugger().SetPropertyValue( 213 nullptr, eVarSetOperationAssign, var_name, var_value_cstr); 214 } 215 216 if (error.Success()) { 217 // FIXME this is the same issue as the one in commands script import 218 // we could be setting target.load-script-from-symbol-file which would 219 // cause 220 // Python scripts to be loaded, which could run LLDB commands 221 // (e.g. settings set target.process.python-os-plugin-path) and cause a 222 // crash 223 // if we did not clear the command's exe_ctx first 224 ExecutionContext exe_ctx(m_exe_ctx); 225 m_exe_ctx.Clear(); 226 error = m_interpreter.GetDebugger().SetPropertyValue( 227 &exe_ctx, eVarSetOperationAssign, var_name, var_value_cstr); 228 } 229 230 if (error.Fail()) { 231 result.AppendError(error.AsCString()); 232 result.SetStatus(eReturnStatusFailed); 233 return false; 234 } else { 235 result.SetStatus(eReturnStatusSuccessFinishResult); 236 } 237 238 return result.Succeeded(); 239 } 240 241 private: 242 CommandOptions m_options; 243 }; 244 245 OptionDefinition CommandObjectSettingsSet::CommandOptions::g_option_table[] = { 246 // clang-format off 247 {LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Apply the new value to the global default value."}, 248 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 249 // clang-format on 250 }; 251 252 //------------------------------------------------------------------------- 253 // CommandObjectSettingsShow -- Show current values 254 //------------------------------------------------------------------------- 255 256 class CommandObjectSettingsShow : public CommandObjectParsed { 257 public: 258 CommandObjectSettingsShow(CommandInterpreter &interpreter) 259 : CommandObjectParsed(interpreter, "settings show", 260 "Show matching debugger settings and their current " 261 "values. Defaults to showing all settings.", 262 nullptr) { 263 CommandArgumentEntry arg1; 264 CommandArgumentData var_name_arg; 265 266 // Define the first (and only) variant of this arg. 267 var_name_arg.arg_type = eArgTypeSettingVariableName; 268 var_name_arg.arg_repetition = eArgRepeatOptional; 269 270 // There is only one variant this argument could be; put it into the 271 // argument entry. 272 arg1.push_back(var_name_arg); 273 274 // Push the data for the first argument into the m_arguments vector. 275 m_arguments.push_back(arg1); 276 } 277 278 ~CommandObjectSettingsShow() override = default; 279 280 int HandleArgumentCompletion(Args &input, int &cursor_index, 281 int &cursor_char_position, 282 OptionElementVector &opt_element_vector, 283 int match_start_point, int max_return_elements, 284 bool &word_complete, 285 StringList &matches) override { 286 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 287 cursor_char_position); 288 289 CommandCompletions::InvokeCommonCompletionCallbacks( 290 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 291 completion_str.c_str(), match_start_point, max_return_elements, nullptr, 292 word_complete, matches); 293 return matches.GetSize(); 294 } 295 296 protected: 297 bool DoExecute(Args &args, CommandReturnObject &result) override { 298 result.SetStatus(eReturnStatusSuccessFinishResult); 299 300 const size_t argc = args.GetArgumentCount(); 301 if (argc > 0) { 302 for (size_t i = 0; i < argc; ++i) { 303 const char *property_path = args.GetArgumentAtIndex(i); 304 305 Error error(m_interpreter.GetDebugger().DumpPropertyValue( 306 &m_exe_ctx, result.GetOutputStream(), property_path, 307 OptionValue::eDumpGroupValue)); 308 if (error.Success()) { 309 result.GetOutputStream().EOL(); 310 } else { 311 result.AppendError(error.AsCString()); 312 result.SetStatus(eReturnStatusFailed); 313 } 314 } 315 } else { 316 m_interpreter.GetDebugger().DumpAllPropertyValues( 317 &m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue); 318 } 319 320 return result.Succeeded(); 321 } 322 }; 323 324 //------------------------------------------------------------------------- 325 // CommandObjectSettingsList -- List settable variables 326 //------------------------------------------------------------------------- 327 328 class CommandObjectSettingsList : public CommandObjectParsed { 329 public: 330 CommandObjectSettingsList(CommandInterpreter &interpreter) 331 : CommandObjectParsed(interpreter, "settings list", 332 "List and describe matching debugger settings. " 333 "Defaults to all listing all settings.", 334 nullptr) { 335 CommandArgumentEntry arg; 336 CommandArgumentData var_name_arg; 337 CommandArgumentData prefix_name_arg; 338 339 // Define the first variant of this arg. 340 var_name_arg.arg_type = eArgTypeSettingVariableName; 341 var_name_arg.arg_repetition = eArgRepeatOptional; 342 343 // Define the second variant of this arg. 344 prefix_name_arg.arg_type = eArgTypeSettingPrefix; 345 prefix_name_arg.arg_repetition = eArgRepeatOptional; 346 347 arg.push_back(var_name_arg); 348 arg.push_back(prefix_name_arg); 349 350 // Push the data for the first argument into the m_arguments vector. 351 m_arguments.push_back(arg); 352 } 353 354 ~CommandObjectSettingsList() override = default; 355 356 int HandleArgumentCompletion(Args &input, int &cursor_index, 357 int &cursor_char_position, 358 OptionElementVector &opt_element_vector, 359 int match_start_point, int max_return_elements, 360 bool &word_complete, 361 StringList &matches) override { 362 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 363 cursor_char_position); 364 365 CommandCompletions::InvokeCommonCompletionCallbacks( 366 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 367 completion_str.c_str(), match_start_point, max_return_elements, nullptr, 368 word_complete, matches); 369 return matches.GetSize(); 370 } 371 372 protected: 373 bool DoExecute(Args &args, CommandReturnObject &result) override { 374 result.SetStatus(eReturnStatusSuccessFinishResult); 375 376 const bool will_modify = false; 377 const size_t argc = args.GetArgumentCount(); 378 if (argc > 0) { 379 const bool dump_qualified_name = true; 380 381 for (size_t i = 0; i < argc; ++i) { 382 const char *property_path = args.GetArgumentAtIndex(i); 383 384 const Property *property = 385 m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath( 386 &m_exe_ctx, will_modify, property_path); 387 388 if (property) { 389 property->DumpDescription(m_interpreter, result.GetOutputStream(), 0, 390 dump_qualified_name); 391 } else { 392 result.AppendErrorWithFormat("invalid property path '%s'", 393 property_path); 394 result.SetStatus(eReturnStatusFailed); 395 } 396 } 397 } else { 398 m_interpreter.GetDebugger().DumpAllDescriptions(m_interpreter, 399 result.GetOutputStream()); 400 } 401 402 return result.Succeeded(); 403 } 404 }; 405 406 //------------------------------------------------------------------------- 407 // CommandObjectSettingsRemove 408 //------------------------------------------------------------------------- 409 410 class CommandObjectSettingsRemove : public CommandObjectRaw { 411 public: 412 CommandObjectSettingsRemove(CommandInterpreter &interpreter) 413 : CommandObjectRaw(interpreter, "settings remove", 414 "Remove a value from a setting, specified by array " 415 "index or dictionary key.", 416 nullptr) { 417 CommandArgumentEntry arg1; 418 CommandArgumentEntry arg2; 419 CommandArgumentData var_name_arg; 420 CommandArgumentData index_arg; 421 CommandArgumentData key_arg; 422 423 // Define the first (and only) variant of this arg. 424 var_name_arg.arg_type = eArgTypeSettingVariableName; 425 var_name_arg.arg_repetition = eArgRepeatPlain; 426 427 // There is only one variant this argument could be; put it into the 428 // argument entry. 429 arg1.push_back(var_name_arg); 430 431 // Define the first variant of this arg. 432 index_arg.arg_type = eArgTypeSettingIndex; 433 index_arg.arg_repetition = eArgRepeatPlain; 434 435 // Define the second variant of this arg. 436 key_arg.arg_type = eArgTypeSettingKey; 437 key_arg.arg_repetition = eArgRepeatPlain; 438 439 // Push both variants into this arg 440 arg2.push_back(index_arg); 441 arg2.push_back(key_arg); 442 443 // Push the data for the first argument into the m_arguments vector. 444 m_arguments.push_back(arg1); 445 m_arguments.push_back(arg2); 446 } 447 448 ~CommandObjectSettingsRemove() override = default; 449 450 int HandleArgumentCompletion(Args &input, int &cursor_index, 451 int &cursor_char_position, 452 OptionElementVector &opt_element_vector, 453 int match_start_point, int max_return_elements, 454 bool &word_complete, 455 StringList &matches) override { 456 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 457 cursor_char_position); 458 459 // Attempting to complete variable name 460 if (cursor_index < 2) 461 CommandCompletions::InvokeCommonCompletionCallbacks( 462 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 463 completion_str.c_str(), match_start_point, max_return_elements, 464 nullptr, word_complete, matches); 465 return matches.GetSize(); 466 } 467 468 protected: 469 bool DoExecute(const char *command, CommandReturnObject &result) override { 470 result.SetStatus(eReturnStatusSuccessFinishNoResult); 471 472 Args cmd_args(command); 473 474 // Process possible options. 475 if (!ParseOptions(cmd_args, result)) 476 return false; 477 478 const size_t argc = cmd_args.GetArgumentCount(); 479 if (argc == 0) { 480 result.AppendError("'settings set' takes an array or dictionary item, or " 481 "an array followed by one or more indexes, or a " 482 "dictionary followed by one or more key names to " 483 "remove"); 484 result.SetStatus(eReturnStatusFailed); 485 return false; 486 } 487 488 const char *var_name = cmd_args.GetArgumentAtIndex(0); 489 if ((var_name == nullptr) || (var_name[0] == '\0')) { 490 result.AppendError( 491 "'settings set' command requires a valid variable name"); 492 result.SetStatus(eReturnStatusFailed); 493 return false; 494 } 495 496 // Split the raw command into var_name and value pair. 497 llvm::StringRef raw_str(command); 498 std::string var_value_string = raw_str.split(var_name).second.str(); 499 const char *var_value_cstr = 500 Args::StripSpaces(var_value_string, true, true, false); 501 502 Error error(m_interpreter.GetDebugger().SetPropertyValue( 503 &m_exe_ctx, eVarSetOperationRemove, var_name, var_value_cstr)); 504 if (error.Fail()) { 505 result.AppendError(error.AsCString()); 506 result.SetStatus(eReturnStatusFailed); 507 return false; 508 } 509 510 return result.Succeeded(); 511 } 512 }; 513 514 //------------------------------------------------------------------------- 515 // CommandObjectSettingsReplace 516 //------------------------------------------------------------------------- 517 518 class CommandObjectSettingsReplace : public CommandObjectRaw { 519 public: 520 CommandObjectSettingsReplace(CommandInterpreter &interpreter) 521 : CommandObjectRaw(interpreter, "settings replace", 522 "Replace the debugger setting value specified by " 523 "array index or dictionary key.", 524 nullptr) { 525 CommandArgumentEntry arg1; 526 CommandArgumentEntry arg2; 527 CommandArgumentEntry arg3; 528 CommandArgumentData var_name_arg; 529 CommandArgumentData index_arg; 530 CommandArgumentData key_arg; 531 CommandArgumentData value_arg; 532 533 // Define the first (and only) variant of this arg. 534 var_name_arg.arg_type = eArgTypeSettingVariableName; 535 var_name_arg.arg_repetition = eArgRepeatPlain; 536 537 // There is only one variant this argument could be; put it into the 538 // argument entry. 539 arg1.push_back(var_name_arg); 540 541 // Define the first (variant of this arg. 542 index_arg.arg_type = eArgTypeSettingIndex; 543 index_arg.arg_repetition = eArgRepeatPlain; 544 545 // Define the second (variant of this arg. 546 key_arg.arg_type = eArgTypeSettingKey; 547 key_arg.arg_repetition = eArgRepeatPlain; 548 549 // Put both variants into this arg 550 arg2.push_back(index_arg); 551 arg2.push_back(key_arg); 552 553 // Define the first (and only) variant of this arg. 554 value_arg.arg_type = eArgTypeValue; 555 value_arg.arg_repetition = eArgRepeatPlain; 556 557 // There is only one variant this argument could be; put it into the 558 // argument entry. 559 arg3.push_back(value_arg); 560 561 // Push the data for the first argument into the m_arguments vector. 562 m_arguments.push_back(arg1); 563 m_arguments.push_back(arg2); 564 m_arguments.push_back(arg3); 565 } 566 567 ~CommandObjectSettingsReplace() override = default; 568 569 // Overrides base class's behavior where WantsCompletion = 570 // !WantsRawCommandString. 571 bool WantsCompletion() override { return true; } 572 573 int HandleArgumentCompletion(Args &input, int &cursor_index, 574 int &cursor_char_position, 575 OptionElementVector &opt_element_vector, 576 int match_start_point, int max_return_elements, 577 bool &word_complete, 578 StringList &matches) override { 579 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 580 cursor_char_position); 581 582 // Attempting to complete variable name 583 if (cursor_index < 2) 584 CommandCompletions::InvokeCommonCompletionCallbacks( 585 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 586 completion_str.c_str(), match_start_point, max_return_elements, 587 nullptr, word_complete, matches); 588 589 return matches.GetSize(); 590 } 591 592 protected: 593 bool DoExecute(const char *command, CommandReturnObject &result) override { 594 result.SetStatus(eReturnStatusSuccessFinishNoResult); 595 596 Args cmd_args(command); 597 const char *var_name = cmd_args.GetArgumentAtIndex(0); 598 if ((var_name == nullptr) || (var_name[0] == '\0')) { 599 result.AppendError("'settings replace' command requires a valid variable " 600 "name; No value supplied"); 601 result.SetStatus(eReturnStatusFailed); 602 return false; 603 } 604 605 // Split the raw command into var_name, index_value, and value triple. 606 llvm::StringRef raw_str(command); 607 std::string var_value_string = raw_str.split(var_name).second.str(); 608 const char *var_value_cstr = 609 Args::StripSpaces(var_value_string, true, true, false); 610 611 Error error(m_interpreter.GetDebugger().SetPropertyValue( 612 &m_exe_ctx, eVarSetOperationReplace, var_name, var_value_cstr)); 613 if (error.Fail()) { 614 result.AppendError(error.AsCString()); 615 result.SetStatus(eReturnStatusFailed); 616 return false; 617 } else { 618 result.SetStatus(eReturnStatusSuccessFinishNoResult); 619 } 620 621 return result.Succeeded(); 622 } 623 }; 624 625 //------------------------------------------------------------------------- 626 // CommandObjectSettingsInsertBefore 627 //------------------------------------------------------------------------- 628 629 class CommandObjectSettingsInsertBefore : public CommandObjectRaw { 630 public: 631 CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter) 632 : CommandObjectRaw(interpreter, "settings insert-before", 633 "Insert one or more values into an debugger array " 634 "setting immediately before the specified element " 635 "index.", 636 nullptr) { 637 CommandArgumentEntry arg1; 638 CommandArgumentEntry arg2; 639 CommandArgumentEntry arg3; 640 CommandArgumentData var_name_arg; 641 CommandArgumentData index_arg; 642 CommandArgumentData value_arg; 643 644 // Define the first (and only) variant of this arg. 645 var_name_arg.arg_type = eArgTypeSettingVariableName; 646 var_name_arg.arg_repetition = eArgRepeatPlain; 647 648 // There is only one variant this argument could be; put it into the 649 // argument entry. 650 arg1.push_back(var_name_arg); 651 652 // Define the first (variant of this arg. 653 index_arg.arg_type = eArgTypeSettingIndex; 654 index_arg.arg_repetition = eArgRepeatPlain; 655 656 // There is only one variant this argument could be; put it into the 657 // argument entry. 658 arg2.push_back(index_arg); 659 660 // Define the first (and only) variant of this arg. 661 value_arg.arg_type = eArgTypeValue; 662 value_arg.arg_repetition = eArgRepeatPlain; 663 664 // There is only one variant this argument could be; put it into the 665 // argument entry. 666 arg3.push_back(value_arg); 667 668 // Push the data for the first argument into the m_arguments vector. 669 m_arguments.push_back(arg1); 670 m_arguments.push_back(arg2); 671 m_arguments.push_back(arg3); 672 } 673 674 ~CommandObjectSettingsInsertBefore() override = default; 675 676 // Overrides base class's behavior where WantsCompletion = 677 // !WantsRawCommandString. 678 bool WantsCompletion() override { return true; } 679 680 int HandleArgumentCompletion(Args &input, int &cursor_index, 681 int &cursor_char_position, 682 OptionElementVector &opt_element_vector, 683 int match_start_point, int max_return_elements, 684 bool &word_complete, 685 StringList &matches) override { 686 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 687 cursor_char_position); 688 689 // Attempting to complete variable name 690 if (cursor_index < 2) 691 CommandCompletions::InvokeCommonCompletionCallbacks( 692 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 693 completion_str.c_str(), match_start_point, max_return_elements, 694 nullptr, word_complete, matches); 695 696 return matches.GetSize(); 697 } 698 699 protected: 700 bool DoExecute(const char *command, CommandReturnObject &result) override { 701 result.SetStatus(eReturnStatusSuccessFinishNoResult); 702 703 Args cmd_args(command); 704 const size_t argc = cmd_args.GetArgumentCount(); 705 706 if (argc < 3) { 707 result.AppendError("'settings insert-before' takes more arguments"); 708 result.SetStatus(eReturnStatusFailed); 709 return false; 710 } 711 712 const char *var_name = cmd_args.GetArgumentAtIndex(0); 713 if ((var_name == nullptr) || (var_name[0] == '\0')) { 714 result.AppendError("'settings insert-before' command requires a valid " 715 "variable name; No value supplied"); 716 result.SetStatus(eReturnStatusFailed); 717 return false; 718 } 719 720 // Split the raw command into var_name, index_value, and value triple. 721 llvm::StringRef raw_str(command); 722 std::string var_value_string = raw_str.split(var_name).second.str(); 723 const char *var_value_cstr = 724 Args::StripSpaces(var_value_string, true, true, false); 725 726 Error error(m_interpreter.GetDebugger().SetPropertyValue( 727 &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value_cstr)); 728 if (error.Fail()) { 729 result.AppendError(error.AsCString()); 730 result.SetStatus(eReturnStatusFailed); 731 return false; 732 } 733 734 return result.Succeeded(); 735 } 736 }; 737 738 //------------------------------------------------------------------------- 739 // CommandObjectSettingInsertAfter 740 //------------------------------------------------------------------------- 741 742 class CommandObjectSettingsInsertAfter : public CommandObjectRaw { 743 public: 744 CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter) 745 : CommandObjectRaw(interpreter, "settings insert-after", 746 "Insert one or more values into a debugger array " 747 "settings after the specified element index.", 748 nullptr) { 749 CommandArgumentEntry arg1; 750 CommandArgumentEntry arg2; 751 CommandArgumentEntry arg3; 752 CommandArgumentData var_name_arg; 753 CommandArgumentData index_arg; 754 CommandArgumentData value_arg; 755 756 // Define the first (and only) variant of this arg. 757 var_name_arg.arg_type = eArgTypeSettingVariableName; 758 var_name_arg.arg_repetition = eArgRepeatPlain; 759 760 // There is only one variant this argument could be; put it into the 761 // argument entry. 762 arg1.push_back(var_name_arg); 763 764 // Define the first (variant of this arg. 765 index_arg.arg_type = eArgTypeSettingIndex; 766 index_arg.arg_repetition = eArgRepeatPlain; 767 768 // There is only one variant this argument could be; put it into the 769 // argument entry. 770 arg2.push_back(index_arg); 771 772 // Define the first (and only) variant of this arg. 773 value_arg.arg_type = eArgTypeValue; 774 value_arg.arg_repetition = eArgRepeatPlain; 775 776 // There is only one variant this argument could be; put it into the 777 // argument entry. 778 arg3.push_back(value_arg); 779 780 // Push the data for the first argument into the m_arguments vector. 781 m_arguments.push_back(arg1); 782 m_arguments.push_back(arg2); 783 m_arguments.push_back(arg3); 784 } 785 786 ~CommandObjectSettingsInsertAfter() override = default; 787 788 // Overrides base class's behavior where WantsCompletion = 789 // !WantsRawCommandString. 790 bool WantsCompletion() override { return true; } 791 792 int HandleArgumentCompletion(Args &input, int &cursor_index, 793 int &cursor_char_position, 794 OptionElementVector &opt_element_vector, 795 int match_start_point, int max_return_elements, 796 bool &word_complete, 797 StringList &matches) override { 798 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 799 cursor_char_position); 800 801 // Attempting to complete variable name 802 if (cursor_index < 2) 803 CommandCompletions::InvokeCommonCompletionCallbacks( 804 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 805 completion_str.c_str(), match_start_point, max_return_elements, 806 nullptr, word_complete, matches); 807 808 return matches.GetSize(); 809 } 810 811 protected: 812 bool DoExecute(const char *command, CommandReturnObject &result) override { 813 result.SetStatus(eReturnStatusSuccessFinishNoResult); 814 815 Args cmd_args(command); 816 const size_t argc = cmd_args.GetArgumentCount(); 817 818 if (argc < 3) { 819 result.AppendError("'settings insert-after' takes more arguments"); 820 result.SetStatus(eReturnStatusFailed); 821 return false; 822 } 823 824 const char *var_name = cmd_args.GetArgumentAtIndex(0); 825 if ((var_name == nullptr) || (var_name[0] == '\0')) { 826 result.AppendError("'settings insert-after' command requires a valid " 827 "variable name; No value supplied"); 828 result.SetStatus(eReturnStatusFailed); 829 return false; 830 } 831 832 // Split the raw command into var_name, index_value, and value triple. 833 llvm::StringRef raw_str(command); 834 std::string var_value_string = raw_str.split(var_name).second.str(); 835 const char *var_value_cstr = 836 Args::StripSpaces(var_value_string, true, true, false); 837 838 Error error(m_interpreter.GetDebugger().SetPropertyValue( 839 &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value_cstr)); 840 if (error.Fail()) { 841 result.AppendError(error.AsCString()); 842 result.SetStatus(eReturnStatusFailed); 843 return false; 844 } 845 846 return result.Succeeded(); 847 } 848 }; 849 850 //------------------------------------------------------------------------- 851 // CommandObjectSettingsAppend 852 //------------------------------------------------------------------------- 853 854 class CommandObjectSettingsAppend : public CommandObjectRaw { 855 public: 856 CommandObjectSettingsAppend(CommandInterpreter &interpreter) 857 : CommandObjectRaw(interpreter, "settings append", 858 "Append one or more values to a debugger array, " 859 "dictionary, or string setting.", 860 nullptr) { 861 CommandArgumentEntry arg1; 862 CommandArgumentEntry arg2; 863 CommandArgumentData var_name_arg; 864 CommandArgumentData value_arg; 865 866 // Define the first (and only) variant of this arg. 867 var_name_arg.arg_type = eArgTypeSettingVariableName; 868 var_name_arg.arg_repetition = eArgRepeatPlain; 869 870 // There is only one variant this argument could be; put it into the 871 // argument entry. 872 arg1.push_back(var_name_arg); 873 874 // Define the first (and only) variant of this arg. 875 value_arg.arg_type = eArgTypeValue; 876 value_arg.arg_repetition = eArgRepeatPlain; 877 878 // There is only one variant this argument could be; put it into the 879 // argument entry. 880 arg2.push_back(value_arg); 881 882 // Push the data for the first argument into the m_arguments vector. 883 m_arguments.push_back(arg1); 884 m_arguments.push_back(arg2); 885 } 886 887 ~CommandObjectSettingsAppend() override = default; 888 889 // Overrides base class's behavior where WantsCompletion = 890 // !WantsRawCommandString. 891 bool WantsCompletion() override { return true; } 892 893 int HandleArgumentCompletion(Args &input, int &cursor_index, 894 int &cursor_char_position, 895 OptionElementVector &opt_element_vector, 896 int match_start_point, int max_return_elements, 897 bool &word_complete, 898 StringList &matches) override { 899 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 900 cursor_char_position); 901 902 // Attempting to complete variable name 903 if (cursor_index < 2) 904 CommandCompletions::InvokeCommonCompletionCallbacks( 905 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 906 completion_str.c_str(), match_start_point, max_return_elements, 907 nullptr, word_complete, matches); 908 909 return matches.GetSize(); 910 } 911 912 protected: 913 bool DoExecute(const char *command, CommandReturnObject &result) override { 914 result.SetStatus(eReturnStatusSuccessFinishNoResult); 915 Args cmd_args(command); 916 const size_t argc = cmd_args.GetArgumentCount(); 917 918 if (argc < 2) { 919 result.AppendError("'settings append' takes more arguments"); 920 result.SetStatus(eReturnStatusFailed); 921 return false; 922 } 923 924 const char *var_name = cmd_args.GetArgumentAtIndex(0); 925 if ((var_name == nullptr) || (var_name[0] == '\0')) { 926 result.AppendError("'settings append' command requires a valid variable " 927 "name; No value supplied"); 928 result.SetStatus(eReturnStatusFailed); 929 return false; 930 } 931 932 // Do not perform cmd_args.Shift() since StringRef is manipulating the 933 // raw character string later on. 934 935 // Split the raw command into var_name and value pair. 936 llvm::StringRef raw_str(command); 937 std::string var_value_string = raw_str.split(var_name).second.str(); 938 const char *var_value_cstr = 939 Args::StripSpaces(var_value_string, true, true, false); 940 941 Error error(m_interpreter.GetDebugger().SetPropertyValue( 942 &m_exe_ctx, eVarSetOperationAppend, var_name, var_value_cstr)); 943 if (error.Fail()) { 944 result.AppendError(error.AsCString()); 945 result.SetStatus(eReturnStatusFailed); 946 return false; 947 } 948 949 return result.Succeeded(); 950 } 951 }; 952 953 //------------------------------------------------------------------------- 954 // CommandObjectSettingsClear 955 //------------------------------------------------------------------------- 956 957 class CommandObjectSettingsClear : public CommandObjectParsed { 958 public: 959 CommandObjectSettingsClear(CommandInterpreter &interpreter) 960 : CommandObjectParsed( 961 interpreter, "settings clear", 962 "Clear a debugger setting array, dictionary, or string.", nullptr) { 963 CommandArgumentEntry arg; 964 CommandArgumentData var_name_arg; 965 966 // Define the first (and only) variant of this arg. 967 var_name_arg.arg_type = eArgTypeSettingVariableName; 968 var_name_arg.arg_repetition = eArgRepeatPlain; 969 970 // There is only one variant this argument could be; put it into the 971 // argument entry. 972 arg.push_back(var_name_arg); 973 974 // Push the data for the first argument into the m_arguments vector. 975 m_arguments.push_back(arg); 976 } 977 978 ~CommandObjectSettingsClear() override = default; 979 980 int HandleArgumentCompletion(Args &input, int &cursor_index, 981 int &cursor_char_position, 982 OptionElementVector &opt_element_vector, 983 int match_start_point, int max_return_elements, 984 bool &word_complete, 985 StringList &matches) override { 986 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 987 cursor_char_position); 988 989 // Attempting to complete variable name 990 if (cursor_index < 2) 991 CommandCompletions::InvokeCommonCompletionCallbacks( 992 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 993 completion_str.c_str(), match_start_point, max_return_elements, 994 nullptr, word_complete, matches); 995 996 return matches.GetSize(); 997 } 998 999 protected: 1000 bool DoExecute(Args &command, CommandReturnObject &result) override { 1001 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1002 const size_t argc = command.GetArgumentCount(); 1003 1004 if (argc != 1) { 1005 result.AppendError("'settings clear' takes exactly one argument"); 1006 result.SetStatus(eReturnStatusFailed); 1007 return false; 1008 } 1009 1010 const char *var_name = command.GetArgumentAtIndex(0); 1011 if ((var_name == nullptr) || (var_name[0] == '\0')) { 1012 result.AppendError("'settings clear' command requires a valid variable " 1013 "name; No value supplied"); 1014 result.SetStatus(eReturnStatusFailed); 1015 return false; 1016 } 1017 1018 Error error(m_interpreter.GetDebugger().SetPropertyValue( 1019 &m_exe_ctx, eVarSetOperationClear, var_name, nullptr)); 1020 if (error.Fail()) { 1021 result.AppendError(error.AsCString()); 1022 result.SetStatus(eReturnStatusFailed); 1023 return false; 1024 } 1025 1026 return result.Succeeded(); 1027 } 1028 }; 1029 1030 //------------------------------------------------------------------------- 1031 // CommandObjectMultiwordSettings 1032 //------------------------------------------------------------------------- 1033 1034 CommandObjectMultiwordSettings::CommandObjectMultiwordSettings( 1035 CommandInterpreter &interpreter) 1036 : CommandObjectMultiword(interpreter, "settings", 1037 "Commands for managing LLDB settings.", 1038 "settings <subcommand> [<command-options>]") { 1039 LoadSubCommand("set", 1040 CommandObjectSP(new CommandObjectSettingsSet(interpreter))); 1041 LoadSubCommand("show", 1042 CommandObjectSP(new CommandObjectSettingsShow(interpreter))); 1043 LoadSubCommand("list", 1044 CommandObjectSP(new CommandObjectSettingsList(interpreter))); 1045 LoadSubCommand("remove", 1046 CommandObjectSP(new CommandObjectSettingsRemove(interpreter))); 1047 LoadSubCommand("replace", CommandObjectSP( 1048 new CommandObjectSettingsReplace(interpreter))); 1049 LoadSubCommand( 1050 "insert-before", 1051 CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter))); 1052 LoadSubCommand( 1053 "insert-after", 1054 CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter))); 1055 LoadSubCommand("append", 1056 CommandObjectSP(new CommandObjectSettingsAppend(interpreter))); 1057 LoadSubCommand("clear", 1058 CommandObjectSP(new CommandObjectSettingsClear(interpreter))); 1059 } 1060 1061 CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default; 1062