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