1 //===-- SBCommandInterpreter.cpp --------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 // Project includes 14 #include "lldb/lldb-types.h" 15 16 #include "lldb/Core/Listener.h" 17 #include "lldb/Interpreter/CommandInterpreter.h" 18 #include "lldb/Interpreter/CommandObjectMultiword.h" 19 #include "lldb/Interpreter/CommandReturnObject.h" 20 #include "lldb/Target/Target.h" 21 22 #include "lldb/API/SBBroadcaster.h" 23 #include "lldb/API/SBCommandInterpreter.h" 24 #include "lldb/API/SBCommandReturnObject.h" 25 #include "lldb/API/SBEvent.h" 26 #include "lldb/API/SBExecutionContext.h" 27 #include "lldb/API/SBListener.h" 28 #include "lldb/API/SBProcess.h" 29 #include "lldb/API/SBStream.h" 30 #include "lldb/API/SBStringList.h" 31 #include "lldb/API/SBTarget.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 SBCommandInterpreterRunOptions::SBCommandInterpreterRunOptions() { 37 m_opaque_up.reset(new CommandInterpreterRunOptions()); 38 } 39 40 SBCommandInterpreterRunOptions::~SBCommandInterpreterRunOptions() = default; 41 42 bool SBCommandInterpreterRunOptions::GetStopOnContinue() const { 43 return m_opaque_up->GetStopOnContinue(); 44 } 45 46 void SBCommandInterpreterRunOptions::SetStopOnContinue(bool stop_on_continue) { 47 m_opaque_up->SetStopOnContinue(stop_on_continue); 48 } 49 50 bool SBCommandInterpreterRunOptions::GetStopOnError() const { 51 return m_opaque_up->GetStopOnError(); 52 } 53 54 void SBCommandInterpreterRunOptions::SetStopOnError(bool stop_on_error) { 55 m_opaque_up->SetStopOnError(stop_on_error); 56 } 57 58 bool SBCommandInterpreterRunOptions::GetStopOnCrash() const { 59 return m_opaque_up->GetStopOnCrash(); 60 } 61 62 void SBCommandInterpreterRunOptions::SetStopOnCrash(bool stop_on_crash) { 63 m_opaque_up->SetStopOnCrash(stop_on_crash); 64 } 65 66 bool SBCommandInterpreterRunOptions::GetEchoCommands() const { 67 return m_opaque_up->GetEchoCommands(); 68 } 69 70 void SBCommandInterpreterRunOptions::SetEchoCommands(bool echo_commands) { 71 m_opaque_up->SetEchoCommands(echo_commands); 72 } 73 74 bool SBCommandInterpreterRunOptions::GetPrintResults() const { 75 return m_opaque_up->GetPrintResults(); 76 } 77 78 void SBCommandInterpreterRunOptions::SetPrintResults(bool print_results) { 79 m_opaque_up->SetPrintResults(print_results); 80 } 81 82 bool SBCommandInterpreterRunOptions::GetAddToHistory() const { 83 return m_opaque_up->GetAddToHistory(); 84 } 85 86 void SBCommandInterpreterRunOptions::SetAddToHistory(bool add_to_history) { 87 m_opaque_up->SetAddToHistory(add_to_history); 88 } 89 90 lldb_private::CommandInterpreterRunOptions * 91 SBCommandInterpreterRunOptions::get() const { 92 return m_opaque_up.get(); 93 } 94 95 lldb_private::CommandInterpreterRunOptions & 96 SBCommandInterpreterRunOptions::ref() const { 97 return *m_opaque_up.get(); 98 } 99 100 class CommandPluginInterfaceImplementation : public CommandObjectParsed { 101 public: 102 CommandPluginInterfaceImplementation(CommandInterpreter &interpreter, 103 const char *name, 104 lldb::SBCommandPluginInterface *backend, 105 const char *help = nullptr, 106 const char *syntax = nullptr, 107 uint32_t flags = 0) 108 : CommandObjectParsed(interpreter, name, help, syntax, flags), 109 m_backend(backend) {} 110 111 bool IsRemovable() const override { return true; } 112 113 protected: 114 bool DoExecute(Args &command, CommandReturnObject &result) override { 115 SBCommandReturnObject sb_return(&result); 116 SBCommandInterpreter sb_interpreter(&m_interpreter); 117 SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); 118 bool ret = m_backend->DoExecute( 119 debugger_sb, (char **)command.GetArgumentVector(), sb_return); 120 sb_return.Release(); 121 return ret; 122 } 123 std::shared_ptr<lldb::SBCommandPluginInterface> m_backend; 124 }; 125 126 SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter) 127 : m_opaque_ptr(interpreter) { 128 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 129 130 if (log) 131 log->Printf("SBCommandInterpreter::SBCommandInterpreter (interpreter=%p)" 132 " => SBCommandInterpreter(%p)", 133 static_cast<void *>(interpreter), 134 static_cast<void *>(m_opaque_ptr)); 135 } 136 137 SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) 138 : m_opaque_ptr(rhs.m_opaque_ptr) {} 139 140 SBCommandInterpreter::~SBCommandInterpreter() = default; 141 142 const SBCommandInterpreter &SBCommandInterpreter:: 143 operator=(const SBCommandInterpreter &rhs) { 144 m_opaque_ptr = rhs.m_opaque_ptr; 145 return *this; 146 } 147 148 bool SBCommandInterpreter::IsValid() const { return m_opaque_ptr != nullptr; } 149 150 bool SBCommandInterpreter::CommandExists(const char *cmd) { 151 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd) 152 : false); 153 } 154 155 bool SBCommandInterpreter::AliasExists(const char *cmd) { 156 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd) 157 : false); 158 } 159 160 bool SBCommandInterpreter::IsActive() { 161 return (IsValid() ? m_opaque_ptr->IsActive() : false); 162 } 163 164 bool SBCommandInterpreter::WasInterrupted() const { 165 return (IsValid() ? m_opaque_ptr->WasInterrupted() : false); 166 } 167 168 const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) { 169 return (IsValid() 170 ? m_opaque_ptr->GetDebugger() 171 .GetTopIOHandlerControlSequence(ch) 172 .GetCString() 173 : nullptr); 174 } 175 176 lldb::ReturnStatus 177 SBCommandInterpreter::HandleCommand(const char *command_line, 178 SBCommandReturnObject &result, 179 bool add_to_history) { 180 SBExecutionContext sb_exe_ctx; 181 return HandleCommand(command_line, sb_exe_ctx, result, add_to_history); 182 } 183 184 lldb::ReturnStatus SBCommandInterpreter::HandleCommand( 185 const char *command_line, SBExecutionContext &override_context, 186 SBCommandReturnObject &result, bool add_to_history) { 187 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 188 189 if (log) 190 log->Printf("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", " 191 "SBCommandReturnObject(%p), add_to_history=%i)", 192 static_cast<void *>(m_opaque_ptr), command_line, 193 static_cast<void *>(result.get()), add_to_history); 194 195 ExecutionContext ctx, *ctx_ptr; 196 if (override_context.get()) { 197 ctx = override_context.get()->Lock(true); 198 ctx_ptr = &ctx; 199 } else 200 ctx_ptr = nullptr; 201 202 result.Clear(); 203 if (command_line && IsValid()) { 204 result.ref().SetInteractive(false); 205 m_opaque_ptr->HandleCommand(command_line, 206 add_to_history ? eLazyBoolYes : eLazyBoolNo, 207 result.ref(), ctx_ptr); 208 } else { 209 result->AppendError( 210 "SBCommandInterpreter or the command line is not valid"); 211 result->SetStatus(eReturnStatusFailed); 212 } 213 214 // We need to get the value again, in case the command disabled the log! 215 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API); 216 if (log) { 217 SBStream sstr; 218 result.GetDescription(sstr); 219 log->Printf("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", " 220 "SBCommandReturnObject(%p): %s, add_to_history=%i) => %i", 221 static_cast<void *>(m_opaque_ptr), command_line, 222 static_cast<void *>(result.get()), sstr.GetData(), 223 add_to_history, result.GetStatus()); 224 } 225 226 return result.GetStatus(); 227 } 228 229 void SBCommandInterpreter::HandleCommandsFromFile( 230 lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context, 231 lldb::SBCommandInterpreterRunOptions &options, 232 lldb::SBCommandReturnObject result) { 233 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 234 235 if (log) { 236 SBStream s; 237 file.GetDescription(s); 238 log->Printf("SBCommandInterpreter(%p)::HandleCommandsFromFile " 239 "(file=\"%s\", SBCommandReturnObject(%p))", 240 static_cast<void *>(m_opaque_ptr), s.GetData(), 241 static_cast<void *>(result.get())); 242 } 243 244 if (!IsValid()) { 245 result->AppendError("SBCommandInterpreter is not valid."); 246 result->SetStatus(eReturnStatusFailed); 247 return; 248 } 249 250 if (!file.IsValid()) { 251 SBStream s; 252 file.GetDescription(s); 253 result->AppendErrorWithFormat("File is not valid: %s.", s.GetData()); 254 result->SetStatus(eReturnStatusFailed); 255 } 256 257 FileSpec tmp_spec = file.ref(); 258 ExecutionContext ctx, *ctx_ptr; 259 if (override_context.get()) { 260 ctx = override_context.get()->Lock(true); 261 ctx_ptr = &ctx; 262 } else 263 ctx_ptr = nullptr; 264 265 m_opaque_ptr->HandleCommandsFromFile(tmp_spec, ctx_ptr, options.ref(), 266 result.ref()); 267 } 268 269 int SBCommandInterpreter::HandleCompletion( 270 const char *current_line, const char *cursor, const char *last_char, 271 int match_start_point, int max_return_elements, SBStringList &matches) { 272 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 273 int num_completions = 0; 274 275 // Sanity check the arguments that are passed in: cursor & last_char have to 276 // be within the current_line. 277 if (current_line == nullptr || cursor == nullptr || last_char == nullptr) 278 return 0; 279 280 if (cursor < current_line || last_char < current_line) 281 return 0; 282 283 size_t current_line_size = strlen(current_line); 284 if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) || 285 last_char - current_line > static_cast<ptrdiff_t>(current_line_size)) 286 return 0; 287 288 if (log) 289 log->Printf("SBCommandInterpreter(%p)::HandleCompletion " 290 "(current_line=\"%s\", cursor at: %" PRId64 291 ", last char at: %" PRId64 292 ", match_start_point: %d, max_return_elements: %d)", 293 static_cast<void *>(m_opaque_ptr), current_line, 294 static_cast<uint64_t>(cursor - current_line), 295 static_cast<uint64_t>(last_char - current_line), 296 match_start_point, max_return_elements); 297 298 if (IsValid()) { 299 lldb_private::StringList lldb_matches; 300 num_completions = m_opaque_ptr->HandleCompletion( 301 current_line, cursor, last_char, match_start_point, max_return_elements, 302 lldb_matches); 303 304 SBStringList temp_list(&lldb_matches); 305 matches.AppendList(temp_list); 306 } 307 if (log) 308 log->Printf( 309 "SBCommandInterpreter(%p)::HandleCompletion - Found %d completions.", 310 static_cast<void *>(m_opaque_ptr), num_completions); 311 312 return num_completions; 313 } 314 315 int SBCommandInterpreter::HandleCompletion(const char *current_line, 316 uint32_t cursor_pos, 317 int match_start_point, 318 int max_return_elements, 319 lldb::SBStringList &matches) { 320 const char *cursor = current_line + cursor_pos; 321 const char *last_char = current_line + strlen(current_line); 322 return HandleCompletion(current_line, cursor, last_char, match_start_point, 323 max_return_elements, matches); 324 } 325 326 bool SBCommandInterpreter::HasCommands() { 327 return (IsValid() ? m_opaque_ptr->HasCommands() : false); 328 } 329 330 bool SBCommandInterpreter::HasAliases() { 331 return (IsValid() ? m_opaque_ptr->HasAliases() : false); 332 } 333 334 bool SBCommandInterpreter::HasAliasOptions() { 335 return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false); 336 } 337 338 SBProcess SBCommandInterpreter::GetProcess() { 339 SBProcess sb_process; 340 ProcessSP process_sp; 341 if (IsValid()) { 342 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 343 if (target_sp) { 344 std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); 345 process_sp = target_sp->GetProcessSP(); 346 sb_process.SetSP(process_sp); 347 } 348 } 349 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 350 351 if (log) 352 log->Printf("SBCommandInterpreter(%p)::GetProcess () => SBProcess(%p)", 353 static_cast<void *>(m_opaque_ptr), 354 static_cast<void *>(process_sp.get())); 355 356 return sb_process; 357 } 358 359 SBDebugger SBCommandInterpreter::GetDebugger() { 360 SBDebugger sb_debugger; 361 if (IsValid()) 362 sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this()); 363 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 364 365 if (log) 366 log->Printf("SBCommandInterpreter(%p)::GetDebugger () => SBDebugger(%p)", 367 static_cast<void *>(m_opaque_ptr), 368 static_cast<void *>(sb_debugger.get())); 369 370 return sb_debugger; 371 } 372 373 bool SBCommandInterpreter::GetPromptOnQuit() { 374 return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false); 375 } 376 377 void SBCommandInterpreter::SetPromptOnQuit(bool b) { 378 if (IsValid()) 379 m_opaque_ptr->SetPromptOnQuit(b); 380 } 381 382 void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) { 383 if (m_opaque_ptr) 384 m_opaque_ptr->AllowExitCodeOnQuit(allow); 385 } 386 387 bool SBCommandInterpreter::HasCustomQuitExitCode() { 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 bool exited = false; 396 return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0); 397 } 398 399 void SBCommandInterpreter::ResolveCommand(const char *command_line, 400 SBCommandReturnObject &result) { 401 result.Clear(); 402 if (command_line && IsValid()) { 403 m_opaque_ptr->ResolveCommand(command_line, result.ref()); 404 } else { 405 result->AppendError( 406 "SBCommandInterpreter or the command line is not valid"); 407 result->SetStatus(eReturnStatusFailed); 408 } 409 } 410 411 CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; } 412 413 CommandInterpreter &SBCommandInterpreter::ref() { 414 assert(m_opaque_ptr); 415 return *m_opaque_ptr; 416 } 417 418 void SBCommandInterpreter::reset( 419 lldb_private::CommandInterpreter *interpreter) { 420 m_opaque_ptr = interpreter; 421 } 422 423 void SBCommandInterpreter::SourceInitFileInHomeDirectory( 424 SBCommandReturnObject &result) { 425 result.Clear(); 426 if (IsValid()) { 427 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 428 std::unique_lock<std::recursive_mutex> lock; 429 if (target_sp) 430 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 431 m_opaque_ptr->SourceInitFile(false, result.ref()); 432 } else { 433 result->AppendError("SBCommandInterpreter is not valid"); 434 result->SetStatus(eReturnStatusFailed); 435 } 436 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 437 438 if (log) 439 log->Printf("SBCommandInterpreter(%p)::SourceInitFileInHomeDirectory " 440 "(&SBCommandReturnObject(%p))", 441 static_cast<void *>(m_opaque_ptr), 442 static_cast<void *>(result.get())); 443 } 444 445 void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory( 446 SBCommandReturnObject &result) { 447 result.Clear(); 448 if (IsValid()) { 449 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 450 std::unique_lock<std::recursive_mutex> lock; 451 if (target_sp) 452 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 453 m_opaque_ptr->SourceInitFile(true, result.ref()); 454 } else { 455 result->AppendError("SBCommandInterpreter is not valid"); 456 result->SetStatus(eReturnStatusFailed); 457 } 458 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 459 460 if (log) 461 log->Printf( 462 "SBCommandInterpreter(%p)::SourceInitFileInCurrentWorkingDirectory " 463 "(&SBCommandReturnObject(%p))", 464 static_cast<void *>(m_opaque_ptr), static_cast<void *>(result.get())); 465 } 466 467 SBBroadcaster SBCommandInterpreter::GetBroadcaster() { 468 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 469 470 SBBroadcaster broadcaster(m_opaque_ptr, false); 471 472 if (log) 473 log->Printf( 474 "SBCommandInterpreter(%p)::GetBroadcaster() => SBBroadcaster(%p)", 475 static_cast<void *>(m_opaque_ptr), 476 static_cast<void *>(broadcaster.get())); 477 478 return broadcaster; 479 } 480 481 const char *SBCommandInterpreter::GetBroadcasterClass() { 482 return CommandInterpreter::GetStaticBroadcasterClass().AsCString(); 483 } 484 485 const char *SBCommandInterpreter::GetArgumentTypeAsCString( 486 const lldb::CommandArgumentType arg_type) { 487 return CommandObject::GetArgumentTypeAsCString(arg_type); 488 } 489 490 const char *SBCommandInterpreter::GetArgumentDescriptionAsCString( 491 const lldb::CommandArgumentType arg_type) { 492 return CommandObject::GetArgumentDescriptionAsCString(arg_type); 493 } 494 495 bool SBCommandInterpreter::EventIsCommandInterpreterEvent( 496 const lldb::SBEvent &event) { 497 return event.GetBroadcasterClass() == 498 SBCommandInterpreter::GetBroadcasterClass(); 499 } 500 501 bool SBCommandInterpreter::SetCommandOverrideCallback( 502 const char *command_name, lldb::CommandOverrideCallback callback, 503 void *baton) { 504 if (command_name && command_name[0] && IsValid()) { 505 llvm::StringRef command_name_str = command_name; 506 CommandObject *cmd_obj = 507 m_opaque_ptr->GetCommandObjectForCommand(command_name_str); 508 if (cmd_obj) { 509 assert(command_name_str.empty()); 510 cmd_obj->SetOverrideCallback(callback, baton); 511 return true; 512 } 513 } 514 return false; 515 } 516 517 lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name, 518 const char *help) { 519 CommandObjectMultiword *new_command = 520 new CommandObjectMultiword(*m_opaque_ptr, name, help); 521 new_command->SetRemovable(true); 522 lldb::CommandObjectSP new_command_sp(new_command); 523 if (new_command_sp && 524 m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) 525 return lldb::SBCommand(new_command_sp); 526 return lldb::SBCommand(); 527 } 528 529 lldb::SBCommand SBCommandInterpreter::AddCommand( 530 const char *name, lldb::SBCommandPluginInterface *impl, const char *help) { 531 lldb::CommandObjectSP new_command_sp; 532 new_command_sp.reset(new CommandPluginInterfaceImplementation( 533 *m_opaque_ptr, name, impl, help)); 534 535 if (new_command_sp && 536 m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) 537 return lldb::SBCommand(new_command_sp); 538 return lldb::SBCommand(); 539 } 540 541 lldb::SBCommand 542 SBCommandInterpreter::AddCommand(const char *name, 543 lldb::SBCommandPluginInterface *impl, 544 const char *help, const char *syntax) { 545 lldb::CommandObjectSP new_command_sp; 546 new_command_sp.reset(new CommandPluginInterfaceImplementation( 547 *m_opaque_ptr, name, impl, help, syntax)); 548 549 if (new_command_sp && 550 m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) 551 return lldb::SBCommand(new_command_sp); 552 return lldb::SBCommand(); 553 } 554 555 SBCommand::SBCommand() = default; 556 557 SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {} 558 559 bool SBCommand::IsValid() { return m_opaque_sp.get() != nullptr; } 560 561 const char *SBCommand::GetName() { 562 return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr); 563 } 564 565 const char *SBCommand::GetHelp() { 566 return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString() 567 : nullptr); 568 } 569 570 const char *SBCommand::GetHelpLong() { 571 return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString() 572 : nullptr); 573 } 574 575 void SBCommand::SetHelp(const char *help) { 576 if (IsValid()) 577 m_opaque_sp->SetHelp(help); 578 } 579 580 void SBCommand::SetHelpLong(const char *help) { 581 if (IsValid()) 582 m_opaque_sp->SetHelpLong(help); 583 } 584 585 lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name, 586 const char *help) { 587 if (!IsValid()) 588 return lldb::SBCommand(); 589 if (!m_opaque_sp->IsMultiwordObject()) 590 return lldb::SBCommand(); 591 CommandObjectMultiword *new_command = new CommandObjectMultiword( 592 m_opaque_sp->GetCommandInterpreter(), name, help); 593 new_command->SetRemovable(true); 594 lldb::CommandObjectSP new_command_sp(new_command); 595 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 596 return lldb::SBCommand(new_command_sp); 597 return lldb::SBCommand(); 598 } 599 600 lldb::SBCommand SBCommand::AddCommand(const char *name, 601 lldb::SBCommandPluginInterface *impl, 602 const char *help) { 603 if (!IsValid()) 604 return lldb::SBCommand(); 605 if (!m_opaque_sp->IsMultiwordObject()) 606 return lldb::SBCommand(); 607 lldb::CommandObjectSP new_command_sp; 608 new_command_sp.reset(new CommandPluginInterfaceImplementation( 609 m_opaque_sp->GetCommandInterpreter(), name, impl, help)); 610 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 611 return lldb::SBCommand(new_command_sp); 612 return lldb::SBCommand(); 613 } 614 615 lldb::SBCommand SBCommand::AddCommand(const char *name, 616 lldb::SBCommandPluginInterface *impl, 617 const char *help, const char *syntax) { 618 if (!IsValid()) 619 return lldb::SBCommand(); 620 if (!m_opaque_sp->IsMultiwordObject()) 621 return lldb::SBCommand(); 622 lldb::CommandObjectSP new_command_sp; 623 new_command_sp.reset(new CommandPluginInterfaceImplementation( 624 m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax)); 625 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 626 return lldb::SBCommand(new_command_sp); 627 return lldb::SBCommand(); 628 } 629 630 uint32_t SBCommand::GetFlags() { 631 return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0); 632 } 633 634 void SBCommand::SetFlags(uint32_t flags) { 635 if (IsValid()) 636 m_opaque_sp->GetFlags().Set(flags); 637 } 638