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