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