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