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

source code of lldb/source/API/SBCommandInterpreter.cpp