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