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( 165 m_interpreter.GetDebugger().GetPropertyValue( 166 &m_exe_ctx, setting_var_name, false, error)); 167 if (value_sp) { 168 value_sp->AutoComplete(m_interpreter, request); 169 } 170 } 171 } 172 } 173 return request.GetNumberOfMatches(); 174 } 175 176 protected: 177 bool DoExecute(llvm::StringRef command, 178 CommandReturnObject &result) override { 179 Args cmd_args(command); 180 181 // Process possible options. 182 if (!ParseOptions(cmd_args, result)) 183 return false; 184 185 const size_t min_argc = m_options.m_force ? 1 : 2; 186 const size_t argc = cmd_args.GetArgumentCount(); 187 188 if ((argc < min_argc) && (!m_options.m_global)) { 189 result.AppendError("'settings set' takes more arguments"); 190 result.SetStatus(eReturnStatusFailed); 191 return false; 192 } 193 194 const char *var_name = cmd_args.GetArgumentAtIndex(0); 195 if ((var_name == nullptr) || (var_name[0] == '\0')) { 196 result.AppendError( 197 "'settings set' command requires a valid variable name"); 198 result.SetStatus(eReturnStatusFailed); 199 return false; 200 } 201 202 // A missing value corresponds to clearing the setting when "force" is 203 // specified. 204 if (argc == 1 && m_options.m_force) { 205 Status error(m_interpreter.GetDebugger().SetPropertyValue( 206 &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef())); 207 if (error.Fail()) { 208 result.AppendError(error.AsCString()); 209 result.SetStatus(eReturnStatusFailed); 210 return false; 211 } 212 return result.Succeeded(); 213 } 214 215 // Split the raw command into var_name and value pair. 216 llvm::StringRef raw_str(command); 217 std::string var_value_string = raw_str.split(var_name).second.str(); 218 const char *var_value_cstr = 219 Args::StripSpaces(var_value_string, true, false, false); 220 221 Status error; 222 if (m_options.m_global) { 223 error = m_interpreter.GetDebugger().SetPropertyValue( 224 nullptr, eVarSetOperationAssign, var_name, var_value_cstr); 225 } 226 227 if (error.Success()) { 228 // FIXME this is the same issue as the one in commands script import 229 // we could be setting target.load-script-from-symbol-file which would 230 // cause Python scripts to be loaded, which could run LLDB commands (e.g. 231 // settings set target.process.python-os-plugin-path) and cause a crash 232 // if we did not clear the command's exe_ctx first 233 ExecutionContext exe_ctx(m_exe_ctx); 234 m_exe_ctx.Clear(); 235 error = m_interpreter.GetDebugger().SetPropertyValue( 236 &exe_ctx, eVarSetOperationAssign, var_name, var_value_cstr); 237 } 238 239 if (error.Fail()) { 240 result.AppendError(error.AsCString()); 241 result.SetStatus(eReturnStatusFailed); 242 return false; 243 } else { 244 result.SetStatus(eReturnStatusSuccessFinishResult); 245 } 246 247 return result.Succeeded(); 248 } 249 250 private: 251 CommandOptions m_options; 252 }; 253 254 // CommandObjectSettingsShow -- Show current values 255 256 class CommandObjectSettingsShow : public CommandObjectParsed { 257 public: 258 CommandObjectSettingsShow(CommandInterpreter &interpreter) 259 : CommandObjectParsed(interpreter, "settings show", 260 "Show matching debugger settings and their current " 261 "values. Defaults to showing all settings.", 262 nullptr) { 263 CommandArgumentEntry arg1; 264 CommandArgumentData var_name_arg; 265 266 // Define the first (and only) variant of this arg. 267 var_name_arg.arg_type = eArgTypeSettingVariableName; 268 var_name_arg.arg_repetition = eArgRepeatOptional; 269 270 // There is only one variant this argument could be; put it into the 271 // argument entry. 272 arg1.push_back(var_name_arg); 273 274 // Push the data for the first argument into the m_arguments vector. 275 m_arguments.push_back(arg1); 276 } 277 278 ~CommandObjectSettingsShow() override = default; 279 280 int HandleArgumentCompletion( 281 CompletionRequest &request, 282 OptionElementVector &opt_element_vector) override { 283 CommandCompletions::InvokeCommonCompletionCallbacks( 284 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 285 request, nullptr); 286 return request.GetNumberOfMatches(); 287 } 288 289 protected: 290 bool DoExecute(Args &args, CommandReturnObject &result) override { 291 result.SetStatus(eReturnStatusSuccessFinishResult); 292 293 if (!args.empty()) { 294 for (const auto &arg : args) { 295 Status error(m_interpreter.GetDebugger().DumpPropertyValue( 296 &m_exe_ctx, result.GetOutputStream(), arg.ref, 297 OptionValue::eDumpGroupValue)); 298 if (error.Success()) { 299 result.GetOutputStream().EOL(); 300 } else { 301 result.AppendError(error.AsCString()); 302 result.SetStatus(eReturnStatusFailed); 303 } 304 } 305 } else { 306 m_interpreter.GetDebugger().DumpAllPropertyValues( 307 &m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue); 308 } 309 310 return result.Succeeded(); 311 } 312 }; 313 314 // CommandObjectSettingsWrite -- Write settings to file 315 316 static constexpr OptionDefinition g_settings_write_options[] = { 317 // clang-format off 318 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the settings." }, 319 { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved settings file if it exists."}, 320 // clang-format on 321 }; 322 323 class CommandObjectSettingsWrite : public CommandObjectParsed { 324 public: 325 CommandObjectSettingsWrite(CommandInterpreter &interpreter) 326 : CommandObjectParsed( 327 interpreter, "settings export", 328 "Write matching debugger settings and their " 329 "current values to a file that can be read in with " 330 "\"settings read\". Defaults to writing all settings.", 331 nullptr), 332 m_options() { 333 CommandArgumentEntry arg1; 334 CommandArgumentData var_name_arg; 335 336 // Define the first (and only) variant of this arg. 337 var_name_arg.arg_type = eArgTypeSettingVariableName; 338 var_name_arg.arg_repetition = eArgRepeatOptional; 339 340 // There is only one variant this argument could be; put it into the 341 // argument entry. 342 arg1.push_back(var_name_arg); 343 344 // Push the data for the first argument into the m_arguments vector. 345 m_arguments.push_back(arg1); 346 } 347 348 ~CommandObjectSettingsWrite() override = default; 349 350 Options *GetOptions() override { return &m_options; } 351 352 class CommandOptions : public Options { 353 public: 354 CommandOptions() : Options() {} 355 356 ~CommandOptions() override = default; 357 358 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 359 ExecutionContext *execution_context) override { 360 Status error; 361 const int short_option = m_getopt_table[option_idx].val; 362 363 switch (short_option) { 364 case 'f': 365 m_filename.assign(option_arg); 366 break; 367 case 'a': 368 m_append = true; 369 break; 370 default: 371 error.SetErrorStringWithFormat("unrecognized option '%c'", 372 short_option); 373 break; 374 } 375 376 return error; 377 } 378 379 void OptionParsingStarting(ExecutionContext *execution_context) override { 380 m_filename.clear(); 381 m_append = false; 382 } 383 384 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 385 return llvm::makeArrayRef(g_settings_write_options); 386 } 387 388 // Instance variables to hold the values for command options. 389 std::string m_filename; 390 bool m_append = false; 391 }; 392 393 protected: 394 bool DoExecute(Args &args, CommandReturnObject &result) override { 395 FileSpec file_spec(m_options.m_filename); 396 FileSystem::Instance().Resolve(file_spec); 397 std::string path(file_spec.GetPath()); 398 uint32_t options = File::OpenOptions::eOpenOptionWrite | 399 File::OpenOptions::eOpenOptionCanCreate; 400 if (m_options.m_append) 401 options |= File::OpenOptions::eOpenOptionAppend; 402 else 403 options |= File::OpenOptions::eOpenOptionTruncate; 404 405 StreamFile out_file(path.c_str(), options, 406 lldb::eFilePermissionsFileDefault); 407 408 if (!out_file.GetFile().IsValid()) { 409 result.AppendErrorWithFormat("%s: unable to write to file", path.c_str()); 410 result.SetStatus(eReturnStatusFailed); 411 return false; 412 } 413 414 // Exporting should not be context sensitive. 415 ExecutionContext clean_ctx; 416 417 if (args.empty()) { 418 m_interpreter.GetDebugger().DumpAllPropertyValues( 419 &clean_ctx, out_file, OptionValue::eDumpGroupExport); 420 return result.Succeeded(); 421 } 422 423 for (const auto &arg : args) { 424 Status error(m_interpreter.GetDebugger().DumpPropertyValue( 425 &clean_ctx, out_file, arg.ref, OptionValue::eDumpGroupExport)); 426 if (!error.Success()) { 427 result.AppendError(error.AsCString()); 428 result.SetStatus(eReturnStatusFailed); 429 } 430 } 431 432 return result.Succeeded(); 433 } 434 435 private: 436 CommandOptions m_options; 437 }; 438 439 // CommandObjectSettingsRead -- Read settings from file 440 441 static constexpr OptionDefinition g_settings_read_options[] = { 442 // clang-format off 443 {LLDB_OPT_SET_ALL, true, "file",'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, 444 // clang-format on 445 }; 446 447 class CommandObjectSettingsRead : public CommandObjectParsed { 448 public: 449 CommandObjectSettingsRead(CommandInterpreter &interpreter) 450 : CommandObjectParsed( 451 interpreter, "settings read", 452 "Read settings previously saved to a file with \"settings write\".", 453 nullptr), 454 m_options() {} 455 456 ~CommandObjectSettingsRead() override = default; 457 458 Options *GetOptions() override { return &m_options; } 459 460 class CommandOptions : public Options { 461 public: 462 CommandOptions() : Options() {} 463 464 ~CommandOptions() override = default; 465 466 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 467 ExecutionContext *execution_context) override { 468 Status error; 469 const int short_option = m_getopt_table[option_idx].val; 470 471 switch (short_option) { 472 case 'f': 473 m_filename.assign(option_arg); 474 break; 475 default: 476 error.SetErrorStringWithFormat("unrecognized option '%c'", 477 short_option); 478 break; 479 } 480 481 return error; 482 } 483 484 void OptionParsingStarting(ExecutionContext *execution_context) override { 485 m_filename.clear(); 486 } 487 488 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 489 return llvm::makeArrayRef(g_settings_read_options); 490 } 491 492 // Instance variables to hold the values for command options. 493 std::string m_filename; 494 }; 495 496 protected: 497 bool DoExecute(Args &command, CommandReturnObject &result) override { 498 FileSpec file(m_options.m_filename); 499 FileSystem::Instance().Resolve(file); 500 ExecutionContext clean_ctx; 501 CommandInterpreterRunOptions options; 502 options.SetAddToHistory(false); 503 options.SetEchoCommands(false); 504 options.SetPrintResults(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 m_interpreter.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 m_interpreter.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(m_interpreter.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(m_interpreter.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(m_interpreter.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(m_interpreter.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(m_interpreter.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(m_interpreter.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