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