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