1 | //===-- SBCommandInterpreter.cpp ------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/lldb-types.h" |
10 | |
11 | #include "lldb/Interpreter/CommandInterpreter.h" |
12 | #include "lldb/Interpreter/CommandObjectMultiword.h" |
13 | #include "lldb/Interpreter/CommandReturnObject.h" |
14 | #include "lldb/Target/Target.h" |
15 | #include "lldb/Utility/Instrumentation.h" |
16 | #include "lldb/Utility/Listener.h" |
17 | |
18 | #include "lldb/API/SBBroadcaster.h" |
19 | #include "lldb/API/SBCommandInterpreter.h" |
20 | #include "lldb/API/SBCommandInterpreterRunOptions.h" |
21 | #include "lldb/API/SBCommandReturnObject.h" |
22 | #include "lldb/API/SBEvent.h" |
23 | #include "lldb/API/SBExecutionContext.h" |
24 | #include "lldb/API/SBListener.h" |
25 | #include "lldb/API/SBProcess.h" |
26 | #include "lldb/API/SBStream.h" |
27 | #include "lldb/API/SBStringList.h" |
28 | #include "lldb/API/SBTarget.h" |
29 | |
30 | #include <memory> |
31 | #include <optional> |
32 | |
33 | using namespace lldb; |
34 | using namespace lldb_private; |
35 | |
36 | namespace lldb_private { |
37 | class CommandPluginInterfaceImplementation : public CommandObjectParsed { |
38 | public: |
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 ¤t_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 | |
72 | protected: |
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 | |
84 | SBCommandInterpreter::SBCommandInterpreter() : m_opaque_ptr() { |
85 | LLDB_INSTRUMENT_VA(this); |
86 | } |
87 | |
88 | SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter) |
89 | : m_opaque_ptr(interpreter) { |
90 | LLDB_INSTRUMENT_VA(this, interpreter); |
91 | } |
92 | |
93 | SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) |
94 | : m_opaque_ptr(rhs.m_opaque_ptr) { |
95 | LLDB_INSTRUMENT_VA(this, rhs); |
96 | } |
97 | |
98 | SBCommandInterpreter::~SBCommandInterpreter() = default; |
99 | |
100 | const SBCommandInterpreter &SBCommandInterpreter:: |
101 | operator=(const SBCommandInterpreter &rhs) { |
102 | LLDB_INSTRUMENT_VA(this, rhs); |
103 | |
104 | m_opaque_ptr = rhs.m_opaque_ptr; |
105 | return *this; |
106 | } |
107 | |
108 | bool SBCommandInterpreter::IsValid() const { |
109 | LLDB_INSTRUMENT_VA(this); |
110 | return this->operator bool(); |
111 | } |
112 | SBCommandInterpreter::operator bool() const { |
113 | LLDB_INSTRUMENT_VA(this); |
114 | |
115 | return m_opaque_ptr != nullptr; |
116 | } |
117 | |
118 | bool 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 | |
125 | bool 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 | |
132 | bool 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 | |
139 | bool SBCommandInterpreter::IsActive() { |
140 | LLDB_INSTRUMENT_VA(this); |
141 | |
142 | return (IsValid() ? m_opaque_ptr->IsActive() : false); |
143 | } |
144 | |
145 | bool SBCommandInterpreter::WasInterrupted() const { |
146 | LLDB_INSTRUMENT_VA(this); |
147 | |
148 | return (IsValid() ? m_opaque_ptr->GetDebugger().InterruptRequested() : false); |
149 | } |
150 | |
151 | bool SBCommandInterpreter::InterruptCommand() { |
152 | LLDB_INSTRUMENT_VA(this); |
153 | |
154 | return (IsValid() ? m_opaque_ptr->InterruptCommand() : false); |
155 | } |
156 | |
157 | const 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 | |
168 | lldb::ReturnStatus |
169 | SBCommandInterpreter::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 | |
178 | lldb::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 | |
203 | void 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 | |
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 | 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 | |
309 | int 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 | |
323 | int 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 | |
337 | bool SBCommandInterpreter::HasCommands() { |
338 | LLDB_INSTRUMENT_VA(this); |
339 | |
340 | return (IsValid() ? m_opaque_ptr->HasCommands() : false); |
341 | } |
342 | |
343 | bool SBCommandInterpreter::HasAliases() { |
344 | LLDB_INSTRUMENT_VA(this); |
345 | |
346 | return (IsValid() ? m_opaque_ptr->HasAliases() : false); |
347 | } |
348 | |
349 | bool SBCommandInterpreter::HasAliasOptions() { |
350 | LLDB_INSTRUMENT_VA(this); |
351 | |
352 | return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false); |
353 | } |
354 | |
355 | bool SBCommandInterpreter::IsInteractive() { |
356 | LLDB_INSTRUMENT_VA(this); |
357 | |
358 | return (IsValid() ? m_opaque_ptr->IsInteractive() : false); |
359 | } |
360 | |
361 | SBProcess 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 | |
378 | SBDebugger 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 | |
388 | bool SBCommandInterpreter::GetPromptOnQuit() { |
389 | LLDB_INSTRUMENT_VA(this); |
390 | |
391 | return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false); |
392 | } |
393 | |
394 | void SBCommandInterpreter::SetPromptOnQuit(bool b) { |
395 | LLDB_INSTRUMENT_VA(this, b); |
396 | |
397 | if (IsValid()) |
398 | m_opaque_ptr->SetPromptOnQuit(b); |
399 | } |
400 | |
401 | void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) { |
402 | LLDB_INSTRUMENT_VA(this, allow); |
403 | |
404 | if (m_opaque_ptr) |
405 | m_opaque_ptr->AllowExitCodeOnQuit(allow); |
406 | } |
407 | |
408 | bool 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 | |
417 | int 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 | |
424 | void 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 | |
437 | CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; } |
438 | |
439 | CommandInterpreter &SBCommandInterpreter::ref() { |
440 | assert(m_opaque_ptr); |
441 | return *m_opaque_ptr; |
442 | } |
443 | |
444 | void SBCommandInterpreter::reset( |
445 | lldb_private::CommandInterpreter *interpreter) { |
446 | m_opaque_ptr = interpreter; |
447 | } |
448 | |
449 | void 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 | |
465 | void SBCommandInterpreter::SourceInitFileInHomeDirectory( |
466 | SBCommandReturnObject &result) { |
467 | LLDB_INSTRUMENT_VA(this, result); |
468 | |
469 | SourceInitFileInHomeDirectory(result, /*is_repl=*/false); |
470 | } |
471 | |
472 | void 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 | |
488 | void 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 | |
504 | SBBroadcaster SBCommandInterpreter::GetBroadcaster() { |
505 | LLDB_INSTRUMENT_VA(this); |
506 | |
507 | SBBroadcaster broadcaster(m_opaque_ptr, false); |
508 | |
509 | return broadcaster; |
510 | } |
511 | |
512 | const char *SBCommandInterpreter::GetBroadcasterClass() { |
513 | LLDB_INSTRUMENT(); |
514 | |
515 | return CommandInterpreter::GetStaticBroadcasterClass().AsCString(); |
516 | } |
517 | |
518 | const 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 | |
526 | const 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 | |
534 | bool SBCommandInterpreter::EventIsCommandInterpreterEvent( |
535 | const lldb::SBEvent &event) { |
536 | LLDB_INSTRUMENT_VA(event); |
537 | |
538 | return event.GetBroadcasterClass() == |
539 | SBCommandInterpreter::GetBroadcasterClass(); |
540 | } |
541 | |
542 | bool 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 | |
560 | SBStructuredData 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 | |
573 | lldb::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 | |
586 | lldb::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 | |
594 | lldb::SBCommand |
595 | SBCommandInterpreter::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 | |
602 | lldb::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 | |
618 | SBCommand::SBCommand() { LLDB_INSTRUMENT_VA(this); } |
619 | |
620 | SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {} |
621 | |
622 | bool SBCommand::IsValid() { |
623 | LLDB_INSTRUMENT_VA(this); |
624 | return this->operator bool(); |
625 | } |
626 | SBCommand::operator bool() const { |
627 | LLDB_INSTRUMENT_VA(this); |
628 | |
629 | return m_opaque_sp.get() != nullptr; |
630 | } |
631 | |
632 | const char *SBCommand::GetName() { |
633 | LLDB_INSTRUMENT_VA(this); |
634 | |
635 | return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr); |
636 | } |
637 | |
638 | const char *SBCommand::GetHelp() { |
639 | LLDB_INSTRUMENT_VA(this); |
640 | |
641 | return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString() |
642 | : nullptr); |
643 | } |
644 | |
645 | const char *SBCommand::GetHelpLong() { |
646 | LLDB_INSTRUMENT_VA(this); |
647 | |
648 | return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString() |
649 | : nullptr); |
650 | } |
651 | |
652 | void SBCommand::SetHelp(const char *help) { |
653 | LLDB_INSTRUMENT_VA(this, help); |
654 | |
655 | if (IsValid()) |
656 | m_opaque_sp->SetHelp(help); |
657 | } |
658 | |
659 | void SBCommand::SetHelpLong(const char *help) { |
660 | LLDB_INSTRUMENT_VA(this, help); |
661 | |
662 | if (IsValid()) |
663 | m_opaque_sp->SetHelpLong(help); |
664 | } |
665 | |
666 | lldb::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 | |
683 | lldb::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 | |
691 | lldb::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 | |
698 | lldb::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 | |
717 | uint32_t SBCommand::GetFlags() { |
718 | LLDB_INSTRUMENT_VA(this); |
719 | |
720 | return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0); |
721 | } |
722 | |
723 | void SBCommand::SetFlags(uint32_t flags) { |
724 | LLDB_INSTRUMENT_VA(this, flags); |
725 | |
726 | if (IsValid()) |
727 | m_opaque_sp->GetFlags().Set(flags); |
728 | } |
729 | |