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