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