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