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