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