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