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