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 // CommandObjectSettingsList -- List settable variables 325 //------------------------------------------------------------------------- 326 327 class CommandObjectSettingsList : public CommandObjectParsed { 328 public: 329 CommandObjectSettingsList(CommandInterpreter &interpreter) 330 : CommandObjectParsed(interpreter, "settings list", 331 "List and describe matching debugger settings. " 332 "Defaults to all listing all settings.", 333 nullptr) { 334 CommandArgumentEntry arg; 335 CommandArgumentData var_name_arg; 336 CommandArgumentData prefix_name_arg; 337 338 // Define the first variant of this arg. 339 var_name_arg.arg_type = eArgTypeSettingVariableName; 340 var_name_arg.arg_repetition = eArgRepeatOptional; 341 342 // Define the second variant of this arg. 343 prefix_name_arg.arg_type = eArgTypeSettingPrefix; 344 prefix_name_arg.arg_repetition = eArgRepeatOptional; 345 346 arg.push_back(var_name_arg); 347 arg.push_back(prefix_name_arg); 348 349 // Push the data for the first argument into the m_arguments vector. 350 m_arguments.push_back(arg); 351 } 352 353 ~CommandObjectSettingsList() override = default; 354 355 int HandleArgumentCompletion( 356 CompletionRequest &request, 357 OptionElementVector &opt_element_vector) override { 358 CommandCompletions::InvokeCommonCompletionCallbacks( 359 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 360 request, nullptr); 361 return request.GetNumberOfMatches(); 362 } 363 364 protected: 365 bool DoExecute(Args &args, CommandReturnObject &result) override { 366 result.SetStatus(eReturnStatusSuccessFinishResult); 367 368 const bool will_modify = false; 369 const size_t argc = args.GetArgumentCount(); 370 if (argc > 0) { 371 const bool dump_qualified_name = true; 372 373 // TODO: Convert to StringRef based enumeration. Requires converting 374 // GetPropertyAtPath first. 375 for (size_t i = 0; i < argc; ++i) { 376 const char *property_path = args.GetArgumentAtIndex(i); 377 378 const Property *property = 379 m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath( 380 &m_exe_ctx, will_modify, property_path); 381 382 if (property) { 383 property->DumpDescription(m_interpreter, result.GetOutputStream(), 0, 384 dump_qualified_name); 385 } else { 386 result.AppendErrorWithFormat("invalid property path '%s'", 387 property_path); 388 result.SetStatus(eReturnStatusFailed); 389 } 390 } 391 } else { 392 m_interpreter.GetDebugger().DumpAllDescriptions(m_interpreter, 393 result.GetOutputStream()); 394 } 395 396 return result.Succeeded(); 397 } 398 }; 399 400 //------------------------------------------------------------------------- 401 // CommandObjectSettingsRemove 402 //------------------------------------------------------------------------- 403 404 class CommandObjectSettingsRemove : public CommandObjectRaw { 405 public: 406 CommandObjectSettingsRemove(CommandInterpreter &interpreter) 407 : CommandObjectRaw(interpreter, "settings remove", 408 "Remove a value from a setting, specified by array " 409 "index or dictionary key.") { 410 CommandArgumentEntry arg1; 411 CommandArgumentEntry arg2; 412 CommandArgumentData var_name_arg; 413 CommandArgumentData index_arg; 414 CommandArgumentData key_arg; 415 416 // Define the first (and only) variant of this arg. 417 var_name_arg.arg_type = eArgTypeSettingVariableName; 418 var_name_arg.arg_repetition = eArgRepeatPlain; 419 420 // There is only one variant this argument could be; put it into the 421 // argument entry. 422 arg1.push_back(var_name_arg); 423 424 // Define the first variant of this arg. 425 index_arg.arg_type = eArgTypeSettingIndex; 426 index_arg.arg_repetition = eArgRepeatPlain; 427 428 // Define the second variant of this arg. 429 key_arg.arg_type = eArgTypeSettingKey; 430 key_arg.arg_repetition = eArgRepeatPlain; 431 432 // Push both variants into this arg 433 arg2.push_back(index_arg); 434 arg2.push_back(key_arg); 435 436 // Push the data for the first argument into the m_arguments vector. 437 m_arguments.push_back(arg1); 438 m_arguments.push_back(arg2); 439 } 440 441 ~CommandObjectSettingsRemove() override = default; 442 443 int HandleArgumentCompletion( 444 CompletionRequest &request, 445 OptionElementVector &opt_element_vector) override { 446 if (request.GetCursorIndex() < 2) 447 CommandCompletions::InvokeCommonCompletionCallbacks( 448 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 449 request, nullptr); 450 return request.GetNumberOfMatches(); 451 } 452 453 protected: 454 bool DoExecute(llvm::StringRef command, 455 CommandReturnObject &result) override { 456 result.SetStatus(eReturnStatusSuccessFinishNoResult); 457 458 Args cmd_args(command); 459 460 // Process possible options. 461 if (!ParseOptions(cmd_args, result)) 462 return false; 463 464 const size_t argc = cmd_args.GetArgumentCount(); 465 if (argc == 0) { 466 result.AppendError("'settings set' takes an array or dictionary item, or " 467 "an array followed by one or more indexes, or a " 468 "dictionary followed by one or more key names to " 469 "remove"); 470 result.SetStatus(eReturnStatusFailed); 471 return false; 472 } 473 474 const char *var_name = cmd_args.GetArgumentAtIndex(0); 475 if ((var_name == nullptr) || (var_name[0] == '\0')) { 476 result.AppendError( 477 "'settings set' command requires a valid variable name"); 478 result.SetStatus(eReturnStatusFailed); 479 return false; 480 } 481 482 // Split the raw command into var_name and value pair. 483 llvm::StringRef raw_str(command); 484 std::string var_value_string = raw_str.split(var_name).second.str(); 485 const char *var_value_cstr = 486 Args::StripSpaces(var_value_string, true, true, false); 487 488 Status error(m_interpreter.GetDebugger().SetPropertyValue( 489 &m_exe_ctx, eVarSetOperationRemove, var_name, var_value_cstr)); 490 if (error.Fail()) { 491 result.AppendError(error.AsCString()); 492 result.SetStatus(eReturnStatusFailed); 493 return false; 494 } 495 496 return result.Succeeded(); 497 } 498 }; 499 500 //------------------------------------------------------------------------- 501 // CommandObjectSettingsReplace 502 //------------------------------------------------------------------------- 503 504 class CommandObjectSettingsReplace : public CommandObjectRaw { 505 public: 506 CommandObjectSettingsReplace(CommandInterpreter &interpreter) 507 : CommandObjectRaw(interpreter, "settings replace", 508 "Replace the debugger setting value specified by " 509 "array index or dictionary key.") { 510 CommandArgumentEntry arg1; 511 CommandArgumentEntry arg2; 512 CommandArgumentEntry arg3; 513 CommandArgumentData var_name_arg; 514 CommandArgumentData index_arg; 515 CommandArgumentData key_arg; 516 CommandArgumentData value_arg; 517 518 // Define the first (and only) variant of this arg. 519 var_name_arg.arg_type = eArgTypeSettingVariableName; 520 var_name_arg.arg_repetition = eArgRepeatPlain; 521 522 // There is only one variant this argument could be; put it into the 523 // argument entry. 524 arg1.push_back(var_name_arg); 525 526 // Define the first (variant of this arg. 527 index_arg.arg_type = eArgTypeSettingIndex; 528 index_arg.arg_repetition = eArgRepeatPlain; 529 530 // Define the second (variant of this arg. 531 key_arg.arg_type = eArgTypeSettingKey; 532 key_arg.arg_repetition = eArgRepeatPlain; 533 534 // Put both variants into this arg 535 arg2.push_back(index_arg); 536 arg2.push_back(key_arg); 537 538 // Define the first (and only) variant of this arg. 539 value_arg.arg_type = eArgTypeValue; 540 value_arg.arg_repetition = eArgRepeatPlain; 541 542 // There is only one variant this argument could be; put it into the 543 // argument entry. 544 arg3.push_back(value_arg); 545 546 // Push the data for the first argument into the m_arguments vector. 547 m_arguments.push_back(arg1); 548 m_arguments.push_back(arg2); 549 m_arguments.push_back(arg3); 550 } 551 552 ~CommandObjectSettingsReplace() override = default; 553 554 // Overrides base class's behavior where WantsCompletion = 555 // !WantsRawCommandString. 556 bool WantsCompletion() override { return true; } 557 558 int HandleArgumentCompletion( 559 CompletionRequest &request, 560 OptionElementVector &opt_element_vector) override { 561 // Attempting to complete variable name 562 if (request.GetCursorIndex() < 2) 563 CommandCompletions::InvokeCommonCompletionCallbacks( 564 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 565 request, nullptr); 566 567 return request.GetNumberOfMatches(); 568 } 569 570 protected: 571 bool DoExecute(llvm::StringRef command, 572 CommandReturnObject &result) override { 573 result.SetStatus(eReturnStatusSuccessFinishNoResult); 574 575 Args cmd_args(command); 576 const char *var_name = cmd_args.GetArgumentAtIndex(0); 577 if ((var_name == nullptr) || (var_name[0] == '\0')) { 578 result.AppendError("'settings replace' command requires a valid variable " 579 "name; No value supplied"); 580 result.SetStatus(eReturnStatusFailed); 581 return false; 582 } 583 584 // Split the raw command into var_name, index_value, and value triple. 585 llvm::StringRef raw_str(command); 586 std::string var_value_string = raw_str.split(var_name).second.str(); 587 const char *var_value_cstr = 588 Args::StripSpaces(var_value_string, true, true, false); 589 590 Status error(m_interpreter.GetDebugger().SetPropertyValue( 591 &m_exe_ctx, eVarSetOperationReplace, var_name, var_value_cstr)); 592 if (error.Fail()) { 593 result.AppendError(error.AsCString()); 594 result.SetStatus(eReturnStatusFailed); 595 return false; 596 } else { 597 result.SetStatus(eReturnStatusSuccessFinishNoResult); 598 } 599 600 return result.Succeeded(); 601 } 602 }; 603 604 //------------------------------------------------------------------------- 605 // CommandObjectSettingsInsertBefore 606 //------------------------------------------------------------------------- 607 608 class CommandObjectSettingsInsertBefore : public CommandObjectRaw { 609 public: 610 CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter) 611 : CommandObjectRaw(interpreter, "settings insert-before", 612 "Insert one or more values into an debugger array " 613 "setting immediately before the specified element " 614 "index.") { 615 CommandArgumentEntry arg1; 616 CommandArgumentEntry arg2; 617 CommandArgumentEntry arg3; 618 CommandArgumentData var_name_arg; 619 CommandArgumentData index_arg; 620 CommandArgumentData value_arg; 621 622 // Define the first (and only) variant of this arg. 623 var_name_arg.arg_type = eArgTypeSettingVariableName; 624 var_name_arg.arg_repetition = eArgRepeatPlain; 625 626 // There is only one variant this argument could be; put it into the 627 // argument entry. 628 arg1.push_back(var_name_arg); 629 630 // Define the first (variant of this arg. 631 index_arg.arg_type = eArgTypeSettingIndex; 632 index_arg.arg_repetition = eArgRepeatPlain; 633 634 // There is only one variant this argument could be; put it into the 635 // argument entry. 636 arg2.push_back(index_arg); 637 638 // Define the first (and only) variant of this arg. 639 value_arg.arg_type = eArgTypeValue; 640 value_arg.arg_repetition = eArgRepeatPlain; 641 642 // There is only one variant this argument could be; put it into the 643 // argument entry. 644 arg3.push_back(value_arg); 645 646 // Push the data for the first argument into the m_arguments vector. 647 m_arguments.push_back(arg1); 648 m_arguments.push_back(arg2); 649 m_arguments.push_back(arg3); 650 } 651 652 ~CommandObjectSettingsInsertBefore() override = default; 653 654 // Overrides base class's behavior where WantsCompletion = 655 // !WantsRawCommandString. 656 bool WantsCompletion() override { return true; } 657 658 int HandleArgumentCompletion( 659 CompletionRequest &request, 660 OptionElementVector &opt_element_vector) override { 661 // Attempting to complete variable name 662 if (request.GetCursorIndex() < 2) 663 CommandCompletions::InvokeCommonCompletionCallbacks( 664 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 665 request, nullptr); 666 667 return request.GetNumberOfMatches(); 668 } 669 670 protected: 671 bool DoExecute(llvm::StringRef command, 672 CommandReturnObject &result) override { 673 result.SetStatus(eReturnStatusSuccessFinishNoResult); 674 675 Args cmd_args(command); 676 const size_t argc = cmd_args.GetArgumentCount(); 677 678 if (argc < 3) { 679 result.AppendError("'settings insert-before' takes more arguments"); 680 result.SetStatus(eReturnStatusFailed); 681 return false; 682 } 683 684 const char *var_name = cmd_args.GetArgumentAtIndex(0); 685 if ((var_name == nullptr) || (var_name[0] == '\0')) { 686 result.AppendError("'settings insert-before' command requires a valid " 687 "variable name; No value supplied"); 688 result.SetStatus(eReturnStatusFailed); 689 return false; 690 } 691 692 // Split the raw command into var_name, index_value, and value triple. 693 llvm::StringRef raw_str(command); 694 std::string var_value_string = raw_str.split(var_name).second.str(); 695 const char *var_value_cstr = 696 Args::StripSpaces(var_value_string, true, true, false); 697 698 Status error(m_interpreter.GetDebugger().SetPropertyValue( 699 &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value_cstr)); 700 if (error.Fail()) { 701 result.AppendError(error.AsCString()); 702 result.SetStatus(eReturnStatusFailed); 703 return false; 704 } 705 706 return result.Succeeded(); 707 } 708 }; 709 710 //------------------------------------------------------------------------- 711 // CommandObjectSettingInsertAfter 712 //------------------------------------------------------------------------- 713 714 class CommandObjectSettingsInsertAfter : public CommandObjectRaw { 715 public: 716 CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter) 717 : CommandObjectRaw(interpreter, "settings insert-after", 718 "Insert one or more values into a debugger array " 719 "settings after the specified element index.") { 720 CommandArgumentEntry arg1; 721 CommandArgumentEntry arg2; 722 CommandArgumentEntry arg3; 723 CommandArgumentData var_name_arg; 724 CommandArgumentData index_arg; 725 CommandArgumentData value_arg; 726 727 // Define the first (and only) variant of this arg. 728 var_name_arg.arg_type = eArgTypeSettingVariableName; 729 var_name_arg.arg_repetition = eArgRepeatPlain; 730 731 // There is only one variant this argument could be; put it into the 732 // argument entry. 733 arg1.push_back(var_name_arg); 734 735 // Define the first (variant of this arg. 736 index_arg.arg_type = eArgTypeSettingIndex; 737 index_arg.arg_repetition = eArgRepeatPlain; 738 739 // There is only one variant this argument could be; put it into the 740 // argument entry. 741 arg2.push_back(index_arg); 742 743 // Define the first (and only) variant of this arg. 744 value_arg.arg_type = eArgTypeValue; 745 value_arg.arg_repetition = eArgRepeatPlain; 746 747 // There is only one variant this argument could be; put it into the 748 // argument entry. 749 arg3.push_back(value_arg); 750 751 // Push the data for the first argument into the m_arguments vector. 752 m_arguments.push_back(arg1); 753 m_arguments.push_back(arg2); 754 m_arguments.push_back(arg3); 755 } 756 757 ~CommandObjectSettingsInsertAfter() override = default; 758 759 // Overrides base class's behavior where WantsCompletion = 760 // !WantsRawCommandString. 761 bool WantsCompletion() override { return true; } 762 763 int HandleArgumentCompletion( 764 CompletionRequest &request, 765 OptionElementVector &opt_element_vector) override { 766 // Attempting to complete variable name 767 if (request.GetCursorIndex() < 2) 768 CommandCompletions::InvokeCommonCompletionCallbacks( 769 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 770 request, nullptr); 771 772 return request.GetNumberOfMatches(); 773 } 774 775 protected: 776 bool DoExecute(llvm::StringRef command, 777 CommandReturnObject &result) override { 778 result.SetStatus(eReturnStatusSuccessFinishNoResult); 779 780 Args cmd_args(command); 781 const size_t argc = cmd_args.GetArgumentCount(); 782 783 if (argc < 3) { 784 result.AppendError("'settings insert-after' takes more arguments"); 785 result.SetStatus(eReturnStatusFailed); 786 return false; 787 } 788 789 const char *var_name = cmd_args.GetArgumentAtIndex(0); 790 if ((var_name == nullptr) || (var_name[0] == '\0')) { 791 result.AppendError("'settings insert-after' command requires a valid " 792 "variable name; No value supplied"); 793 result.SetStatus(eReturnStatusFailed); 794 return false; 795 } 796 797 // Split the raw command into var_name, index_value, and value triple. 798 llvm::StringRef raw_str(command); 799 std::string var_value_string = raw_str.split(var_name).second.str(); 800 const char *var_value_cstr = 801 Args::StripSpaces(var_value_string, true, true, false); 802 803 Status error(m_interpreter.GetDebugger().SetPropertyValue( 804 &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value_cstr)); 805 if (error.Fail()) { 806 result.AppendError(error.AsCString()); 807 result.SetStatus(eReturnStatusFailed); 808 return false; 809 } 810 811 return result.Succeeded(); 812 } 813 }; 814 815 //------------------------------------------------------------------------- 816 // CommandObjectSettingsAppend 817 //------------------------------------------------------------------------- 818 819 class CommandObjectSettingsAppend : public CommandObjectRaw { 820 public: 821 CommandObjectSettingsAppend(CommandInterpreter &interpreter) 822 : CommandObjectRaw(interpreter, "settings append", 823 "Append one or more values to a debugger array, " 824 "dictionary, or string setting.") { 825 CommandArgumentEntry arg1; 826 CommandArgumentEntry arg2; 827 CommandArgumentData var_name_arg; 828 CommandArgumentData value_arg; 829 830 // Define the first (and only) variant of this arg. 831 var_name_arg.arg_type = eArgTypeSettingVariableName; 832 var_name_arg.arg_repetition = eArgRepeatPlain; 833 834 // There is only one variant this argument could be; put it into the 835 // argument entry. 836 arg1.push_back(var_name_arg); 837 838 // Define the first (and only) variant of this arg. 839 value_arg.arg_type = eArgTypeValue; 840 value_arg.arg_repetition = eArgRepeatPlain; 841 842 // There is only one variant this argument could be; put it into the 843 // argument entry. 844 arg2.push_back(value_arg); 845 846 // Push the data for the first argument into the m_arguments vector. 847 m_arguments.push_back(arg1); 848 m_arguments.push_back(arg2); 849 } 850 851 ~CommandObjectSettingsAppend() override = default; 852 853 // Overrides base class's behavior where WantsCompletion = 854 // !WantsRawCommandString. 855 bool WantsCompletion() override { return true; } 856 857 int HandleArgumentCompletion( 858 CompletionRequest &request, 859 OptionElementVector &opt_element_vector) override { 860 // Attempting to complete variable name 861 if (request.GetCursorIndex() < 2) 862 CommandCompletions::InvokeCommonCompletionCallbacks( 863 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 864 request, nullptr); 865 866 return request.GetNumberOfMatches(); 867 } 868 869 protected: 870 bool DoExecute(llvm::StringRef command, 871 CommandReturnObject &result) override { 872 result.SetStatus(eReturnStatusSuccessFinishNoResult); 873 Args cmd_args(command); 874 const size_t argc = cmd_args.GetArgumentCount(); 875 876 if (argc < 2) { 877 result.AppendError("'settings append' takes more arguments"); 878 result.SetStatus(eReturnStatusFailed); 879 return false; 880 } 881 882 const char *var_name = cmd_args.GetArgumentAtIndex(0); 883 if ((var_name == nullptr) || (var_name[0] == '\0')) { 884 result.AppendError("'settings append' command requires a valid variable " 885 "name; No value supplied"); 886 result.SetStatus(eReturnStatusFailed); 887 return false; 888 } 889 890 // Do not perform cmd_args.Shift() since StringRef is manipulating the raw 891 // character string later on. 892 893 // Split the raw command into var_name and value pair. 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, eVarSetOperationAppend, 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 // CommandObjectSettingsClear 913 //------------------------------------------------------------------------- 914 915 class CommandObjectSettingsClear : public CommandObjectParsed { 916 public: 917 CommandObjectSettingsClear(CommandInterpreter &interpreter) 918 : CommandObjectParsed( 919 interpreter, "settings clear", 920 "Clear a debugger setting array, dictionary, or string.", nullptr) { 921 CommandArgumentEntry arg; 922 CommandArgumentData var_name_arg; 923 924 // Define the first (and only) variant of this arg. 925 var_name_arg.arg_type = eArgTypeSettingVariableName; 926 var_name_arg.arg_repetition = eArgRepeatPlain; 927 928 // There is only one variant this argument could be; put it into the 929 // argument entry. 930 arg.push_back(var_name_arg); 931 932 // Push the data for the first argument into the m_arguments vector. 933 m_arguments.push_back(arg); 934 } 935 936 ~CommandObjectSettingsClear() override = default; 937 938 int HandleArgumentCompletion( 939 CompletionRequest &request, 940 OptionElementVector &opt_element_vector) override { 941 // Attempting to complete variable name 942 if (request.GetCursorIndex() < 2) 943 CommandCompletions::InvokeCommonCompletionCallbacks( 944 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, 945 request, nullptr); 946 947 return request.GetNumberOfMatches(); 948 } 949 950 protected: 951 bool DoExecute(Args &command, CommandReturnObject &result) override { 952 result.SetStatus(eReturnStatusSuccessFinishNoResult); 953 const size_t argc = command.GetArgumentCount(); 954 955 if (argc != 1) { 956 result.AppendError("'settings clear' takes exactly one argument"); 957 result.SetStatus(eReturnStatusFailed); 958 return false; 959 } 960 961 const char *var_name = command.GetArgumentAtIndex(0); 962 if ((var_name == nullptr) || (var_name[0] == '\0')) { 963 result.AppendError("'settings clear' command requires a valid variable " 964 "name; No value supplied"); 965 result.SetStatus(eReturnStatusFailed); 966 return false; 967 } 968 969 Status error(m_interpreter.GetDebugger().SetPropertyValue( 970 &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef())); 971 if (error.Fail()) { 972 result.AppendError(error.AsCString()); 973 result.SetStatus(eReturnStatusFailed); 974 return false; 975 } 976 977 return result.Succeeded(); 978 } 979 }; 980 981 //------------------------------------------------------------------------- 982 // CommandObjectMultiwordSettings 983 //------------------------------------------------------------------------- 984 985 CommandObjectMultiwordSettings::CommandObjectMultiwordSettings( 986 CommandInterpreter &interpreter) 987 : CommandObjectMultiword(interpreter, "settings", 988 "Commands for managing LLDB settings.", 989 "settings <subcommand> [<command-options>]") { 990 LoadSubCommand("set", 991 CommandObjectSP(new CommandObjectSettingsSet(interpreter))); 992 LoadSubCommand("show", 993 CommandObjectSP(new CommandObjectSettingsShow(interpreter))); 994 LoadSubCommand("list", 995 CommandObjectSP(new CommandObjectSettingsList(interpreter))); 996 LoadSubCommand("remove", 997 CommandObjectSP(new CommandObjectSettingsRemove(interpreter))); 998 LoadSubCommand("replace", CommandObjectSP( 999 new CommandObjectSettingsReplace(interpreter))); 1000 LoadSubCommand( 1001 "insert-before", 1002 CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter))); 1003 LoadSubCommand( 1004 "insert-after", 1005 CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter))); 1006 LoadSubCommand("append", 1007 CommandObjectSP(new CommandObjectSettingsAppend(interpreter))); 1008 LoadSubCommand("clear", 1009 CommandObjectSP(new CommandObjectSettingsClear(interpreter))); 1010 } 1011 1012 CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default; 1013