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 ExecutionContext clean_ctx; 473 CommandInterpreterRunOptions options; 474 options.SetAddToHistory(false); 475 options.SetEchoCommands(false); 476 options.SetPrintResults(true); 477 options.SetPrintErrors(true); 478 options.SetStopOnError(false); 479 m_interpreter.HandleCommandsFromFile(file, &clean_ctx, options, result); 480 return result.Succeeded(); 481 } 482 483 private: 484 CommandOptions m_options; 485 }; 486 487 // CommandObjectSettingsList -- List settable variables 488 489 class CommandObjectSettingsList : public CommandObjectParsed { 490 public: 491 CommandObjectSettingsList(CommandInterpreter &interpreter) 492 : CommandObjectParsed(interpreter, "settings list", 493 "List and describe matching debugger settings. " 494 "Defaults to all listing all settings.", 495 nullptr) { 496 CommandArgumentEntry arg; 497 CommandArgumentData var_name_arg; 498 CommandArgumentData prefix_name_arg; 499 500 // Define the first variant of this arg. 501 var_name_arg.arg_type = eArgTypeSettingVariableName; 502 var_name_arg.arg_repetition = eArgRepeatOptional; 503 504 // Define the second variant of this arg. 505 prefix_name_arg.arg_type = eArgTypeSettingPrefix; 506 prefix_name_arg.arg_repetition = eArgRepeatOptional; 507 508 arg.push_back(var_name_arg); 509 arg.push_back(prefix_name_arg); 510 511 // Push the data for the first argument into the m_arguments vector. 512 m_arguments.push_back(arg); 513 } 514 515 ~CommandObjectSettingsList() override = default; 516 517 void 518 HandleArgumentCompletion(CompletionRequest &request, 519 OptionElementVector &opt_element_vector) override { 520 CommandCompletions::InvokeCommonCompletionCallbacks( 521 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 522 request, nullptr); 523 } 524 525 protected: 526 bool DoExecute(Args &args, CommandReturnObject &result) override { 527 result.SetStatus(eReturnStatusSuccessFinishResult); 528 529 const bool will_modify = false; 530 const size_t argc = args.GetArgumentCount(); 531 if (argc > 0) { 532 const bool dump_qualified_name = true; 533 534 for (const Args::ArgEntry &arg : args) { 535 const char *property_path = arg.c_str(); 536 537 const Property *property = 538 GetDebugger().GetValueProperties()->GetPropertyAtPath( 539 &m_exe_ctx, will_modify, property_path); 540 541 if (property) { 542 property->DumpDescription(m_interpreter, result.GetOutputStream(), 0, 543 dump_qualified_name); 544 } else { 545 result.AppendErrorWithFormat("invalid property path '%s'", 546 property_path); 547 result.SetStatus(eReturnStatusFailed); 548 } 549 } 550 } else { 551 GetDebugger().DumpAllDescriptions(m_interpreter, 552 result.GetOutputStream()); 553 } 554 555 return result.Succeeded(); 556 } 557 }; 558 559 // CommandObjectSettingsRemove 560 561 class CommandObjectSettingsRemove : public CommandObjectRaw { 562 public: 563 CommandObjectSettingsRemove(CommandInterpreter &interpreter) 564 : CommandObjectRaw(interpreter, "settings remove", 565 "Remove a value from a setting, specified by array " 566 "index or dictionary key.") { 567 CommandArgumentEntry arg1; 568 CommandArgumentEntry arg2; 569 CommandArgumentData var_name_arg; 570 CommandArgumentData index_arg; 571 CommandArgumentData key_arg; 572 573 // Define the first (and only) variant of this arg. 574 var_name_arg.arg_type = eArgTypeSettingVariableName; 575 var_name_arg.arg_repetition = eArgRepeatPlain; 576 577 // There is only one variant this argument could be; put it into the 578 // argument entry. 579 arg1.push_back(var_name_arg); 580 581 // Define the first variant of this arg. 582 index_arg.arg_type = eArgTypeSettingIndex; 583 index_arg.arg_repetition = eArgRepeatPlain; 584 585 // Define the second variant of this arg. 586 key_arg.arg_type = eArgTypeSettingKey; 587 key_arg.arg_repetition = eArgRepeatPlain; 588 589 // Push both variants into this arg 590 arg2.push_back(index_arg); 591 arg2.push_back(key_arg); 592 593 // Push the data for the first argument into the m_arguments vector. 594 m_arguments.push_back(arg1); 595 m_arguments.push_back(arg2); 596 } 597 598 ~CommandObjectSettingsRemove() override = default; 599 600 bool WantsCompletion() override { return true; } 601 602 void 603 HandleArgumentCompletion(CompletionRequest &request, 604 OptionElementVector &opt_element_vector) override { 605 if (request.GetCursorIndex() < 2) 606 CommandCompletions::InvokeCommonCompletionCallbacks( 607 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 608 request, nullptr); 609 } 610 611 protected: 612 bool DoExecute(llvm::StringRef command, 613 CommandReturnObject &result) override { 614 result.SetStatus(eReturnStatusSuccessFinishNoResult); 615 616 Args cmd_args(command); 617 618 // Process possible options. 619 if (!ParseOptions(cmd_args, result)) 620 return false; 621 622 const size_t argc = cmd_args.GetArgumentCount(); 623 if (argc == 0) { 624 result.AppendError("'settings remove' takes an array or dictionary item, " 625 "or an array followed by one or more indexes, or a " 626 "dictionary followed by one or more key names to " 627 "remove"); 628 result.SetStatus(eReturnStatusFailed); 629 return false; 630 } 631 632 const char *var_name = cmd_args.GetArgumentAtIndex(0); 633 if ((var_name == nullptr) || (var_name[0] == '\0')) { 634 result.AppendError( 635 "'settings remove' command requires a valid variable name"); 636 result.SetStatus(eReturnStatusFailed); 637 return false; 638 } 639 640 // Split the raw command into var_name and value pair. 641 llvm::StringRef var_value(command); 642 var_value = var_value.split(var_name).second.trim(); 643 644 Status error(GetDebugger().SetPropertyValue( 645 &m_exe_ctx, eVarSetOperationRemove, var_name, var_value)); 646 if (error.Fail()) { 647 result.AppendError(error.AsCString()); 648 result.SetStatus(eReturnStatusFailed); 649 return false; 650 } 651 652 return result.Succeeded(); 653 } 654 }; 655 656 // CommandObjectSettingsReplace 657 658 class CommandObjectSettingsReplace : public CommandObjectRaw { 659 public: 660 CommandObjectSettingsReplace(CommandInterpreter &interpreter) 661 : CommandObjectRaw(interpreter, "settings replace", 662 "Replace the debugger setting value specified by " 663 "array index or dictionary key.") { 664 CommandArgumentEntry arg1; 665 CommandArgumentEntry arg2; 666 CommandArgumentEntry arg3; 667 CommandArgumentData var_name_arg; 668 CommandArgumentData index_arg; 669 CommandArgumentData key_arg; 670 CommandArgumentData value_arg; 671 672 // Define the first (and only) variant of this arg. 673 var_name_arg.arg_type = eArgTypeSettingVariableName; 674 var_name_arg.arg_repetition = eArgRepeatPlain; 675 676 // There is only one variant this argument could be; put it into the 677 // argument entry. 678 arg1.push_back(var_name_arg); 679 680 // Define the first (variant of this arg. 681 index_arg.arg_type = eArgTypeSettingIndex; 682 index_arg.arg_repetition = eArgRepeatPlain; 683 684 // Define the second (variant of this arg. 685 key_arg.arg_type = eArgTypeSettingKey; 686 key_arg.arg_repetition = eArgRepeatPlain; 687 688 // Put both variants into this arg 689 arg2.push_back(index_arg); 690 arg2.push_back(key_arg); 691 692 // Define the first (and only) variant of this arg. 693 value_arg.arg_type = eArgTypeValue; 694 value_arg.arg_repetition = eArgRepeatPlain; 695 696 // There is only one variant this argument could be; put it into the 697 // argument entry. 698 arg3.push_back(value_arg); 699 700 // Push the data for the first argument into the m_arguments vector. 701 m_arguments.push_back(arg1); 702 m_arguments.push_back(arg2); 703 m_arguments.push_back(arg3); 704 } 705 706 ~CommandObjectSettingsReplace() override = default; 707 708 // Overrides base class's behavior where WantsCompletion = 709 // !WantsRawCommandString. 710 bool WantsCompletion() override { return true; } 711 712 void 713 HandleArgumentCompletion(CompletionRequest &request, 714 OptionElementVector &opt_element_vector) override { 715 // Attempting to complete variable name 716 if (request.GetCursorIndex() < 2) 717 CommandCompletions::InvokeCommonCompletionCallbacks( 718 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 719 request, nullptr); 720 } 721 722 protected: 723 bool DoExecute(llvm::StringRef command, 724 CommandReturnObject &result) override { 725 result.SetStatus(eReturnStatusSuccessFinishNoResult); 726 727 Args cmd_args(command); 728 const char *var_name = cmd_args.GetArgumentAtIndex(0); 729 if ((var_name == nullptr) || (var_name[0] == '\0')) { 730 result.AppendError("'settings replace' command requires a valid variable " 731 "name; No value supplied"); 732 result.SetStatus(eReturnStatusFailed); 733 return false; 734 } 735 736 // Split the raw command into var_name, index_value, and value triple. 737 llvm::StringRef var_value(command); 738 var_value = var_value.split(var_name).second.trim(); 739 740 Status error(GetDebugger().SetPropertyValue( 741 &m_exe_ctx, eVarSetOperationReplace, var_name, var_value)); 742 if (error.Fail()) { 743 result.AppendError(error.AsCString()); 744 result.SetStatus(eReturnStatusFailed); 745 return false; 746 } else { 747 result.SetStatus(eReturnStatusSuccessFinishNoResult); 748 } 749 750 return result.Succeeded(); 751 } 752 }; 753 754 // CommandObjectSettingsInsertBefore 755 756 class CommandObjectSettingsInsertBefore : public CommandObjectRaw { 757 public: 758 CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter) 759 : CommandObjectRaw(interpreter, "settings insert-before", 760 "Insert one or more values into an debugger array " 761 "setting immediately before the specified element " 762 "index.") { 763 CommandArgumentEntry arg1; 764 CommandArgumentEntry arg2; 765 CommandArgumentEntry arg3; 766 CommandArgumentData var_name_arg; 767 CommandArgumentData index_arg; 768 CommandArgumentData value_arg; 769 770 // Define the first (and only) variant of this arg. 771 var_name_arg.arg_type = eArgTypeSettingVariableName; 772 var_name_arg.arg_repetition = eArgRepeatPlain; 773 774 // There is only one variant this argument could be; put it into the 775 // argument entry. 776 arg1.push_back(var_name_arg); 777 778 // Define the first (variant of this arg. 779 index_arg.arg_type = eArgTypeSettingIndex; 780 index_arg.arg_repetition = eArgRepeatPlain; 781 782 // There is only one variant this argument could be; put it into the 783 // argument entry. 784 arg2.push_back(index_arg); 785 786 // Define the first (and only) variant of this arg. 787 value_arg.arg_type = eArgTypeValue; 788 value_arg.arg_repetition = eArgRepeatPlain; 789 790 // There is only one variant this argument could be; put it into the 791 // argument entry. 792 arg3.push_back(value_arg); 793 794 // Push the data for the first argument into the m_arguments vector. 795 m_arguments.push_back(arg1); 796 m_arguments.push_back(arg2); 797 m_arguments.push_back(arg3); 798 } 799 800 ~CommandObjectSettingsInsertBefore() override = default; 801 802 // Overrides base class's behavior where WantsCompletion = 803 // !WantsRawCommandString. 804 bool WantsCompletion() override { return true; } 805 806 void 807 HandleArgumentCompletion(CompletionRequest &request, 808 OptionElementVector &opt_element_vector) override { 809 // Attempting to complete variable name 810 if (request.GetCursorIndex() < 2) 811 CommandCompletions::InvokeCommonCompletionCallbacks( 812 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 813 request, nullptr); 814 } 815 816 protected: 817 bool DoExecute(llvm::StringRef command, 818 CommandReturnObject &result) override { 819 result.SetStatus(eReturnStatusSuccessFinishNoResult); 820 821 Args cmd_args(command); 822 const size_t argc = cmd_args.GetArgumentCount(); 823 824 if (argc < 3) { 825 result.AppendError("'settings insert-before' takes more arguments"); 826 result.SetStatus(eReturnStatusFailed); 827 return false; 828 } 829 830 const char *var_name = cmd_args.GetArgumentAtIndex(0); 831 if ((var_name == nullptr) || (var_name[0] == '\0')) { 832 result.AppendError("'settings insert-before' command requires a valid " 833 "variable name; No value supplied"); 834 result.SetStatus(eReturnStatusFailed); 835 return false; 836 } 837 838 // Split the raw command into var_name, index_value, and value triple. 839 llvm::StringRef var_value(command); 840 var_value = var_value.split(var_name).second.trim(); 841 842 Status error(GetDebugger().SetPropertyValue( 843 &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value)); 844 if (error.Fail()) { 845 result.AppendError(error.AsCString()); 846 result.SetStatus(eReturnStatusFailed); 847 return false; 848 } 849 850 return result.Succeeded(); 851 } 852 }; 853 854 // CommandObjectSettingInsertAfter 855 856 class CommandObjectSettingsInsertAfter : public CommandObjectRaw { 857 public: 858 CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter) 859 : CommandObjectRaw(interpreter, "settings insert-after", 860 "Insert one or more values into a debugger array " 861 "settings after the specified element index.") { 862 CommandArgumentEntry arg1; 863 CommandArgumentEntry arg2; 864 CommandArgumentEntry arg3; 865 CommandArgumentData var_name_arg; 866 CommandArgumentData index_arg; 867 CommandArgumentData value_arg; 868 869 // Define the first (and only) variant of this arg. 870 var_name_arg.arg_type = eArgTypeSettingVariableName; 871 var_name_arg.arg_repetition = eArgRepeatPlain; 872 873 // There is only one variant this argument could be; put it into the 874 // argument entry. 875 arg1.push_back(var_name_arg); 876 877 // Define the first (variant of this arg. 878 index_arg.arg_type = eArgTypeSettingIndex; 879 index_arg.arg_repetition = eArgRepeatPlain; 880 881 // There is only one variant this argument could be; put it into the 882 // argument entry. 883 arg2.push_back(index_arg); 884 885 // Define the first (and only) variant of this arg. 886 value_arg.arg_type = eArgTypeValue; 887 value_arg.arg_repetition = eArgRepeatPlain; 888 889 // There is only one variant this argument could be; put it into the 890 // argument entry. 891 arg3.push_back(value_arg); 892 893 // Push the data for the first argument into the m_arguments vector. 894 m_arguments.push_back(arg1); 895 m_arguments.push_back(arg2); 896 m_arguments.push_back(arg3); 897 } 898 899 ~CommandObjectSettingsInsertAfter() override = default; 900 901 // Overrides base class's behavior where WantsCompletion = 902 // !WantsRawCommandString. 903 bool WantsCompletion() override { return true; } 904 905 void 906 HandleArgumentCompletion(CompletionRequest &request, 907 OptionElementVector &opt_element_vector) override { 908 // Attempting to complete variable name 909 if (request.GetCursorIndex() < 2) 910 CommandCompletions::InvokeCommonCompletionCallbacks( 911 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 912 request, nullptr); 913 } 914 915 protected: 916 bool DoExecute(llvm::StringRef command, 917 CommandReturnObject &result) override { 918 result.SetStatus(eReturnStatusSuccessFinishNoResult); 919 920 Args cmd_args(command); 921 const size_t argc = cmd_args.GetArgumentCount(); 922 923 if (argc < 3) { 924 result.AppendError("'settings insert-after' takes more arguments"); 925 result.SetStatus(eReturnStatusFailed); 926 return false; 927 } 928 929 const char *var_name = cmd_args.GetArgumentAtIndex(0); 930 if ((var_name == nullptr) || (var_name[0] == '\0')) { 931 result.AppendError("'settings insert-after' command requires a valid " 932 "variable name; No value supplied"); 933 result.SetStatus(eReturnStatusFailed); 934 return false; 935 } 936 937 // Split the raw command into var_name, index_value, and value triple. 938 llvm::StringRef var_value(command); 939 var_value = var_value.split(var_name).second.trim(); 940 941 Status error(GetDebugger().SetPropertyValue( 942 &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value)); 943 if (error.Fail()) { 944 result.AppendError(error.AsCString()); 945 result.SetStatus(eReturnStatusFailed); 946 return false; 947 } 948 949 return result.Succeeded(); 950 } 951 }; 952 953 // CommandObjectSettingsAppend 954 955 class CommandObjectSettingsAppend : public CommandObjectRaw { 956 public: 957 CommandObjectSettingsAppend(CommandInterpreter &interpreter) 958 : CommandObjectRaw(interpreter, "settings append", 959 "Append one or more values to a debugger array, " 960 "dictionary, or string setting.") { 961 CommandArgumentEntry arg1; 962 CommandArgumentEntry arg2; 963 CommandArgumentData var_name_arg; 964 CommandArgumentData value_arg; 965 966 // Define the first (and only) variant of this arg. 967 var_name_arg.arg_type = eArgTypeSettingVariableName; 968 var_name_arg.arg_repetition = eArgRepeatPlain; 969 970 // There is only one variant this argument could be; put it into the 971 // argument entry. 972 arg1.push_back(var_name_arg); 973 974 // Define the first (and only) variant of this arg. 975 value_arg.arg_type = eArgTypeValue; 976 value_arg.arg_repetition = eArgRepeatPlain; 977 978 // There is only one variant this argument could be; put it into the 979 // argument entry. 980 arg2.push_back(value_arg); 981 982 // Push the data for the first argument into the m_arguments vector. 983 m_arguments.push_back(arg1); 984 m_arguments.push_back(arg2); 985 } 986 987 ~CommandObjectSettingsAppend() override = default; 988 989 // Overrides base class's behavior where WantsCompletion = 990 // !WantsRawCommandString. 991 bool WantsCompletion() override { return true; } 992 993 void 994 HandleArgumentCompletion(CompletionRequest &request, 995 OptionElementVector &opt_element_vector) override { 996 // Attempting to complete variable name 997 if (request.GetCursorIndex() < 2) 998 CommandCompletions::InvokeCommonCompletionCallbacks( 999 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 1000 request, nullptr); 1001 } 1002 1003 protected: 1004 bool DoExecute(llvm::StringRef command, 1005 CommandReturnObject &result) override { 1006 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1007 Args cmd_args(command); 1008 const size_t argc = cmd_args.GetArgumentCount(); 1009 1010 if (argc < 2) { 1011 result.AppendError("'settings append' takes more arguments"); 1012 result.SetStatus(eReturnStatusFailed); 1013 return false; 1014 } 1015 1016 const char *var_name = cmd_args.GetArgumentAtIndex(0); 1017 if ((var_name == nullptr) || (var_name[0] == '\0')) { 1018 result.AppendError("'settings append' command requires a valid variable " 1019 "name; No value supplied"); 1020 result.SetStatus(eReturnStatusFailed); 1021 return false; 1022 } 1023 1024 // Do not perform cmd_args.Shift() since StringRef is manipulating the raw 1025 // character string later on. 1026 1027 // Split the raw command into var_name and value pair. 1028 llvm::StringRef var_value(command); 1029 var_value = var_value.split(var_name).second.trim(); 1030 1031 Status error(GetDebugger().SetPropertyValue( 1032 &m_exe_ctx, eVarSetOperationAppend, var_name, var_value)); 1033 if (error.Fail()) { 1034 result.AppendError(error.AsCString()); 1035 result.SetStatus(eReturnStatusFailed); 1036 return false; 1037 } 1038 1039 return result.Succeeded(); 1040 } 1041 }; 1042 1043 // CommandObjectSettingsClear 1044 #define LLDB_OPTIONS_settings_clear 1045 #include "CommandOptions.inc" 1046 1047 class CommandObjectSettingsClear : public CommandObjectParsed { 1048 public: 1049 CommandObjectSettingsClear(CommandInterpreter &interpreter) 1050 : CommandObjectParsed( 1051 interpreter, "settings clear", 1052 "Clear a debugger setting array, dictionary, or string. " 1053 "If '-a' option is specified, it clears all settings.", nullptr) { 1054 CommandArgumentEntry arg; 1055 CommandArgumentData var_name_arg; 1056 1057 // Define the first (and only) variant of this arg. 1058 var_name_arg.arg_type = eArgTypeSettingVariableName; 1059 var_name_arg.arg_repetition = eArgRepeatPlain; 1060 1061 // There is only one variant this argument could be; put it into the 1062 // argument entry. 1063 arg.push_back(var_name_arg); 1064 1065 // Push the data for the first argument into the m_arguments vector. 1066 m_arguments.push_back(arg); 1067 } 1068 1069 ~CommandObjectSettingsClear() override = default; 1070 1071 void 1072 HandleArgumentCompletion(CompletionRequest &request, 1073 OptionElementVector &opt_element_vector) override { 1074 // Attempting to complete variable name 1075 if (request.GetCursorIndex() < 2) 1076 CommandCompletions::InvokeCommonCompletionCallbacks( 1077 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 1078 request, nullptr); 1079 } 1080 1081 Options *GetOptions() override { return &m_options; } 1082 1083 class CommandOptions : public Options { 1084 public: 1085 CommandOptions() = default; 1086 1087 ~CommandOptions() override = default; 1088 1089 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1090 ExecutionContext *execution_context) override { 1091 const int short_option = m_getopt_table[option_idx].val; 1092 switch (short_option) { 1093 case 'a': 1094 m_clear_all = true; 1095 break; 1096 default: 1097 llvm_unreachable("Unimplemented option"); 1098 } 1099 return Status(); 1100 } 1101 1102 void OptionParsingStarting(ExecutionContext *execution_context) override { 1103 m_clear_all = false; 1104 } 1105 1106 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1107 return llvm::makeArrayRef(g_settings_clear_options); 1108 } 1109 1110 bool m_clear_all = false; 1111 }; 1112 1113 protected: 1114 bool DoExecute(Args &command, CommandReturnObject &result) override { 1115 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1116 const size_t argc = command.GetArgumentCount(); 1117 1118 if (m_options.m_clear_all) { 1119 if (argc != 0) { 1120 result.AppendError("'settings clear --all' doesn't take any arguments"); 1121 result.SetStatus(eReturnStatusFailed); 1122 return false; 1123 } 1124 GetDebugger().GetValueProperties()->Clear(); 1125 return result.Succeeded(); 1126 } 1127 1128 if (argc != 1) { 1129 result.AppendError("'settings clear' takes exactly one argument"); 1130 result.SetStatus(eReturnStatusFailed); 1131 return false; 1132 } 1133 1134 const char *var_name = command.GetArgumentAtIndex(0); 1135 if ((var_name == nullptr) || (var_name[0] == '\0')) { 1136 result.AppendError("'settings clear' command requires a valid variable " 1137 "name; No value supplied"); 1138 result.SetStatus(eReturnStatusFailed); 1139 return false; 1140 } 1141 1142 Status error(GetDebugger().SetPropertyValue( 1143 &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef())); 1144 if (error.Fail()) { 1145 result.AppendError(error.AsCString()); 1146 result.SetStatus(eReturnStatusFailed); 1147 return false; 1148 } 1149 1150 return result.Succeeded(); 1151 } 1152 1153 private: 1154 CommandOptions m_options; 1155 }; 1156 1157 // CommandObjectMultiwordSettings 1158 1159 CommandObjectMultiwordSettings::CommandObjectMultiwordSettings( 1160 CommandInterpreter &interpreter) 1161 : CommandObjectMultiword(interpreter, "settings", 1162 "Commands for managing LLDB settings.", 1163 "settings <subcommand> [<command-options>]") { 1164 LoadSubCommand("set", 1165 CommandObjectSP(new CommandObjectSettingsSet(interpreter))); 1166 LoadSubCommand("show", 1167 CommandObjectSP(new CommandObjectSettingsShow(interpreter))); 1168 LoadSubCommand("list", 1169 CommandObjectSP(new CommandObjectSettingsList(interpreter))); 1170 LoadSubCommand("remove", 1171 CommandObjectSP(new CommandObjectSettingsRemove(interpreter))); 1172 LoadSubCommand("replace", CommandObjectSP( 1173 new CommandObjectSettingsReplace(interpreter))); 1174 LoadSubCommand( 1175 "insert-before", 1176 CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter))); 1177 LoadSubCommand( 1178 "insert-after", 1179 CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter))); 1180 LoadSubCommand("append", 1181 CommandObjectSP(new CommandObjectSettingsAppend(interpreter))); 1182 LoadSubCommand("clear", 1183 CommandObjectSP(new CommandObjectSettingsClear(interpreter))); 1184 LoadSubCommand("write", 1185 CommandObjectSP(new CommandObjectSettingsWrite(interpreter))); 1186 LoadSubCommand("read", 1187 CommandObjectSP(new CommandObjectSettingsRead(interpreter))); 1188 } 1189 1190 CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default; 1191