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