1 //===-- CommandObjectSettings.cpp -----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CommandObjectSettings.h" 10 11 #include "llvm/ADT/StringRef.h" 12 13 #include "lldb/Host/OptionParser.h" 14 #include "lldb/Interpreter/CommandCompletions.h" 15 #include "lldb/Interpreter/CommandInterpreter.h" 16 #include "lldb/Interpreter/CommandReturnObject.h" 17 #include "lldb/Interpreter/OptionValueProperties.h" 18 19 using namespace lldb; 20 using namespace lldb_private; 21 22 // CommandObjectSettingsSet 23 #define LLDB_OPTIONS_settings_set 24 #include "CommandOptions.inc" 25 26 class CommandObjectSettingsSet : public CommandObjectRaw { 27 public: 28 CommandObjectSettingsSet(CommandInterpreter &interpreter) 29 : CommandObjectRaw(interpreter, "settings set", 30 "Set the value of the specified debugger setting.") { 31 CommandArgumentEntry arg1; 32 CommandArgumentEntry arg2; 33 CommandArgumentData var_name_arg; 34 CommandArgumentData value_arg; 35 36 // Define the first (and only) variant of this arg. 37 var_name_arg.arg_type = eArgTypeSettingVariableName; 38 var_name_arg.arg_repetition = eArgRepeatPlain; 39 40 // There is only one variant this argument could be; put it into the 41 // argument entry. 42 arg1.push_back(var_name_arg); 43 44 // Define the first (and only) variant of this arg. 45 value_arg.arg_type = eArgTypeValue; 46 value_arg.arg_repetition = eArgRepeatPlain; 47 48 // There is only one variant this argument could be; put it into the 49 // argument entry. 50 arg2.push_back(value_arg); 51 52 // Push the data for the first argument into the m_arguments vector. 53 m_arguments.push_back(arg1); 54 m_arguments.push_back(arg2); 55 56 SetHelpLong( 57 "\nWhen setting a dictionary or array variable, you can set multiple entries \ 58 at once by giving the values to the set command. For example:" 59 R"( 60 61 (lldb) settings set target.run-args value1 value2 value3 62 (lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345 63 64 (lldb) settings show target.run-args 65 [0]: 'value1' 66 [1]: 'value2' 67 [3]: 'value3' 68 (lldb) settings show target.env-vars 69 'MYPATH=~/.:/usr/bin' 70 'SOME_ENV_VAR=12345' 71 72 )" 73 "Warning: The 'set' command re-sets the entire array or dictionary. If you \ 74 just want to add, remove or update individual values (or add something to \ 75 the end), use one of the other settings sub-commands: append, replace, \ 76 insert-before or insert-after."); 77 } 78 79 ~CommandObjectSettingsSet() override = default; 80 81 // Overrides base class's behavior where WantsCompletion = 82 // !WantsRawCommandString. 83 bool WantsCompletion() override { return true; } 84 85 Options *GetOptions() override { return &m_options; } 86 87 class CommandOptions : public Options { 88 public: 89 CommandOptions() = default; 90 91 ~CommandOptions() override = default; 92 93 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 94 ExecutionContext *execution_context) override { 95 Status error; 96 const int short_option = m_getopt_table[option_idx].val; 97 98 switch (short_option) { 99 case 'f': 100 m_force = true; 101 break; 102 case 'g': 103 m_global = true; 104 break; 105 case 'e': 106 m_exists = true; 107 break; 108 default: 109 llvm_unreachable("Unimplemented option"); 110 } 111 112 return error; 113 } 114 115 void OptionParsingStarting(ExecutionContext *execution_context) override { 116 m_global = false; 117 m_force = false; 118 m_exists = false; 119 } 120 121 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 122 return llvm::makeArrayRef(g_settings_set_options); 123 } 124 125 // Instance variables to hold the values for command options. 126 bool m_global = false; 127 bool m_force = false; 128 bool m_exists = false; 129 }; 130 131 void 132 HandleArgumentCompletion(CompletionRequest &request, 133 OptionElementVector &opt_element_vector) override { 134 135 const size_t argc = request.GetParsedLine().GetArgumentCount(); 136 const char *arg = nullptr; 137 size_t setting_var_idx; 138 for (setting_var_idx = 0; setting_var_idx < argc; ++setting_var_idx) { 139 arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx); 140 if (arg && arg[0] != '-') 141 break; // We found our setting variable name index 142 } 143 if (request.GetCursorIndex() == setting_var_idx) { 144 // Attempting to complete setting variable name 145 CommandCompletions::InvokeCommonCompletionCallbacks( 146 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 147 request, nullptr); 148 return; 149 } 150 arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()); 151 152 if (!arg) 153 return; 154 155 // Complete option name 156 if (arg[0] != '-') 157 return; 158 159 // Complete setting value 160 const char *setting_var_name = 161 request.GetParsedLine().GetArgumentAtIndex(setting_var_idx); 162 Status error; 163 lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue( 164 &m_exe_ctx, setting_var_name, false, error)); 165 if (!value_sp) 166 return; 167 value_sp->AutoComplete(m_interpreter, request); 168 } 169 170 protected: 171 bool DoExecute(llvm::StringRef command, 172 CommandReturnObject &result) override { 173 Args cmd_args(command); 174 175 // Process possible options. 176 if (!ParseOptions(cmd_args, result)) 177 return false; 178 179 const size_t min_argc = m_options.m_force ? 1 : 2; 180 const size_t argc = cmd_args.GetArgumentCount(); 181 182 if ((argc < min_argc) && (!m_options.m_global)) { 183 result.AppendError("'settings set' takes more arguments"); 184 return false; 185 } 186 187 const char *var_name = cmd_args.GetArgumentAtIndex(0); 188 if ((var_name == nullptr) || (var_name[0] == '\0')) { 189 result.AppendError( 190 "'settings set' command requires a valid variable name"); 191 return false; 192 } 193 194 // A missing value corresponds to clearing the setting when "force" is 195 // specified. 196 if (argc == 1 && m_options.m_force) { 197 Status error(GetDebugger().SetPropertyValue( 198 &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef())); 199 if (error.Fail()) { 200 result.AppendError(error.AsCString()); 201 return false; 202 } 203 return result.Succeeded(); 204 } 205 206 // Split the raw command into var_name and value pair. 207 llvm::StringRef var_value(command); 208 var_value = var_value.split(var_name).second.ltrim(); 209 210 Status error; 211 if (m_options.m_global) 212 error = GetDebugger().SetPropertyValue(nullptr, eVarSetOperationAssign, 213 var_name, var_value); 214 215 if (error.Success()) { 216 // FIXME this is the same issue as the one in commands script import 217 // we could be setting target.load-script-from-symbol-file which would 218 // cause Python scripts to be loaded, which could run LLDB commands (e.g. 219 // settings set target.process.python-os-plugin-path) and cause a crash 220 // if we did not clear the command's exe_ctx first 221 ExecutionContext exe_ctx(m_exe_ctx); 222 m_exe_ctx.Clear(); 223 error = GetDebugger().SetPropertyValue(&exe_ctx, eVarSetOperationAssign, 224 var_name, var_value); 225 } 226 227 if (error.Fail() && !m_options.m_exists) { 228 result.AppendError(error.AsCString()); 229 return false; 230 } 231 232 result.SetStatus(eReturnStatusSuccessFinishResult); 233 return result.Succeeded(); 234 } 235 236 private: 237 CommandOptions m_options; 238 }; 239 240 // CommandObjectSettingsShow -- Show current values 241 242 class CommandObjectSettingsShow : public CommandObjectParsed { 243 public: 244 CommandObjectSettingsShow(CommandInterpreter &interpreter) 245 : CommandObjectParsed(interpreter, "settings show", 246 "Show matching debugger settings and their current " 247 "values. Defaults to showing all settings.", 248 nullptr) { 249 CommandArgumentEntry arg1; 250 CommandArgumentData var_name_arg; 251 252 // Define the first (and only) variant of this arg. 253 var_name_arg.arg_type = eArgTypeSettingVariableName; 254 var_name_arg.arg_repetition = eArgRepeatOptional; 255 256 // There is only one variant this argument could be; put it into the 257 // argument entry. 258 arg1.push_back(var_name_arg); 259 260 // Push the data for the first argument into the m_arguments vector. 261 m_arguments.push_back(arg1); 262 } 263 264 ~CommandObjectSettingsShow() override = default; 265 266 void 267 HandleArgumentCompletion(CompletionRequest &request, 268 OptionElementVector &opt_element_vector) override { 269 CommandCompletions::InvokeCommonCompletionCallbacks( 270 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 271 request, nullptr); 272 } 273 274 protected: 275 bool DoExecute(Args &args, CommandReturnObject &result) override { 276 result.SetStatus(eReturnStatusSuccessFinishResult); 277 278 if (!args.empty()) { 279 for (const auto &arg : args) { 280 Status error(GetDebugger().DumpPropertyValue( 281 &m_exe_ctx, result.GetOutputStream(), arg.ref(), 282 OptionValue::eDumpGroupValue)); 283 if (error.Success()) { 284 result.GetOutputStream().EOL(); 285 } else { 286 result.AppendError(error.AsCString()); 287 } 288 } 289 } else { 290 GetDebugger().DumpAllPropertyValues(&m_exe_ctx, result.GetOutputStream(), 291 OptionValue::eDumpGroupValue); 292 } 293 294 return result.Succeeded(); 295 } 296 }; 297 298 // CommandObjectSettingsWrite -- Write settings to file 299 #define LLDB_OPTIONS_settings_write 300 #include "CommandOptions.inc" 301 302 class CommandObjectSettingsWrite : public CommandObjectParsed { 303 public: 304 CommandObjectSettingsWrite(CommandInterpreter &interpreter) 305 : CommandObjectParsed( 306 interpreter, "settings export", 307 "Write matching debugger settings and their " 308 "current values to a file that can be read in with " 309 "\"settings read\". Defaults to writing all settings.", 310 nullptr) { 311 CommandArgumentEntry arg1; 312 CommandArgumentData var_name_arg; 313 314 // Define the first (and only) variant of this arg. 315 var_name_arg.arg_type = eArgTypeSettingVariableName; 316 var_name_arg.arg_repetition = eArgRepeatOptional; 317 318 // There is only one variant this argument could be; put it into the 319 // argument entry. 320 arg1.push_back(var_name_arg); 321 322 // Push the data for the first argument into the m_arguments vector. 323 m_arguments.push_back(arg1); 324 } 325 326 ~CommandObjectSettingsWrite() override = default; 327 328 Options *GetOptions() override { return &m_options; } 329 330 class CommandOptions : public Options { 331 public: 332 CommandOptions() = default; 333 334 ~CommandOptions() override = default; 335 336 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 337 ExecutionContext *execution_context) override { 338 Status error; 339 const int short_option = m_getopt_table[option_idx].val; 340 341 switch (short_option) { 342 case 'f': 343 m_filename.assign(std::string(option_arg)); 344 break; 345 case 'a': 346 m_append = true; 347 break; 348 default: 349 llvm_unreachable("Unimplemented option"); 350 } 351 352 return error; 353 } 354 355 void OptionParsingStarting(ExecutionContext *execution_context) override { 356 m_filename.clear(); 357 m_append = false; 358 } 359 360 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 361 return llvm::makeArrayRef(g_settings_write_options); 362 } 363 364 // Instance variables to hold the values for command options. 365 std::string m_filename; 366 bool m_append = false; 367 }; 368 369 protected: 370 bool DoExecute(Args &args, CommandReturnObject &result) override { 371 FileSpec file_spec(m_options.m_filename); 372 FileSystem::Instance().Resolve(file_spec); 373 std::string path(file_spec.GetPath()); 374 auto options = File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate; 375 if (m_options.m_append) 376 options |= File::eOpenOptionAppend; 377 else 378 options |= File::eOpenOptionTruncate; 379 380 StreamFile out_file(path.c_str(), options, 381 lldb::eFilePermissionsFileDefault); 382 383 if (!out_file.GetFile().IsValid()) { 384 result.AppendErrorWithFormat("%s: unable to write to file", path.c_str()); 385 return false; 386 } 387 388 // Exporting should not be context sensitive. 389 ExecutionContext clean_ctx; 390 391 if (args.empty()) { 392 GetDebugger().DumpAllPropertyValues(&clean_ctx, out_file, 393 OptionValue::eDumpGroupExport); 394 return result.Succeeded(); 395 } 396 397 for (const auto &arg : args) { 398 Status error(GetDebugger().DumpPropertyValue( 399 &clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport)); 400 if (!error.Success()) { 401 result.AppendError(error.AsCString()); 402 } 403 } 404 405 return result.Succeeded(); 406 } 407 408 private: 409 CommandOptions m_options; 410 }; 411 412 // CommandObjectSettingsRead -- Read settings from file 413 #define LLDB_OPTIONS_settings_read 414 #include "CommandOptions.inc" 415 416 class CommandObjectSettingsRead : public CommandObjectParsed { 417 public: 418 CommandObjectSettingsRead(CommandInterpreter &interpreter) 419 : CommandObjectParsed( 420 interpreter, "settings read", 421 "Read settings previously saved to a file with \"settings write\".", 422 nullptr) {} 423 424 ~CommandObjectSettingsRead() override = default; 425 426 Options *GetOptions() override { return &m_options; } 427 428 class CommandOptions : public Options { 429 public: 430 CommandOptions() = default; 431 432 ~CommandOptions() override = default; 433 434 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 435 ExecutionContext *execution_context) override { 436 Status error; 437 const int short_option = m_getopt_table[option_idx].val; 438 439 switch (short_option) { 440 case 'f': 441 m_filename.assign(std::string(option_arg)); 442 break; 443 default: 444 llvm_unreachable("Unimplemented option"); 445 } 446 447 return error; 448 } 449 450 void OptionParsingStarting(ExecutionContext *execution_context) override { 451 m_filename.clear(); 452 } 453 454 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 455 return llvm::makeArrayRef(g_settings_read_options); 456 } 457 458 // Instance variables to hold the values for command options. 459 std::string m_filename; 460 }; 461 462 protected: 463 bool DoExecute(Args &command, CommandReturnObject &result) override { 464 FileSpec file(m_options.m_filename); 465 FileSystem::Instance().Resolve(file); 466 CommandInterpreterRunOptions options; 467 options.SetAddToHistory(false); 468 options.SetEchoCommands(false); 469 options.SetPrintResults(true); 470 options.SetPrintErrors(true); 471 options.SetStopOnError(false); 472 m_interpreter.HandleCommandsFromFile(file, options, result); 473 return result.Succeeded(); 474 } 475 476 private: 477 CommandOptions m_options; 478 }; 479 480 // CommandObjectSettingsList -- List settable variables 481 482 class CommandObjectSettingsList : public CommandObjectParsed { 483 public: 484 CommandObjectSettingsList(CommandInterpreter &interpreter) 485 : CommandObjectParsed(interpreter, "settings list", 486 "List and describe matching debugger settings. " 487 "Defaults to all listing all settings.", 488 nullptr) { 489 CommandArgumentEntry arg; 490 CommandArgumentData var_name_arg; 491 CommandArgumentData prefix_name_arg; 492 493 // Define the first variant of this arg. 494 var_name_arg.arg_type = eArgTypeSettingVariableName; 495 var_name_arg.arg_repetition = eArgRepeatOptional; 496 497 // Define the second variant of this arg. 498 prefix_name_arg.arg_type = eArgTypeSettingPrefix; 499 prefix_name_arg.arg_repetition = eArgRepeatOptional; 500 501 arg.push_back(var_name_arg); 502 arg.push_back(prefix_name_arg); 503 504 // Push the data for the first argument into the m_arguments vector. 505 m_arguments.push_back(arg); 506 } 507 508 ~CommandObjectSettingsList() override = default; 509 510 void 511 HandleArgumentCompletion(CompletionRequest &request, 512 OptionElementVector &opt_element_vector) override { 513 CommandCompletions::InvokeCommonCompletionCallbacks( 514 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 515 request, nullptr); 516 } 517 518 protected: 519 bool DoExecute(Args &args, CommandReturnObject &result) override { 520 result.SetStatus(eReturnStatusSuccessFinishResult); 521 522 const bool will_modify = false; 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, will_modify, 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 CommandCompletions::InvokeCommonCompletionCallbacks( 599 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 600 request, 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 CommandCompletions::InvokeCommonCompletionCallbacks( 707 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 708 request, 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 CommandCompletions::InvokeCommonCompletionCallbacks( 799 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 800 request, 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 CommandCompletions::InvokeCommonCompletionCallbacks( 895 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 896 request, 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 CommandCompletions::InvokeCommonCompletionCallbacks( 980 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 981 request, 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 CommandCompletions::InvokeCommonCompletionCallbacks( 1055 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 1056 request, 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::makeArrayRef(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