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