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