1 //===-- SBCommandInterpreter.cpp ------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/lldb-types.h" 10 11 #include "lldb/Interpreter/CommandInterpreter.h" 12 #include "lldb/Interpreter/CommandObjectMultiword.h" 13 #include "lldb/Interpreter/CommandReturnObject.h" 14 #include "lldb/Target/Target.h" 15 #include "lldb/Utility/Instrumentation.h" 16 #include "lldb/Utility/Listener.h" 17 18 #include "lldb/API/SBBroadcaster.h" 19 #include "lldb/API/SBCommandInterpreter.h" 20 #include "lldb/API/SBCommandInterpreterRunOptions.h" 21 #include "lldb/API/SBCommandReturnObject.h" 22 #include "lldb/API/SBEvent.h" 23 #include "lldb/API/SBExecutionContext.h" 24 #include "lldb/API/SBListener.h" 25 #include "lldb/API/SBProcess.h" 26 #include "lldb/API/SBStream.h" 27 #include "lldb/API/SBStringList.h" 28 #include "lldb/API/SBTarget.h" 29 30 #include <memory> 31 #include <optional> 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 namespace lldb_private { 37 class CommandPluginInterfaceImplementation : public CommandObjectParsed { 38 public: 39 CommandPluginInterfaceImplementation(CommandInterpreter &interpreter, 40 const char *name, 41 lldb::SBCommandPluginInterface *backend, 42 const char *help = nullptr, 43 const char *syntax = nullptr, 44 uint32_t flags = 0, 45 const char *auto_repeat_command = "") 46 : CommandObjectParsed(interpreter, name, help, syntax, flags), 47 m_backend(backend) { 48 m_auto_repeat_command = 49 auto_repeat_command == nullptr 50 ? std::nullopt 51 : std::optional<std::string>(auto_repeat_command); 52 // We don't know whether any given command coming from this interface takes 53 // arguments or not so here we're just disabling the basic args check. 54 CommandArgumentData none_arg{eArgTypeNone, eArgRepeatStar}; 55 m_arguments.push_back({none_arg}); 56 } 57 58 bool IsRemovable() const override { return true; } 59 60 /// More documentation is available in lldb::CommandObject::GetRepeatCommand, 61 /// but in short, if std::nullopt is returned, the previous command will be 62 /// repeated, and if an empty string is returned, no commands will be 63 /// executed. 64 std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, 65 uint32_t index) override { 66 if (!m_auto_repeat_command) 67 return std::nullopt; 68 else 69 return m_auto_repeat_command; 70 } 71 72 protected: 73 bool DoExecute(Args &command, CommandReturnObject &result) override { 74 SBCommandReturnObject sb_return(result); 75 SBCommandInterpreter sb_interpreter(&m_interpreter); 76 SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); 77 bool ret = m_backend->DoExecute(debugger_sb, command.GetArgumentVector(), 78 sb_return); 79 return ret; 80 } 81 std::shared_ptr<lldb::SBCommandPluginInterface> m_backend; 82 std::optional<std::string> m_auto_repeat_command; 83 }; 84 } // namespace lldb_private 85 86 SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter) 87 : m_opaque_ptr(interpreter) { 88 LLDB_INSTRUMENT_VA(this, interpreter); 89 } 90 91 SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) 92 : m_opaque_ptr(rhs.m_opaque_ptr) { 93 LLDB_INSTRUMENT_VA(this, rhs); 94 } 95 96 SBCommandInterpreter::~SBCommandInterpreter() = default; 97 98 const SBCommandInterpreter &SBCommandInterpreter:: 99 operator=(const SBCommandInterpreter &rhs) { 100 LLDB_INSTRUMENT_VA(this, rhs); 101 102 m_opaque_ptr = rhs.m_opaque_ptr; 103 return *this; 104 } 105 106 bool SBCommandInterpreter::IsValid() const { 107 LLDB_INSTRUMENT_VA(this); 108 return this->operator bool(); 109 } 110 SBCommandInterpreter::operator bool() const { 111 LLDB_INSTRUMENT_VA(this); 112 113 return m_opaque_ptr != nullptr; 114 } 115 116 bool SBCommandInterpreter::CommandExists(const char *cmd) { 117 LLDB_INSTRUMENT_VA(this, cmd); 118 119 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd) 120 : false); 121 } 122 123 bool SBCommandInterpreter::UserCommandExists(const char *cmd) { 124 LLDB_INSTRUMENT_VA(this, cmd); 125 126 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->UserCommandExists(cmd) 127 : false); 128 } 129 130 bool SBCommandInterpreter::AliasExists(const char *cmd) { 131 LLDB_INSTRUMENT_VA(this, cmd); 132 133 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd) 134 : false); 135 } 136 137 bool SBCommandInterpreter::IsActive() { 138 LLDB_INSTRUMENT_VA(this); 139 140 return (IsValid() ? m_opaque_ptr->IsActive() : false); 141 } 142 143 bool SBCommandInterpreter::WasInterrupted() const { 144 LLDB_INSTRUMENT_VA(this); 145 146 return (IsValid() ? m_opaque_ptr->GetDebugger().InterruptRequested() : false); 147 } 148 149 bool SBCommandInterpreter::InterruptCommand() { 150 LLDB_INSTRUMENT_VA(this); 151 152 return (IsValid() ? m_opaque_ptr->InterruptCommand() : false); 153 } 154 155 const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) { 156 LLDB_INSTRUMENT_VA(this, ch); 157 158 if (!IsValid()) 159 return nullptr; 160 161 return ConstString( 162 m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence(ch)) 163 .GetCString(); 164 } 165 166 lldb::ReturnStatus 167 SBCommandInterpreter::HandleCommand(const char *command_line, 168 SBCommandReturnObject &result, 169 bool add_to_history) { 170 LLDB_INSTRUMENT_VA(this, command_line, result, add_to_history); 171 172 SBExecutionContext sb_exe_ctx; 173 return HandleCommand(command_line, sb_exe_ctx, result, add_to_history); 174 } 175 176 lldb::ReturnStatus SBCommandInterpreter::HandleCommand( 177 const char *command_line, SBExecutionContext &override_context, 178 SBCommandReturnObject &result, bool add_to_history) { 179 LLDB_INSTRUMENT_VA(this, command_line, override_context, result, 180 add_to_history); 181 182 result.Clear(); 183 if (command_line && IsValid()) { 184 result.ref().SetInteractive(false); 185 auto do_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo; 186 if (override_context.get()) 187 m_opaque_ptr->HandleCommand(command_line, do_add_to_history, 188 override_context.get()->Lock(true), 189 result.ref()); 190 else 191 m_opaque_ptr->HandleCommand(command_line, do_add_to_history, 192 result.ref()); 193 } else { 194 result->AppendError( 195 "SBCommandInterpreter or the command line is not valid"); 196 } 197 198 return result.GetStatus(); 199 } 200 201 void SBCommandInterpreter::HandleCommandsFromFile( 202 lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context, 203 lldb::SBCommandInterpreterRunOptions &options, 204 lldb::SBCommandReturnObject result) { 205 LLDB_INSTRUMENT_VA(this, file, override_context, options, result); 206 207 if (!IsValid()) { 208 result->AppendError("SBCommandInterpreter is not valid."); 209 return; 210 } 211 212 if (!file.IsValid()) { 213 SBStream s; 214 file.GetDescription(s); 215 result->AppendErrorWithFormat("File is not valid: %s.", s.GetData()); 216 } 217 218 FileSpec tmp_spec = file.ref(); 219 if (override_context.get()) 220 m_opaque_ptr->HandleCommandsFromFile(tmp_spec, 221 override_context.get()->Lock(true), 222 options.ref(), 223 result.ref()); 224 225 else 226 m_opaque_ptr->HandleCommandsFromFile(tmp_spec, options.ref(), result.ref()); 227 } 228 229 int SBCommandInterpreter::HandleCompletion( 230 const char *current_line, const char *cursor, const char *last_char, 231 int match_start_point, int max_return_elements, SBStringList &matches) { 232 LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point, 233 max_return_elements, matches); 234 235 SBStringList dummy_descriptions; 236 return HandleCompletionWithDescriptions( 237 current_line, cursor, last_char, match_start_point, max_return_elements, 238 matches, dummy_descriptions); 239 } 240 241 int SBCommandInterpreter::HandleCompletionWithDescriptions( 242 const char *current_line, const char *cursor, const char *last_char, 243 int match_start_point, int max_return_elements, SBStringList &matches, 244 SBStringList &descriptions) { 245 LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point, 246 max_return_elements, matches, descriptions); 247 248 // Sanity check the arguments that are passed in: cursor & last_char have to 249 // be within the current_line. 250 if (current_line == nullptr || cursor == nullptr || last_char == nullptr) 251 return 0; 252 253 if (cursor < current_line || last_char < current_line) 254 return 0; 255 256 size_t current_line_size = strlen(current_line); 257 if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) || 258 last_char - current_line > static_cast<ptrdiff_t>(current_line_size)) 259 return 0; 260 261 if (!IsValid()) 262 return 0; 263 264 lldb_private::StringList lldb_matches, lldb_descriptions; 265 CompletionResult result; 266 CompletionRequest request(current_line, cursor - current_line, result); 267 m_opaque_ptr->HandleCompletion(request); 268 result.GetMatches(lldb_matches); 269 result.GetDescriptions(lldb_descriptions); 270 271 // Make the result array indexed from 1 again by adding the 'common prefix' 272 // of all completions as element 0. This is done to emulate the old API. 273 if (request.GetParsedLine().GetArgumentCount() == 0) { 274 // If we got an empty string, insert nothing. 275 lldb_matches.InsertStringAtIndex(0, ""); 276 lldb_descriptions.InsertStringAtIndex(0, ""); 277 } else { 278 // Now figure out if there is a common substring, and if so put that in 279 // element 0, otherwise put an empty string in element 0. 280 std::string command_partial_str = request.GetCursorArgumentPrefix().str(); 281 282 std::string common_prefix = lldb_matches.LongestCommonPrefix(); 283 const size_t partial_name_len = command_partial_str.size(); 284 common_prefix.erase(0, partial_name_len); 285 286 // If we matched a unique single command, add a space... Only do this if 287 // the completer told us this was a complete word, however... 288 if (lldb_matches.GetSize() == 1) { 289 char quote_char = request.GetParsedArg().GetQuoteChar(); 290 common_prefix = 291 Args::EscapeLLDBCommandArgument(common_prefix, quote_char); 292 if (request.GetParsedArg().IsQuoted()) 293 common_prefix.push_back(quote_char); 294 common_prefix.push_back(' '); 295 } 296 lldb_matches.InsertStringAtIndex(0, common_prefix.c_str()); 297 lldb_descriptions.InsertStringAtIndex(0, ""); 298 } 299 300 SBStringList temp_matches_list(&lldb_matches); 301 matches.AppendList(temp_matches_list); 302 SBStringList temp_descriptions_list(&lldb_descriptions); 303 descriptions.AppendList(temp_descriptions_list); 304 return result.GetNumberOfResults(); 305 } 306 307 int SBCommandInterpreter::HandleCompletionWithDescriptions( 308 const char *current_line, uint32_t cursor_pos, int match_start_point, 309 int max_return_elements, SBStringList &matches, 310 SBStringList &descriptions) { 311 LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point, 312 max_return_elements, matches, descriptions); 313 314 const char *cursor = current_line + cursor_pos; 315 const char *last_char = current_line + strlen(current_line); 316 return HandleCompletionWithDescriptions( 317 current_line, cursor, last_char, match_start_point, max_return_elements, 318 matches, descriptions); 319 } 320 321 int SBCommandInterpreter::HandleCompletion(const char *current_line, 322 uint32_t cursor_pos, 323 int match_start_point, 324 int max_return_elements, 325 lldb::SBStringList &matches) { 326 LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point, 327 max_return_elements, matches); 328 329 const char *cursor = current_line + cursor_pos; 330 const char *last_char = current_line + strlen(current_line); 331 return HandleCompletion(current_line, cursor, last_char, match_start_point, 332 max_return_elements, matches); 333 } 334 335 bool SBCommandInterpreter::HasCommands() { 336 LLDB_INSTRUMENT_VA(this); 337 338 return (IsValid() ? m_opaque_ptr->HasCommands() : false); 339 } 340 341 bool SBCommandInterpreter::HasAliases() { 342 LLDB_INSTRUMENT_VA(this); 343 344 return (IsValid() ? m_opaque_ptr->HasAliases() : false); 345 } 346 347 bool SBCommandInterpreter::HasAliasOptions() { 348 LLDB_INSTRUMENT_VA(this); 349 350 return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false); 351 } 352 353 bool SBCommandInterpreter::IsInteractive() { 354 LLDB_INSTRUMENT_VA(this); 355 356 return (IsValid() ? m_opaque_ptr->IsInteractive() : false); 357 } 358 359 SBProcess SBCommandInterpreter::GetProcess() { 360 LLDB_INSTRUMENT_VA(this); 361 362 SBProcess sb_process; 363 ProcessSP process_sp; 364 if (IsValid()) { 365 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 366 if (target_sp) { 367 std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); 368 process_sp = target_sp->GetProcessSP(); 369 sb_process.SetSP(process_sp); 370 } 371 } 372 373 return sb_process; 374 } 375 376 SBDebugger SBCommandInterpreter::GetDebugger() { 377 LLDB_INSTRUMENT_VA(this); 378 379 SBDebugger sb_debugger; 380 if (IsValid()) 381 sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this()); 382 383 return sb_debugger; 384 } 385 386 bool SBCommandInterpreter::GetPromptOnQuit() { 387 LLDB_INSTRUMENT_VA(this); 388 389 return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false); 390 } 391 392 void SBCommandInterpreter::SetPromptOnQuit(bool b) { 393 LLDB_INSTRUMENT_VA(this, b); 394 395 if (IsValid()) 396 m_opaque_ptr->SetPromptOnQuit(b); 397 } 398 399 void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) { 400 LLDB_INSTRUMENT_VA(this, allow); 401 402 if (m_opaque_ptr) 403 m_opaque_ptr->AllowExitCodeOnQuit(allow); 404 } 405 406 bool SBCommandInterpreter::HasCustomQuitExitCode() { 407 LLDB_INSTRUMENT_VA(this); 408 409 bool exited = false; 410 if (m_opaque_ptr) 411 m_opaque_ptr->GetQuitExitCode(exited); 412 return exited; 413 } 414 415 int SBCommandInterpreter::GetQuitStatus() { 416 LLDB_INSTRUMENT_VA(this); 417 418 bool exited = false; 419 return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0); 420 } 421 422 void SBCommandInterpreter::ResolveCommand(const char *command_line, 423 SBCommandReturnObject &result) { 424 LLDB_INSTRUMENT_VA(this, command_line, result); 425 426 result.Clear(); 427 if (command_line && IsValid()) { 428 m_opaque_ptr->ResolveCommand(command_line, result.ref()); 429 } else { 430 result->AppendError( 431 "SBCommandInterpreter or the command line is not valid"); 432 } 433 } 434 435 CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; } 436 437 CommandInterpreter &SBCommandInterpreter::ref() { 438 assert(m_opaque_ptr); 439 return *m_opaque_ptr; 440 } 441 442 void SBCommandInterpreter::reset( 443 lldb_private::CommandInterpreter *interpreter) { 444 m_opaque_ptr = interpreter; 445 } 446 447 void SBCommandInterpreter::SourceInitFileInGlobalDirectory( 448 SBCommandReturnObject &result) { 449 LLDB_INSTRUMENT_VA(this, result); 450 451 result.Clear(); 452 if (IsValid()) { 453 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 454 std::unique_lock<std::recursive_mutex> lock; 455 if (target_sp) 456 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 457 m_opaque_ptr->SourceInitFileGlobal(result.ref()); 458 } else { 459 result->AppendError("SBCommandInterpreter is not valid"); 460 } 461 } 462 463 void SBCommandInterpreter::SourceInitFileInHomeDirectory( 464 SBCommandReturnObject &result) { 465 LLDB_INSTRUMENT_VA(this, result); 466 467 SourceInitFileInHomeDirectory(result, /*is_repl=*/false); 468 } 469 470 void SBCommandInterpreter::SourceInitFileInHomeDirectory( 471 SBCommandReturnObject &result, bool is_repl) { 472 LLDB_INSTRUMENT_VA(this, result, is_repl); 473 474 result.Clear(); 475 if (IsValid()) { 476 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 477 std::unique_lock<std::recursive_mutex> lock; 478 if (target_sp) 479 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 480 m_opaque_ptr->SourceInitFileHome(result.ref(), is_repl); 481 } else { 482 result->AppendError("SBCommandInterpreter is not valid"); 483 } 484 } 485 486 void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory( 487 SBCommandReturnObject &result) { 488 LLDB_INSTRUMENT_VA(this, result); 489 490 result.Clear(); 491 if (IsValid()) { 492 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 493 std::unique_lock<std::recursive_mutex> lock; 494 if (target_sp) 495 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 496 m_opaque_ptr->SourceInitFileCwd(result.ref()); 497 } else { 498 result->AppendError("SBCommandInterpreter is not valid"); 499 } 500 } 501 502 SBBroadcaster SBCommandInterpreter::GetBroadcaster() { 503 LLDB_INSTRUMENT_VA(this); 504 505 SBBroadcaster broadcaster(m_opaque_ptr, false); 506 507 return broadcaster; 508 } 509 510 const char *SBCommandInterpreter::GetBroadcasterClass() { 511 LLDB_INSTRUMENT(); 512 513 return CommandInterpreter::GetStaticBroadcasterClass().AsCString(); 514 } 515 516 const char *SBCommandInterpreter::GetArgumentTypeAsCString( 517 const lldb::CommandArgumentType arg_type) { 518 LLDB_INSTRUMENT_VA(arg_type); 519 520 return ConstString(CommandObject::GetArgumentTypeAsCString(arg_type)) 521 .GetCString(); 522 } 523 524 const char *SBCommandInterpreter::GetArgumentDescriptionAsCString( 525 const lldb::CommandArgumentType arg_type) { 526 LLDB_INSTRUMENT_VA(arg_type); 527 528 return ConstString(CommandObject::GetArgumentDescriptionAsCString(arg_type)) 529 .GetCString(); 530 } 531 532 bool SBCommandInterpreter::EventIsCommandInterpreterEvent( 533 const lldb::SBEvent &event) { 534 LLDB_INSTRUMENT_VA(event); 535 536 return event.GetBroadcasterClass() == 537 SBCommandInterpreter::GetBroadcasterClass(); 538 } 539 540 bool SBCommandInterpreter::SetCommandOverrideCallback( 541 const char *command_name, lldb::CommandOverrideCallback callback, 542 void *baton) { 543 LLDB_INSTRUMENT_VA(this, command_name, callback, baton); 544 545 if (command_name && command_name[0] && IsValid()) { 546 llvm::StringRef command_name_str = command_name; 547 CommandObject *cmd_obj = 548 m_opaque_ptr->GetCommandObjectForCommand(command_name_str); 549 if (cmd_obj) { 550 assert(command_name_str.empty()); 551 cmd_obj->SetOverrideCallback(callback, baton); 552 return true; 553 } 554 } 555 return false; 556 } 557 558 lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name, 559 const char *help) { 560 LLDB_INSTRUMENT_VA(this, name, help); 561 562 lldb::CommandObjectSP new_command_sp( 563 new CommandObjectMultiword(*m_opaque_ptr, name, help)); 564 new_command_sp->GetAsMultiwordCommand()->SetRemovable(true); 565 Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true); 566 if (add_error.Success()) 567 return lldb::SBCommand(new_command_sp); 568 return lldb::SBCommand(); 569 } 570 571 lldb::SBCommand SBCommandInterpreter::AddCommand( 572 const char *name, lldb::SBCommandPluginInterface *impl, const char *help) { 573 LLDB_INSTRUMENT_VA(this, name, impl, help); 574 575 return AddCommand(name, impl, help, /*syntax=*/nullptr, 576 /*auto_repeat_command=*/""); 577 } 578 579 lldb::SBCommand 580 SBCommandInterpreter::AddCommand(const char *name, 581 lldb::SBCommandPluginInterface *impl, 582 const char *help, const char *syntax) { 583 LLDB_INSTRUMENT_VA(this, name, impl, help, syntax); 584 return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""); 585 } 586 587 lldb::SBCommand SBCommandInterpreter::AddCommand( 588 const char *name, lldb::SBCommandPluginInterface *impl, const char *help, 589 const char *syntax, const char *auto_repeat_command) { 590 LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command); 591 592 lldb::CommandObjectSP new_command_sp; 593 new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>( 594 *m_opaque_ptr, name, impl, help, syntax, /*flags=*/0, 595 auto_repeat_command); 596 597 Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true); 598 if (add_error.Success()) 599 return lldb::SBCommand(new_command_sp); 600 return lldb::SBCommand(); 601 } 602 603 SBCommand::SBCommand() { LLDB_INSTRUMENT_VA(this); } 604 605 SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {} 606 607 bool SBCommand::IsValid() { 608 LLDB_INSTRUMENT_VA(this); 609 return this->operator bool(); 610 } 611 SBCommand::operator bool() const { 612 LLDB_INSTRUMENT_VA(this); 613 614 return m_opaque_sp.get() != nullptr; 615 } 616 617 const char *SBCommand::GetName() { 618 LLDB_INSTRUMENT_VA(this); 619 620 return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr); 621 } 622 623 const char *SBCommand::GetHelp() { 624 LLDB_INSTRUMENT_VA(this); 625 626 return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString() 627 : nullptr); 628 } 629 630 const char *SBCommand::GetHelpLong() { 631 LLDB_INSTRUMENT_VA(this); 632 633 return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString() 634 : nullptr); 635 } 636 637 void SBCommand::SetHelp(const char *help) { 638 LLDB_INSTRUMENT_VA(this, help); 639 640 if (IsValid()) 641 m_opaque_sp->SetHelp(help); 642 } 643 644 void SBCommand::SetHelpLong(const char *help) { 645 LLDB_INSTRUMENT_VA(this, help); 646 647 if (IsValid()) 648 m_opaque_sp->SetHelpLong(help); 649 } 650 651 lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name, 652 const char *help) { 653 LLDB_INSTRUMENT_VA(this, name, help); 654 655 if (!IsValid()) 656 return lldb::SBCommand(); 657 if (!m_opaque_sp->IsMultiwordObject()) 658 return lldb::SBCommand(); 659 CommandObjectMultiword *new_command = new CommandObjectMultiword( 660 m_opaque_sp->GetCommandInterpreter(), name, help); 661 new_command->SetRemovable(true); 662 lldb::CommandObjectSP new_command_sp(new_command); 663 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 664 return lldb::SBCommand(new_command_sp); 665 return lldb::SBCommand(); 666 } 667 668 lldb::SBCommand SBCommand::AddCommand(const char *name, 669 lldb::SBCommandPluginInterface *impl, 670 const char *help) { 671 LLDB_INSTRUMENT_VA(this, name, impl, help); 672 return AddCommand(name, impl, help, /*syntax=*/nullptr, 673 /*auto_repeat_command=*/""); 674 } 675 676 lldb::SBCommand SBCommand::AddCommand(const char *name, 677 lldb::SBCommandPluginInterface *impl, 678 const char *help, const char *syntax) { 679 LLDB_INSTRUMENT_VA(this, name, impl, help, syntax); 680 return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""); 681 } 682 683 lldb::SBCommand SBCommand::AddCommand(const char *name, 684 lldb::SBCommandPluginInterface *impl, 685 const char *help, const char *syntax, 686 const char *auto_repeat_command) { 687 LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command); 688 689 if (!IsValid()) 690 return lldb::SBCommand(); 691 if (!m_opaque_sp->IsMultiwordObject()) 692 return lldb::SBCommand(); 693 lldb::CommandObjectSP new_command_sp; 694 new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>( 695 m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax, 696 /*flags=*/0, auto_repeat_command); 697 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 698 return lldb::SBCommand(new_command_sp); 699 return lldb::SBCommand(); 700 } 701 702 uint32_t SBCommand::GetFlags() { 703 LLDB_INSTRUMENT_VA(this); 704 705 return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0); 706 } 707 708 void SBCommand::SetFlags(uint32_t flags) { 709 LLDB_INSTRUMENT_VA(this, flags); 710 711 if (IsValid()) 712 m_opaque_sp->GetFlags().Set(flags); 713 } 714