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