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