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