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