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