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