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