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