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 const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) { 165 return (IsValid() 166 ? m_opaque_ptr->GetDebugger() 167 .GetTopIOHandlerControlSequence(ch) 168 .GetCString() 169 : nullptr); 170 } 171 172 lldb::ReturnStatus 173 SBCommandInterpreter::HandleCommand(const char *command_line, 174 SBCommandReturnObject &result, 175 bool add_to_history) { 176 SBExecutionContext sb_exe_ctx; 177 return HandleCommand(command_line, sb_exe_ctx, result, add_to_history); 178 } 179 180 lldb::ReturnStatus SBCommandInterpreter::HandleCommand( 181 const char *command_line, SBExecutionContext &override_context, 182 SBCommandReturnObject &result, bool add_to_history) { 183 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 184 185 if (log) 186 log->Printf("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", " 187 "SBCommandReturnObject(%p), add_to_history=%i)", 188 static_cast<void *>(m_opaque_ptr), command_line, 189 static_cast<void *>(result.get()), add_to_history); 190 191 ExecutionContext ctx, *ctx_ptr; 192 if (override_context.get()) { 193 ctx = override_context.get()->Lock(true); 194 ctx_ptr = &ctx; 195 } else 196 ctx_ptr = nullptr; 197 198 result.Clear(); 199 if (command_line && IsValid()) { 200 result.ref().SetInteractive(false); 201 m_opaque_ptr->HandleCommand(command_line, 202 add_to_history ? eLazyBoolYes : eLazyBoolNo, 203 result.ref(), ctx_ptr); 204 } else { 205 result->AppendError( 206 "SBCommandInterpreter or the command line is not valid"); 207 result->SetStatus(eReturnStatusFailed); 208 } 209 210 // We need to get the value again, in case the command disabled the log! 211 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API); 212 if (log) { 213 SBStream sstr; 214 result.GetDescription(sstr); 215 log->Printf("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", " 216 "SBCommandReturnObject(%p): %s, add_to_history=%i) => %i", 217 static_cast<void *>(m_opaque_ptr), command_line, 218 static_cast<void *>(result.get()), sstr.GetData(), 219 add_to_history, result.GetStatus()); 220 } 221 222 return result.GetStatus(); 223 } 224 225 void SBCommandInterpreter::HandleCommandsFromFile( 226 lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context, 227 lldb::SBCommandInterpreterRunOptions &options, 228 lldb::SBCommandReturnObject result) { 229 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 230 231 if (log) { 232 SBStream s; 233 file.GetDescription(s); 234 log->Printf("SBCommandInterpreter(%p)::HandleCommandsFromFile " 235 "(file=\"%s\", SBCommandReturnObject(%p))", 236 static_cast<void *>(m_opaque_ptr), s.GetData(), 237 static_cast<void *>(result.get())); 238 } 239 240 if (!IsValid()) { 241 result->AppendError("SBCommandInterpreter is not valid."); 242 result->SetStatus(eReturnStatusFailed); 243 return; 244 } 245 246 if (!file.IsValid()) { 247 SBStream s; 248 file.GetDescription(s); 249 result->AppendErrorWithFormat("File is not valid: %s.", s.GetData()); 250 result->SetStatus(eReturnStatusFailed); 251 } 252 253 FileSpec tmp_spec = file.ref(); 254 ExecutionContext ctx, *ctx_ptr; 255 if (override_context.get()) { 256 ctx = override_context.get()->Lock(true); 257 ctx_ptr = &ctx; 258 } else 259 ctx_ptr = nullptr; 260 261 m_opaque_ptr->HandleCommandsFromFile(tmp_spec, ctx_ptr, options.ref(), 262 result.ref()); 263 } 264 265 int SBCommandInterpreter::HandleCompletion( 266 const char *current_line, const char *cursor, const char *last_char, 267 int match_start_point, int max_return_elements, SBStringList &matches) { 268 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 269 int num_completions = 0; 270 271 // Sanity check the arguments that are passed in: 272 // cursor & last_char have to be within the current_line. 273 if (current_line == nullptr || cursor == nullptr || last_char == nullptr) 274 return 0; 275 276 if (cursor < current_line || last_char < current_line) 277 return 0; 278 279 size_t current_line_size = strlen(current_line); 280 if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) || 281 last_char - current_line > static_cast<ptrdiff_t>(current_line_size)) 282 return 0; 283 284 if (log) 285 log->Printf("SBCommandInterpreter(%p)::HandleCompletion " 286 "(current_line=\"%s\", cursor at: %" PRId64 287 ", last char at: %" PRId64 288 ", match_start_point: %d, max_return_elements: %d)", 289 static_cast<void *>(m_opaque_ptr), current_line, 290 static_cast<uint64_t>(cursor - current_line), 291 static_cast<uint64_t>(last_char - current_line), 292 match_start_point, max_return_elements); 293 294 if (IsValid()) { 295 lldb_private::StringList lldb_matches; 296 num_completions = m_opaque_ptr->HandleCompletion( 297 current_line, cursor, last_char, match_start_point, max_return_elements, 298 lldb_matches); 299 300 SBStringList temp_list(&lldb_matches); 301 matches.AppendList(temp_list); 302 } 303 if (log) 304 log->Printf( 305 "SBCommandInterpreter(%p)::HandleCompletion - Found %d completions.", 306 static_cast<void *>(m_opaque_ptr), num_completions); 307 308 return num_completions; 309 } 310 311 int SBCommandInterpreter::HandleCompletion(const char *current_line, 312 uint32_t cursor_pos, 313 int match_start_point, 314 int max_return_elements, 315 lldb::SBStringList &matches) { 316 const char *cursor = current_line + cursor_pos; 317 const char *last_char = current_line + strlen(current_line); 318 return HandleCompletion(current_line, cursor, last_char, match_start_point, 319 max_return_elements, matches); 320 } 321 322 bool SBCommandInterpreter::HasCommands() { 323 return (IsValid() ? m_opaque_ptr->HasCommands() : false); 324 } 325 326 bool SBCommandInterpreter::HasAliases() { 327 return (IsValid() ? m_opaque_ptr->HasAliases() : false); 328 } 329 330 bool SBCommandInterpreter::HasAliasOptions() { 331 return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false); 332 } 333 334 SBProcess SBCommandInterpreter::GetProcess() { 335 SBProcess sb_process; 336 ProcessSP process_sp; 337 if (IsValid()) { 338 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 339 if (target_sp) { 340 std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); 341 process_sp = target_sp->GetProcessSP(); 342 sb_process.SetSP(process_sp); 343 } 344 } 345 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 346 347 if (log) 348 log->Printf("SBCommandInterpreter(%p)::GetProcess () => SBProcess(%p)", 349 static_cast<void *>(m_opaque_ptr), 350 static_cast<void *>(process_sp.get())); 351 352 return sb_process; 353 } 354 355 SBDebugger SBCommandInterpreter::GetDebugger() { 356 SBDebugger sb_debugger; 357 if (IsValid()) 358 sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this()); 359 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 360 361 if (log) 362 log->Printf("SBCommandInterpreter(%p)::GetDebugger () => SBDebugger(%p)", 363 static_cast<void *>(m_opaque_ptr), 364 static_cast<void *>(sb_debugger.get())); 365 366 return sb_debugger; 367 } 368 369 bool SBCommandInterpreter::GetPromptOnQuit() { 370 return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false); 371 } 372 373 void SBCommandInterpreter::SetPromptOnQuit(bool b) { 374 if (IsValid()) 375 m_opaque_ptr->SetPromptOnQuit(b); 376 } 377 378 void SBCommandInterpreter::ResolveCommand(const char *command_line, 379 SBCommandReturnObject &result) { 380 result.Clear(); 381 if (command_line && IsValid()) { 382 m_opaque_ptr->ResolveCommand(command_line, result.ref()); 383 } else { 384 result->AppendError( 385 "SBCommandInterpreter or the command line is not valid"); 386 result->SetStatus(eReturnStatusFailed); 387 } 388 } 389 390 CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; } 391 392 CommandInterpreter &SBCommandInterpreter::ref() { 393 assert(m_opaque_ptr); 394 return *m_opaque_ptr; 395 } 396 397 void SBCommandInterpreter::reset( 398 lldb_private::CommandInterpreter *interpreter) { 399 m_opaque_ptr = interpreter; 400 } 401 402 void SBCommandInterpreter::SourceInitFileInHomeDirectory( 403 SBCommandReturnObject &result) { 404 result.Clear(); 405 if (IsValid()) { 406 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 407 std::unique_lock<std::recursive_mutex> lock; 408 if (target_sp) 409 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 410 m_opaque_ptr->SourceInitFile(false, result.ref()); 411 } else { 412 result->AppendError("SBCommandInterpreter is not valid"); 413 result->SetStatus(eReturnStatusFailed); 414 } 415 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 416 417 if (log) 418 log->Printf("SBCommandInterpreter(%p)::SourceInitFileInHomeDirectory " 419 "(&SBCommandReturnObject(%p))", 420 static_cast<void *>(m_opaque_ptr), 421 static_cast<void *>(result.get())); 422 } 423 424 void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory( 425 SBCommandReturnObject &result) { 426 result.Clear(); 427 if (IsValid()) { 428 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 429 std::unique_lock<std::recursive_mutex> lock; 430 if (target_sp) 431 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 432 m_opaque_ptr->SourceInitFile(true, result.ref()); 433 } else { 434 result->AppendError("SBCommandInterpreter is not valid"); 435 result->SetStatus(eReturnStatusFailed); 436 } 437 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 438 439 if (log) 440 log->Printf( 441 "SBCommandInterpreter(%p)::SourceInitFileInCurrentWorkingDirectory " 442 "(&SBCommandReturnObject(%p))", 443 static_cast<void *>(m_opaque_ptr), static_cast<void *>(result.get())); 444 } 445 446 SBBroadcaster SBCommandInterpreter::GetBroadcaster() { 447 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 448 449 SBBroadcaster broadcaster(m_opaque_ptr, false); 450 451 if (log) 452 log->Printf( 453 "SBCommandInterpreter(%p)::GetBroadcaster() => SBBroadcaster(%p)", 454 static_cast<void *>(m_opaque_ptr), 455 static_cast<void *>(broadcaster.get())); 456 457 return broadcaster; 458 } 459 460 const char *SBCommandInterpreter::GetBroadcasterClass() { 461 return CommandInterpreter::GetStaticBroadcasterClass().AsCString(); 462 } 463 464 const char *SBCommandInterpreter::GetArgumentTypeAsCString( 465 const lldb::CommandArgumentType arg_type) { 466 return CommandObject::GetArgumentTypeAsCString(arg_type); 467 } 468 469 const char *SBCommandInterpreter::GetArgumentDescriptionAsCString( 470 const lldb::CommandArgumentType arg_type) { 471 return CommandObject::GetArgumentDescriptionAsCString(arg_type); 472 } 473 474 bool SBCommandInterpreter::EventIsCommandInterpreterEvent( 475 const lldb::SBEvent &event) { 476 return event.GetBroadcasterClass() == 477 SBCommandInterpreter::GetBroadcasterClass(); 478 } 479 480 bool SBCommandInterpreter::SetCommandOverrideCallback( 481 const char *command_name, lldb::CommandOverrideCallback callback, 482 void *baton) { 483 if (command_name && command_name[0] && IsValid()) { 484 llvm::StringRef command_name_str = command_name; 485 CommandObject *cmd_obj = 486 m_opaque_ptr->GetCommandObjectForCommand(command_name_str); 487 if (cmd_obj) { 488 assert(command_name_str.empty()); 489 cmd_obj->SetOverrideCallback(callback, baton); 490 return true; 491 } 492 } 493 return false; 494 } 495 496 lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name, 497 const char *help) { 498 CommandObjectMultiword *new_command = 499 new CommandObjectMultiword(*m_opaque_ptr, name, help); 500 new_command->SetRemovable(true); 501 lldb::CommandObjectSP new_command_sp(new_command); 502 if (new_command_sp && 503 m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) 504 return lldb::SBCommand(new_command_sp); 505 return lldb::SBCommand(); 506 } 507 508 lldb::SBCommand SBCommandInterpreter::AddCommand( 509 const char *name, lldb::SBCommandPluginInterface *impl, const char *help) { 510 lldb::CommandObjectSP new_command_sp; 511 new_command_sp.reset(new CommandPluginInterfaceImplementation( 512 *m_opaque_ptr, name, impl, help)); 513 514 if (new_command_sp && 515 m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) 516 return lldb::SBCommand(new_command_sp); 517 return lldb::SBCommand(); 518 } 519 520 lldb::SBCommand 521 SBCommandInterpreter::AddCommand(const char *name, 522 lldb::SBCommandPluginInterface *impl, 523 const char *help, const char *syntax) { 524 lldb::CommandObjectSP new_command_sp; 525 new_command_sp.reset(new CommandPluginInterfaceImplementation( 526 *m_opaque_ptr, name, impl, help, syntax)); 527 528 if (new_command_sp && 529 m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) 530 return lldb::SBCommand(new_command_sp); 531 return lldb::SBCommand(); 532 } 533 534 SBCommand::SBCommand() = default; 535 536 SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {} 537 538 bool SBCommand::IsValid() { return m_opaque_sp.get() != nullptr; } 539 540 const char *SBCommand::GetName() { 541 return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr); 542 } 543 544 const char *SBCommand::GetHelp() { 545 return (IsValid() ? m_opaque_sp->GetHelp() : nullptr); 546 } 547 548 const char *SBCommand::GetHelpLong() { 549 return (IsValid() ? m_opaque_sp->GetHelpLong() : nullptr); 550 } 551 552 void SBCommand::SetHelp(const char *help) { 553 if (IsValid()) 554 m_opaque_sp->SetHelp(help); 555 } 556 557 void SBCommand::SetHelpLong(const char *help) { 558 if (IsValid()) 559 m_opaque_sp->SetHelpLong(help); 560 } 561 562 lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name, 563 const char *help) { 564 if (!IsValid()) 565 return lldb::SBCommand(); 566 if (!m_opaque_sp->IsMultiwordObject()) 567 return lldb::SBCommand(); 568 CommandObjectMultiword *new_command = new CommandObjectMultiword( 569 m_opaque_sp->GetCommandInterpreter(), name, help); 570 new_command->SetRemovable(true); 571 lldb::CommandObjectSP new_command_sp(new_command); 572 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 573 return lldb::SBCommand(new_command_sp); 574 return lldb::SBCommand(); 575 } 576 577 lldb::SBCommand SBCommand::AddCommand(const char *name, 578 lldb::SBCommandPluginInterface *impl, 579 const char *help) { 580 if (!IsValid()) 581 return lldb::SBCommand(); 582 if (!m_opaque_sp->IsMultiwordObject()) 583 return lldb::SBCommand(); 584 lldb::CommandObjectSP new_command_sp; 585 new_command_sp.reset(new CommandPluginInterfaceImplementation( 586 m_opaque_sp->GetCommandInterpreter(), name, impl, help)); 587 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 588 return lldb::SBCommand(new_command_sp); 589 return lldb::SBCommand(); 590 } 591 592 lldb::SBCommand SBCommand::AddCommand(const char *name, 593 lldb::SBCommandPluginInterface *impl, 594 const char *help, const char *syntax) { 595 if (!IsValid()) 596 return lldb::SBCommand(); 597 if (!m_opaque_sp->IsMultiwordObject()) 598 return lldb::SBCommand(); 599 lldb::CommandObjectSP new_command_sp; 600 new_command_sp.reset(new CommandPluginInterfaceImplementation( 601 m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax)); 602 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 603 return lldb::SBCommand(new_command_sp); 604 return lldb::SBCommand(); 605 } 606 607 uint32_t SBCommand::GetFlags() { 608 return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0); 609 } 610 611 void SBCommand::SetFlags(uint32_t flags) { 612 if (IsValid()) 613 m_opaque_sp->GetFlags().Set(flags); 614 } 615