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