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