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