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