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