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