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, const char *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 const size_t argc = args.GetArgumentCount(); 297 if (!args.empty()) { 298 // TODO: Convert this to StringRef based enumeration. Requires converting 299 // DumpPropertyValue first. 300 for (size_t i = 0; i < argc; ++i) { 301 const char *property_path = args.GetArgumentAtIndex(i); 302 303 Error error(m_interpreter.GetDebugger().DumpPropertyValue( 304 &m_exe_ctx, result.GetOutputStream(), property_path, 305 OptionValue::eDumpGroupValue)); 306 if (error.Success()) { 307 result.GetOutputStream().EOL(); 308 } else { 309 result.AppendError(error.AsCString()); 310 result.SetStatus(eReturnStatusFailed); 311 } 312 } 313 } else { 314 m_interpreter.GetDebugger().DumpAllPropertyValues( 315 &m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue); 316 } 317 318 return result.Succeeded(); 319 } 320 }; 321 322 //------------------------------------------------------------------------- 323 // CommandObjectSettingsList -- List settable variables 324 //------------------------------------------------------------------------- 325 326 class CommandObjectSettingsList : public CommandObjectParsed { 327 public: 328 CommandObjectSettingsList(CommandInterpreter &interpreter) 329 : CommandObjectParsed(interpreter, "settings list", 330 "List and describe matching debugger settings. " 331 "Defaults to all listing all settings.", 332 nullptr) { 333 CommandArgumentEntry arg; 334 CommandArgumentData var_name_arg; 335 CommandArgumentData prefix_name_arg; 336 337 // Define the first variant of this arg. 338 var_name_arg.arg_type = eArgTypeSettingVariableName; 339 var_name_arg.arg_repetition = eArgRepeatOptional; 340 341 // Define the second variant of this arg. 342 prefix_name_arg.arg_type = eArgTypeSettingPrefix; 343 prefix_name_arg.arg_repetition = eArgRepeatOptional; 344 345 arg.push_back(var_name_arg); 346 arg.push_back(prefix_name_arg); 347 348 // Push the data for the first argument into the m_arguments vector. 349 m_arguments.push_back(arg); 350 } 351 352 ~CommandObjectSettingsList() override = default; 353 354 int HandleArgumentCompletion(Args &input, int &cursor_index, 355 int &cursor_char_position, 356 OptionElementVector &opt_element_vector, 357 int match_start_point, int max_return_elements, 358 bool &word_complete, 359 StringList &matches) override { 360 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 361 cursor_char_position); 362 363 CommandCompletions::InvokeCommonCompletionCallbacks( 364 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 365 completion_str.c_str(), match_start_point, max_return_elements, nullptr, 366 word_complete, matches); 367 return matches.GetSize(); 368 } 369 370 protected: 371 bool DoExecute(Args &args, CommandReturnObject &result) override { 372 result.SetStatus(eReturnStatusSuccessFinishResult); 373 374 const bool will_modify = false; 375 const size_t argc = args.GetArgumentCount(); 376 if (argc > 0) { 377 const bool dump_qualified_name = true; 378 379 // TODO: Convert to StringRef based enumeration. Requires converting 380 // GetPropertyAtPath first. 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 CommandArgumentEntry arg1; 417 CommandArgumentEntry arg2; 418 CommandArgumentData var_name_arg; 419 CommandArgumentData index_arg; 420 CommandArgumentData key_arg; 421 422 // Define the first (and only) variant of this arg. 423 var_name_arg.arg_type = eArgTypeSettingVariableName; 424 var_name_arg.arg_repetition = eArgRepeatPlain; 425 426 // There is only one variant this argument could be; put it into the 427 // argument entry. 428 arg1.push_back(var_name_arg); 429 430 // Define the first variant of this arg. 431 index_arg.arg_type = eArgTypeSettingIndex; 432 index_arg.arg_repetition = eArgRepeatPlain; 433 434 // Define the second variant of this arg. 435 key_arg.arg_type = eArgTypeSettingKey; 436 key_arg.arg_repetition = eArgRepeatPlain; 437 438 // Push both variants into this arg 439 arg2.push_back(index_arg); 440 arg2.push_back(key_arg); 441 442 // Push the data for the first argument into the m_arguments vector. 443 m_arguments.push_back(arg1); 444 m_arguments.push_back(arg2); 445 } 446 447 ~CommandObjectSettingsRemove() override = default; 448 449 int HandleArgumentCompletion(Args &input, int &cursor_index, 450 int &cursor_char_position, 451 OptionElementVector &opt_element_vector, 452 int match_start_point, int max_return_elements, 453 bool &word_complete, 454 StringList &matches) override { 455 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 456 cursor_char_position); 457 458 // Attempting to complete variable name 459 if (cursor_index < 2) 460 CommandCompletions::InvokeCommonCompletionCallbacks( 461 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 462 completion_str.c_str(), match_start_point, max_return_elements, 463 nullptr, word_complete, matches); 464 return matches.GetSize(); 465 } 466 467 protected: 468 bool DoExecute(const char *command, CommandReturnObject &result) override { 469 result.SetStatus(eReturnStatusSuccessFinishNoResult); 470 471 Args cmd_args(command); 472 473 // Process possible options. 474 if (!ParseOptions(cmd_args, result)) 475 return false; 476 477 const size_t argc = cmd_args.GetArgumentCount(); 478 if (argc == 0) { 479 result.AppendError("'settings set' takes an array or dictionary item, or " 480 "an array followed by one or more indexes, or a " 481 "dictionary followed by one or more key names to " 482 "remove"); 483 result.SetStatus(eReturnStatusFailed); 484 return false; 485 } 486 487 const char *var_name = cmd_args.GetArgumentAtIndex(0); 488 if ((var_name == nullptr) || (var_name[0] == '\0')) { 489 result.AppendError( 490 "'settings set' command requires a valid variable name"); 491 result.SetStatus(eReturnStatusFailed); 492 return false; 493 } 494 495 // Split the raw command into var_name and value pair. 496 llvm::StringRef raw_str(command); 497 std::string var_value_string = raw_str.split(var_name).second.str(); 498 const char *var_value_cstr = 499 Args::StripSpaces(var_value_string, true, true, false); 500 501 Error error(m_interpreter.GetDebugger().SetPropertyValue( 502 &m_exe_ctx, eVarSetOperationRemove, var_name, var_value_cstr)); 503 if (error.Fail()) { 504 result.AppendError(error.AsCString()); 505 result.SetStatus(eReturnStatusFailed); 506 return false; 507 } 508 509 return result.Succeeded(); 510 } 511 }; 512 513 //------------------------------------------------------------------------- 514 // CommandObjectSettingsReplace 515 //------------------------------------------------------------------------- 516 517 class CommandObjectSettingsReplace : public CommandObjectRaw { 518 public: 519 CommandObjectSettingsReplace(CommandInterpreter &interpreter) 520 : CommandObjectRaw(interpreter, "settings replace", 521 "Replace the debugger setting value specified by " 522 "array index or dictionary key.") { 523 CommandArgumentEntry arg1; 524 CommandArgumentEntry arg2; 525 CommandArgumentEntry arg3; 526 CommandArgumentData var_name_arg; 527 CommandArgumentData index_arg; 528 CommandArgumentData key_arg; 529 CommandArgumentData value_arg; 530 531 // Define the first (and only) variant of this arg. 532 var_name_arg.arg_type = eArgTypeSettingVariableName; 533 var_name_arg.arg_repetition = eArgRepeatPlain; 534 535 // There is only one variant this argument could be; put it into the 536 // argument entry. 537 arg1.push_back(var_name_arg); 538 539 // Define the first (variant of this arg. 540 index_arg.arg_type = eArgTypeSettingIndex; 541 index_arg.arg_repetition = eArgRepeatPlain; 542 543 // Define the second (variant of this arg. 544 key_arg.arg_type = eArgTypeSettingKey; 545 key_arg.arg_repetition = eArgRepeatPlain; 546 547 // Put both variants into this arg 548 arg2.push_back(index_arg); 549 arg2.push_back(key_arg); 550 551 // Define the first (and only) variant of this arg. 552 value_arg.arg_type = eArgTypeValue; 553 value_arg.arg_repetition = eArgRepeatPlain; 554 555 // There is only one variant this argument could be; put it into the 556 // argument entry. 557 arg3.push_back(value_arg); 558 559 // Push the data for the first argument into the m_arguments vector. 560 m_arguments.push_back(arg1); 561 m_arguments.push_back(arg2); 562 m_arguments.push_back(arg3); 563 } 564 565 ~CommandObjectSettingsReplace() override = default; 566 567 // Overrides base class's behavior where WantsCompletion = 568 // !WantsRawCommandString. 569 bool WantsCompletion() override { return true; } 570 571 int HandleArgumentCompletion(Args &input, int &cursor_index, 572 int &cursor_char_position, 573 OptionElementVector &opt_element_vector, 574 int match_start_point, int max_return_elements, 575 bool &word_complete, 576 StringList &matches) override { 577 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 578 cursor_char_position); 579 580 // Attempting to complete variable name 581 if (cursor_index < 2) 582 CommandCompletions::InvokeCommonCompletionCallbacks( 583 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 584 completion_str.c_str(), match_start_point, max_return_elements, 585 nullptr, word_complete, matches); 586 587 return matches.GetSize(); 588 } 589 590 protected: 591 bool DoExecute(const char *command, CommandReturnObject &result) override { 592 result.SetStatus(eReturnStatusSuccessFinishNoResult); 593 594 Args cmd_args(command); 595 const char *var_name = cmd_args.GetArgumentAtIndex(0); 596 if ((var_name == nullptr) || (var_name[0] == '\0')) { 597 result.AppendError("'settings replace' command requires a valid variable " 598 "name; No value supplied"); 599 result.SetStatus(eReturnStatusFailed); 600 return false; 601 } 602 603 // Split the raw command into var_name, index_value, and value triple. 604 llvm::StringRef raw_str(command); 605 std::string var_value_string = raw_str.split(var_name).second.str(); 606 const char *var_value_cstr = 607 Args::StripSpaces(var_value_string, true, true, false); 608 609 Error error(m_interpreter.GetDebugger().SetPropertyValue( 610 &m_exe_ctx, eVarSetOperationReplace, var_name, var_value_cstr)); 611 if (error.Fail()) { 612 result.AppendError(error.AsCString()); 613 result.SetStatus(eReturnStatusFailed); 614 return false; 615 } else { 616 result.SetStatus(eReturnStatusSuccessFinishNoResult); 617 } 618 619 return result.Succeeded(); 620 } 621 }; 622 623 //------------------------------------------------------------------------- 624 // CommandObjectSettingsInsertBefore 625 //------------------------------------------------------------------------- 626 627 class CommandObjectSettingsInsertBefore : public CommandObjectRaw { 628 public: 629 CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter) 630 : CommandObjectRaw(interpreter, "settings insert-before", 631 "Insert one or more values into an debugger array " 632 "setting immediately before the specified element " 633 "index.") { 634 CommandArgumentEntry arg1; 635 CommandArgumentEntry arg2; 636 CommandArgumentEntry arg3; 637 CommandArgumentData var_name_arg; 638 CommandArgumentData index_arg; 639 CommandArgumentData value_arg; 640 641 // Define the first (and only) variant of this arg. 642 var_name_arg.arg_type = eArgTypeSettingVariableName; 643 var_name_arg.arg_repetition = eArgRepeatPlain; 644 645 // There is only one variant this argument could be; put it into the 646 // argument entry. 647 arg1.push_back(var_name_arg); 648 649 // Define the first (variant of this arg. 650 index_arg.arg_type = eArgTypeSettingIndex; 651 index_arg.arg_repetition = eArgRepeatPlain; 652 653 // There is only one variant this argument could be; put it into the 654 // argument entry. 655 arg2.push_back(index_arg); 656 657 // Define the first (and only) variant of this arg. 658 value_arg.arg_type = eArgTypeValue; 659 value_arg.arg_repetition = eArgRepeatPlain; 660 661 // There is only one variant this argument could be; put it into the 662 // argument entry. 663 arg3.push_back(value_arg); 664 665 // Push the data for the first argument into the m_arguments vector. 666 m_arguments.push_back(arg1); 667 m_arguments.push_back(arg2); 668 m_arguments.push_back(arg3); 669 } 670 671 ~CommandObjectSettingsInsertBefore() override = default; 672 673 // Overrides base class's behavior where WantsCompletion = 674 // !WantsRawCommandString. 675 bool WantsCompletion() override { return true; } 676 677 int HandleArgumentCompletion(Args &input, int &cursor_index, 678 int &cursor_char_position, 679 OptionElementVector &opt_element_vector, 680 int match_start_point, int max_return_elements, 681 bool &word_complete, 682 StringList &matches) override { 683 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 684 cursor_char_position); 685 686 // Attempting to complete variable name 687 if (cursor_index < 2) 688 CommandCompletions::InvokeCommonCompletionCallbacks( 689 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 690 completion_str.c_str(), match_start_point, max_return_elements, 691 nullptr, word_complete, matches); 692 693 return matches.GetSize(); 694 } 695 696 protected: 697 bool DoExecute(const char *command, CommandReturnObject &result) override { 698 result.SetStatus(eReturnStatusSuccessFinishNoResult); 699 700 Args cmd_args(command); 701 const size_t argc = cmd_args.GetArgumentCount(); 702 703 if (argc < 3) { 704 result.AppendError("'settings insert-before' takes more arguments"); 705 result.SetStatus(eReturnStatusFailed); 706 return false; 707 } 708 709 const char *var_name = cmd_args.GetArgumentAtIndex(0); 710 if ((var_name == nullptr) || (var_name[0] == '\0')) { 711 result.AppendError("'settings insert-before' command requires a valid " 712 "variable name; No value supplied"); 713 result.SetStatus(eReturnStatusFailed); 714 return false; 715 } 716 717 // Split the raw command into var_name, index_value, and value triple. 718 llvm::StringRef raw_str(command); 719 std::string var_value_string = raw_str.split(var_name).second.str(); 720 const char *var_value_cstr = 721 Args::StripSpaces(var_value_string, true, true, false); 722 723 Error error(m_interpreter.GetDebugger().SetPropertyValue( 724 &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value_cstr)); 725 if (error.Fail()) { 726 result.AppendError(error.AsCString()); 727 result.SetStatus(eReturnStatusFailed); 728 return false; 729 } 730 731 return result.Succeeded(); 732 } 733 }; 734 735 //------------------------------------------------------------------------- 736 // CommandObjectSettingInsertAfter 737 //------------------------------------------------------------------------- 738 739 class CommandObjectSettingsInsertAfter : public CommandObjectRaw { 740 public: 741 CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter) 742 : CommandObjectRaw(interpreter, "settings insert-after", 743 "Insert one or more values into a debugger array " 744 "settings after the specified element index.") { 745 CommandArgumentEntry arg1; 746 CommandArgumentEntry arg2; 747 CommandArgumentEntry arg3; 748 CommandArgumentData var_name_arg; 749 CommandArgumentData index_arg; 750 CommandArgumentData value_arg; 751 752 // Define the first (and only) variant of this arg. 753 var_name_arg.arg_type = eArgTypeSettingVariableName; 754 var_name_arg.arg_repetition = eArgRepeatPlain; 755 756 // There is only one variant this argument could be; put it into the 757 // argument entry. 758 arg1.push_back(var_name_arg); 759 760 // Define the first (variant of this arg. 761 index_arg.arg_type = eArgTypeSettingIndex; 762 index_arg.arg_repetition = eArgRepeatPlain; 763 764 // There is only one variant this argument could be; put it into the 765 // argument entry. 766 arg2.push_back(index_arg); 767 768 // Define the first (and only) variant of this arg. 769 value_arg.arg_type = eArgTypeValue; 770 value_arg.arg_repetition = eArgRepeatPlain; 771 772 // There is only one variant this argument could be; put it into the 773 // argument entry. 774 arg3.push_back(value_arg); 775 776 // Push the data for the first argument into the m_arguments vector. 777 m_arguments.push_back(arg1); 778 m_arguments.push_back(arg2); 779 m_arguments.push_back(arg3); 780 } 781 782 ~CommandObjectSettingsInsertAfter() override = default; 783 784 // Overrides base class's behavior where WantsCompletion = 785 // !WantsRawCommandString. 786 bool WantsCompletion() override { return true; } 787 788 int HandleArgumentCompletion(Args &input, int &cursor_index, 789 int &cursor_char_position, 790 OptionElementVector &opt_element_vector, 791 int match_start_point, int max_return_elements, 792 bool &word_complete, 793 StringList &matches) override { 794 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 795 cursor_char_position); 796 797 // Attempting to complete variable name 798 if (cursor_index < 2) 799 CommandCompletions::InvokeCommonCompletionCallbacks( 800 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 801 completion_str.c_str(), match_start_point, max_return_elements, 802 nullptr, word_complete, matches); 803 804 return matches.GetSize(); 805 } 806 807 protected: 808 bool DoExecute(const char *command, CommandReturnObject &result) override { 809 result.SetStatus(eReturnStatusSuccessFinishNoResult); 810 811 Args cmd_args(command); 812 const size_t argc = cmd_args.GetArgumentCount(); 813 814 if (argc < 3) { 815 result.AppendError("'settings insert-after' takes more arguments"); 816 result.SetStatus(eReturnStatusFailed); 817 return false; 818 } 819 820 const char *var_name = cmd_args.GetArgumentAtIndex(0); 821 if ((var_name == nullptr) || (var_name[0] == '\0')) { 822 result.AppendError("'settings insert-after' command requires a valid " 823 "variable name; No value supplied"); 824 result.SetStatus(eReturnStatusFailed); 825 return false; 826 } 827 828 // Split the raw command into var_name, index_value, and value triple. 829 llvm::StringRef raw_str(command); 830 std::string var_value_string = raw_str.split(var_name).second.str(); 831 const char *var_value_cstr = 832 Args::StripSpaces(var_value_string, true, true, false); 833 834 Error error(m_interpreter.GetDebugger().SetPropertyValue( 835 &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value_cstr)); 836 if (error.Fail()) { 837 result.AppendError(error.AsCString()); 838 result.SetStatus(eReturnStatusFailed); 839 return false; 840 } 841 842 return result.Succeeded(); 843 } 844 }; 845 846 //------------------------------------------------------------------------- 847 // CommandObjectSettingsAppend 848 //------------------------------------------------------------------------- 849 850 class CommandObjectSettingsAppend : public CommandObjectRaw { 851 public: 852 CommandObjectSettingsAppend(CommandInterpreter &interpreter) 853 : CommandObjectRaw(interpreter, "settings append", 854 "Append one or more values to a debugger array, " 855 "dictionary, or string setting.") { 856 CommandArgumentEntry arg1; 857 CommandArgumentEntry arg2; 858 CommandArgumentData var_name_arg; 859 CommandArgumentData value_arg; 860 861 // Define the first (and only) variant of this arg. 862 var_name_arg.arg_type = eArgTypeSettingVariableName; 863 var_name_arg.arg_repetition = eArgRepeatPlain; 864 865 // There is only one variant this argument could be; put it into the 866 // argument entry. 867 arg1.push_back(var_name_arg); 868 869 // Define the first (and only) variant of this arg. 870 value_arg.arg_type = eArgTypeValue; 871 value_arg.arg_repetition = eArgRepeatPlain; 872 873 // There is only one variant this argument could be; put it into the 874 // argument entry. 875 arg2.push_back(value_arg); 876 877 // Push the data for the first argument into the m_arguments vector. 878 m_arguments.push_back(arg1); 879 m_arguments.push_back(arg2); 880 } 881 882 ~CommandObjectSettingsAppend() override = default; 883 884 // Overrides base class's behavior where WantsCompletion = 885 // !WantsRawCommandString. 886 bool WantsCompletion() override { return true; } 887 888 int HandleArgumentCompletion(Args &input, int &cursor_index, 889 int &cursor_char_position, 890 OptionElementVector &opt_element_vector, 891 int match_start_point, int max_return_elements, 892 bool &word_complete, 893 StringList &matches) override { 894 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 895 cursor_char_position); 896 897 // Attempting to complete variable name 898 if (cursor_index < 2) 899 CommandCompletions::InvokeCommonCompletionCallbacks( 900 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 901 completion_str.c_str(), match_start_point, max_return_elements, 902 nullptr, word_complete, matches); 903 904 return matches.GetSize(); 905 } 906 907 protected: 908 bool DoExecute(const char *command, CommandReturnObject &result) override { 909 result.SetStatus(eReturnStatusSuccessFinishNoResult); 910 Args cmd_args(command); 911 const size_t argc = cmd_args.GetArgumentCount(); 912 913 if (argc < 2) { 914 result.AppendError("'settings append' takes more arguments"); 915 result.SetStatus(eReturnStatusFailed); 916 return false; 917 } 918 919 const char *var_name = cmd_args.GetArgumentAtIndex(0); 920 if ((var_name == nullptr) || (var_name[0] == '\0')) { 921 result.AppendError("'settings append' command requires a valid variable " 922 "name; No value supplied"); 923 result.SetStatus(eReturnStatusFailed); 924 return false; 925 } 926 927 // Do not perform cmd_args.Shift() since StringRef is manipulating the 928 // raw character string later on. 929 930 // Split the raw command into var_name and value pair. 931 llvm::StringRef raw_str(command); 932 std::string var_value_string = raw_str.split(var_name).second.str(); 933 const char *var_value_cstr = 934 Args::StripSpaces(var_value_string, true, true, false); 935 936 Error error(m_interpreter.GetDebugger().SetPropertyValue( 937 &m_exe_ctx, eVarSetOperationAppend, var_name, var_value_cstr)); 938 if (error.Fail()) { 939 result.AppendError(error.AsCString()); 940 result.SetStatus(eReturnStatusFailed); 941 return false; 942 } 943 944 return result.Succeeded(); 945 } 946 }; 947 948 //------------------------------------------------------------------------- 949 // CommandObjectSettingsClear 950 //------------------------------------------------------------------------- 951 952 class CommandObjectSettingsClear : public CommandObjectParsed { 953 public: 954 CommandObjectSettingsClear(CommandInterpreter &interpreter) 955 : CommandObjectParsed( 956 interpreter, "settings clear", 957 "Clear a debugger setting array, dictionary, or string.", nullptr) { 958 CommandArgumentEntry arg; 959 CommandArgumentData var_name_arg; 960 961 // Define the first (and only) variant of this arg. 962 var_name_arg.arg_type = eArgTypeSettingVariableName; 963 var_name_arg.arg_repetition = eArgRepeatPlain; 964 965 // There is only one variant this argument could be; put it into the 966 // argument entry. 967 arg.push_back(var_name_arg); 968 969 // Push the data for the first argument into the m_arguments vector. 970 m_arguments.push_back(arg); 971 } 972 973 ~CommandObjectSettingsClear() override = default; 974 975 int HandleArgumentCompletion(Args &input, int &cursor_index, 976 int &cursor_char_position, 977 OptionElementVector &opt_element_vector, 978 int match_start_point, int max_return_elements, 979 bool &word_complete, 980 StringList &matches) override { 981 std::string completion_str(input.GetArgumentAtIndex(cursor_index), 982 cursor_char_position); 983 984 // Attempting to complete variable name 985 if (cursor_index < 2) 986 CommandCompletions::InvokeCommonCompletionCallbacks( 987 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 988 completion_str.c_str(), match_start_point, max_return_elements, 989 nullptr, word_complete, matches); 990 991 return matches.GetSize(); 992 } 993 994 protected: 995 bool DoExecute(Args &command, CommandReturnObject &result) override { 996 result.SetStatus(eReturnStatusSuccessFinishNoResult); 997 const size_t argc = command.GetArgumentCount(); 998 999 if (argc != 1) { 1000 result.AppendError("'settings clear' takes exactly one argument"); 1001 result.SetStatus(eReturnStatusFailed); 1002 return false; 1003 } 1004 1005 const char *var_name = command.GetArgumentAtIndex(0); 1006 if ((var_name == nullptr) || (var_name[0] == '\0')) { 1007 result.AppendError("'settings clear' command requires a valid variable " 1008 "name; No value supplied"); 1009 result.SetStatus(eReturnStatusFailed); 1010 return false; 1011 } 1012 1013 Error error(m_interpreter.GetDebugger().SetPropertyValue( 1014 &m_exe_ctx, eVarSetOperationClear, var_name, nullptr)); 1015 if (error.Fail()) { 1016 result.AppendError(error.AsCString()); 1017 result.SetStatus(eReturnStatusFailed); 1018 return false; 1019 } 1020 1021 return result.Succeeded(); 1022 } 1023 }; 1024 1025 //------------------------------------------------------------------------- 1026 // CommandObjectMultiwordSettings 1027 //------------------------------------------------------------------------- 1028 1029 CommandObjectMultiwordSettings::CommandObjectMultiwordSettings( 1030 CommandInterpreter &interpreter) 1031 : CommandObjectMultiword(interpreter, "settings", 1032 "Commands for managing LLDB settings.", 1033 "settings <subcommand> [<command-options>]") { 1034 LoadSubCommand("set", 1035 CommandObjectSP(new CommandObjectSettingsSet(interpreter))); 1036 LoadSubCommand("show", 1037 CommandObjectSP(new CommandObjectSettingsShow(interpreter))); 1038 LoadSubCommand("list", 1039 CommandObjectSP(new CommandObjectSettingsList(interpreter))); 1040 LoadSubCommand("remove", 1041 CommandObjectSP(new CommandObjectSettingsRemove(interpreter))); 1042 LoadSubCommand("replace", CommandObjectSP( 1043 new CommandObjectSettingsReplace(interpreter))); 1044 LoadSubCommand( 1045 "insert-before", 1046 CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter))); 1047 LoadSubCommand( 1048 "insert-after", 1049 CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter))); 1050 LoadSubCommand("append", 1051 CommandObjectSP(new CommandObjectSettingsAppend(interpreter))); 1052 LoadSubCommand("clear", 1053 CommandObjectSP(new CommandObjectSettingsClear(interpreter))); 1054 } 1055 1056 CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default; 1057