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