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