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 #include "lldb/lldb-types.h"
11 #include "lldb/Core/SourceManager.h"
12 #include "lldb/Core/Listener.h"
13 #include "lldb/Interpreter/CommandInterpreter.h"
14 #include "lldb/Interpreter/CommandObjectMultiword.h"
15 #include "lldb/Interpreter/CommandReturnObject.h"
16 #include "lldb/Target/Target.h"
17 
18 #include "lldb/API/SBBroadcaster.h"
19 #include "lldb/API/SBCommandReturnObject.h"
20 #include "lldb/API/SBCommandInterpreter.h"
21 #include "lldb/API/SBProcess.h"
22 #include "lldb/API/SBTarget.h"
23 #include "lldb/API/SBListener.h"
24 #include "lldb/API/SBStream.h"
25 #include "lldb/API/SBStringList.h"
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 
30 class CommandPluginInterfaceImplementation : public CommandObjectParsed
31 {
32 public:
33     CommandPluginInterfaceImplementation (CommandInterpreter &interpreter,
34                                           const char *name,
35                                           lldb::SBCommandPluginInterface* backend,
36                                           const char *help = NULL,
37                                           const char *syntax = NULL,
38                                           uint32_t flags = 0) :
39     CommandObjectParsed (interpreter, name, help, syntax, flags),
40     m_backend(backend) {}
41 
42     virtual bool
43     IsRemovable() const { return true; }
44 
45 protected:
46     virtual bool
47     DoExecute (Args& command, CommandReturnObject &result)
48     {
49         SBCommandReturnObject sb_return(&result);
50         SBCommandInterpreter sb_interpreter(&m_interpreter);
51         SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this());
52         bool ret = m_backend->DoExecute (debugger_sb,(char**)command.GetArgumentVector(), sb_return);
53         sb_return.Release();
54         return ret;
55     }
56     lldb::SBCommandPluginInterface* m_backend;
57 };
58 
59 SBCommandInterpreter::SBCommandInterpreter (CommandInterpreter *interpreter) :
60     m_opaque_ptr (interpreter)
61 {
62     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
63 
64     if (log)
65         log->Printf ("SBCommandInterpreter::SBCommandInterpreter (interpreter=%p)"
66                      " => SBCommandInterpreter(%p)", interpreter, m_opaque_ptr);
67 }
68 
69 SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) :
70     m_opaque_ptr (rhs.m_opaque_ptr)
71 {
72 }
73 
74 const SBCommandInterpreter &
75 SBCommandInterpreter::operator = (const SBCommandInterpreter &rhs)
76 {
77     m_opaque_ptr = rhs.m_opaque_ptr;
78     return *this;
79 }
80 
81 SBCommandInterpreter::~SBCommandInterpreter ()
82 {
83 }
84 
85 bool
86 SBCommandInterpreter::IsValid() const
87 {
88     return m_opaque_ptr != NULL;
89 }
90 
91 
92 bool
93 SBCommandInterpreter::CommandExists (const char *cmd)
94 {
95     if (cmd && m_opaque_ptr)
96         return m_opaque_ptr->CommandExists (cmd);
97     return false;
98 }
99 
100 bool
101 SBCommandInterpreter::AliasExists (const char *cmd)
102 {
103     if (cmd && m_opaque_ptr)
104         return m_opaque_ptr->AliasExists (cmd);
105     return false;
106 }
107 
108 lldb::ReturnStatus
109 SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnObject &result, bool add_to_history)
110 {
111     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
112 
113     if (log)
114         log->Printf ("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", SBCommandReturnObject(%p), add_to_history=%i)",
115                      m_opaque_ptr, command_line, result.get(), add_to_history);
116 
117     result.Clear();
118     if (command_line && m_opaque_ptr)
119     {
120         TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
121         Mutex::Locker api_locker;
122         if (target_sp)
123             api_locker.Lock(target_sp->GetAPIMutex());
124         m_opaque_ptr->HandleCommand (command_line, add_to_history ? eLazyBoolYes : eLazyBoolNo, result.ref());
125     }
126     else
127     {
128         result->AppendError ("SBCommandInterpreter or the command line is not valid");
129         result->SetStatus (eReturnStatusFailed);
130     }
131 
132     // We need to get the value again, in case the command disabled the log!
133     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
134     if (log)
135     {
136         SBStream sstr;
137         result.GetDescription (sstr);
138         log->Printf ("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", SBCommandReturnObject(%p): %s, add_to_history=%i) => %i",
139                      m_opaque_ptr, command_line, result.get(), sstr.GetData(), add_to_history, result.GetStatus());
140     }
141 
142     return result.GetStatus();
143 }
144 
145 int
146 SBCommandInterpreter::HandleCompletion (const char *current_line,
147                                         const char *cursor,
148                                         const char *last_char,
149                                         int match_start_point,
150                                         int max_return_elements,
151                                         SBStringList &matches)
152 {
153     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
154     int num_completions = 0;
155 
156     // Sanity check the arguments that are passed in:
157     // cursor & last_char have to be within the current_line.
158     if (current_line == NULL || cursor == NULL || last_char == NULL)
159         return 0;
160 
161     if (cursor < current_line || last_char < current_line)
162         return 0;
163 
164     size_t current_line_size = strlen (current_line);
165     if (cursor - current_line > current_line_size || last_char - current_line > current_line_size)
166         return 0;
167 
168     if (log)
169         log->Printf ("SBCommandInterpreter(%p)::HandleCompletion (current_line=\"%s\", cursor at: %lld, last char at: %lld, match_start_point: %d, max_return_elements: %d)",
170                      m_opaque_ptr, current_line, (uint64_t) (cursor - current_line), (uint64_t) (last_char - current_line), match_start_point, max_return_elements);
171 
172     if (m_opaque_ptr)
173     {
174         lldb_private::StringList lldb_matches;
175         num_completions =  m_opaque_ptr->HandleCompletion (current_line, cursor, last_char, match_start_point,
176                                                            max_return_elements, lldb_matches);
177 
178         SBStringList temp_list (&lldb_matches);
179         matches.AppendList (temp_list);
180     }
181     if (log)
182         log->Printf ("SBCommandInterpreter(%p)::HandleCompletion - Found %d completions.", m_opaque_ptr, num_completions);
183 
184     return num_completions;
185 }
186 
187 int
188 SBCommandInterpreter::HandleCompletion (const char *current_line,
189                   uint32_t cursor_pos,
190                   int match_start_point,
191                   int max_return_elements,
192                   lldb::SBStringList &matches)
193 {
194     const char *cursor = current_line + cursor_pos;
195     const char *last_char = current_line + strlen (current_line);
196     return HandleCompletion (current_line, cursor, last_char, match_start_point, max_return_elements, matches);
197 }
198 
199 bool
200 SBCommandInterpreter::HasCommands ()
201 {
202     if (m_opaque_ptr)
203         return m_opaque_ptr->HasCommands();
204     return false;
205 }
206 
207 bool
208 SBCommandInterpreter::HasAliases ()
209 {
210     if (m_opaque_ptr)
211         return m_opaque_ptr->HasAliases();
212     return false;
213 }
214 
215 bool
216 SBCommandInterpreter::HasAliasOptions ()
217 {
218     if (m_opaque_ptr)
219         return m_opaque_ptr->HasAliasOptions ();
220     return false;
221 }
222 
223 SBProcess
224 SBCommandInterpreter::GetProcess ()
225 {
226     SBProcess sb_process;
227     ProcessSP process_sp;
228     if (m_opaque_ptr)
229     {
230         TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
231         if (target_sp)
232         {
233             Mutex::Locker api_locker(target_sp->GetAPIMutex());
234             process_sp = target_sp->GetProcessSP();
235             sb_process.SetSP(process_sp);
236         }
237     }
238     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
239 
240     if (log)
241         log->Printf ("SBCommandInterpreter(%p)::GetProcess () => SBProcess(%p)",
242                      m_opaque_ptr, process_sp.get());
243 
244 
245     return sb_process;
246 }
247 
248 SBDebugger
249 SBCommandInterpreter::GetDebugger ()
250 {
251     SBDebugger sb_debugger;
252     if (m_opaque_ptr)
253         sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());
254     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
255 
256     if (log)
257         log->Printf ("SBCommandInterpreter(%p)::GetDebugger () => SBDebugger(%p)",
258                      m_opaque_ptr, sb_debugger.get());
259 
260 
261     return sb_debugger;
262 }
263 
264 CommandInterpreter *
265 SBCommandInterpreter::get ()
266 {
267     return m_opaque_ptr;
268 }
269 
270 CommandInterpreter &
271 SBCommandInterpreter::ref ()
272 {
273     assert (m_opaque_ptr);
274     return *m_opaque_ptr;
275 }
276 
277 void
278 SBCommandInterpreter::reset (lldb_private::CommandInterpreter *interpreter)
279 {
280     m_opaque_ptr = interpreter;
281 }
282 
283 void
284 SBCommandInterpreter::SourceInitFileInHomeDirectory (SBCommandReturnObject &result)
285 {
286     result.Clear();
287     if (m_opaque_ptr)
288     {
289         TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
290         Mutex::Locker api_locker;
291         if (target_sp)
292             api_locker.Lock(target_sp->GetAPIMutex());
293         m_opaque_ptr->SourceInitFile (false, result.ref());
294     }
295     else
296     {
297         result->AppendError ("SBCommandInterpreter is not valid");
298         result->SetStatus (eReturnStatusFailed);
299     }
300     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
301 
302     if (log)
303         log->Printf ("SBCommandInterpreter(%p)::SourceInitFileInHomeDirectory (&SBCommandReturnObject(%p))",
304                      m_opaque_ptr, result.get());
305 
306 }
307 
308 void
309 SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory (SBCommandReturnObject &result)
310 {
311     result.Clear();
312     if (m_opaque_ptr)
313     {
314         TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
315         Mutex::Locker api_locker;
316         if (target_sp)
317             api_locker.Lock(target_sp->GetAPIMutex());
318         m_opaque_ptr->SourceInitFile (true, result.ref());
319     }
320     else
321     {
322         result->AppendError ("SBCommandInterpreter is not valid");
323         result->SetStatus (eReturnStatusFailed);
324     }
325     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
326 
327     if (log)
328         log->Printf ("SBCommandInterpreter(%p)::SourceInitFileInCurrentWorkingDirectory (&SBCommandReturnObject(%p))",
329                      m_opaque_ptr, result.get());
330 }
331 
332 SBBroadcaster
333 SBCommandInterpreter::GetBroadcaster ()
334 {
335     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
336 
337     SBBroadcaster broadcaster (m_opaque_ptr, false);
338 
339     if (log)
340         log->Printf ("SBCommandInterpreter(%p)::GetBroadcaster() => SBBroadcaster(%p)",
341                      m_opaque_ptr, broadcaster.get());
342 
343     return broadcaster;
344 }
345 
346 const char *
347 SBCommandInterpreter::GetBroadcasterClass ()
348 {
349     return Communication::GetStaticBroadcasterClass().AsCString();
350 }
351 
352 const char *
353 SBCommandInterpreter::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type)
354 {
355     return CommandObject::GetArgumentTypeAsCString (arg_type);
356 }
357 
358 const char *
359 SBCommandInterpreter::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type)
360 {
361     return CommandObject::GetArgumentDescriptionAsCString (arg_type);
362 }
363 
364 bool
365 SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name,
366                                                   lldb::CommandOverrideCallback callback,
367                                                   void *baton)
368 {
369     if (command_name && command_name[0] && m_opaque_ptr)
370     {
371         std::string command_name_str (command_name);
372         CommandObject *cmd_obj = m_opaque_ptr->GetCommandObjectForCommand(command_name_str);
373         if (cmd_obj)
374         {
375             assert(command_name_str.empty());
376             cmd_obj->SetOverrideCallback (callback, baton);
377             return true;
378         }
379     }
380     return false;
381 }
382 
383 #ifndef LLDB_DISABLE_PYTHON
384 
385 // Defined in the SWIG source file
386 extern "C" void
387 init_lldb(void);
388 
389 #else
390 
391 extern "C" void init_lldb(void);
392 
393 // Usually defined in the SWIG source file, but we have sripting disabled
394 extern "C" void
395 init_lldb(void)
396 {
397 }
398 
399 #endif
400 
401 void
402 SBCommandInterpreter::InitializeSWIG ()
403 {
404     static bool g_initialized = false;
405     if (!g_initialized)
406     {
407         g_initialized = true;
408 #ifndef LLDB_DISABLE_PYTHON
409         ScriptInterpreter::InitializeInterpreter (init_lldb);
410 #endif
411     }
412 }
413 
414 lldb::SBCommand
415 SBCommandInterpreter::AddMultiwordCommand (const char* name, const char* help)
416 {
417     CommandObjectMultiword *new_command = new CommandObjectMultiword(*m_opaque_ptr,name,help);
418     new_command->SetRemovable (true);
419     lldb::CommandObjectSP new_command_sp(new_command);
420     if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
421         return lldb::SBCommand(new_command_sp);
422     return lldb::SBCommand();
423 }
424 
425 lldb::SBCommand
426 SBCommandInterpreter::AddCommand (const char* name, lldb::SBCommandPluginInterface* impl, const char* help)
427 {
428     lldb::CommandObjectSP new_command_sp;
429     new_command_sp.reset(new CommandPluginInterfaceImplementation(*m_opaque_ptr,name,impl,help));
430 
431     if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
432         return lldb::SBCommand(new_command_sp);
433     return lldb::SBCommand();
434 }
435 
436 SBCommand::SBCommand ()
437 {}
438 
439 SBCommand::SBCommand (lldb::CommandObjectSP cmd_sp) : m_opaque_sp (cmd_sp)
440 {}
441 
442 bool
443 SBCommand::IsValid ()
444 {
445     return (bool)m_opaque_sp;
446 }
447 
448 const char*
449 SBCommand::GetName ()
450 {
451     if (IsValid ())
452         return m_opaque_sp->GetCommandName ();
453     return NULL;
454 }
455 
456 const char*
457 SBCommand::GetHelp ()
458 {
459     if (IsValid ())
460         return m_opaque_sp->GetHelp ();
461     return NULL;
462 }
463 
464 lldb::SBCommand
465 SBCommand::AddMultiwordCommand (const char* name, const char* help)
466 {
467     if (!IsValid ())
468         return lldb::SBCommand();
469     if (m_opaque_sp->IsMultiwordObject() == false)
470         return lldb::SBCommand();
471     CommandObjectMultiword *new_command = new CommandObjectMultiword(m_opaque_sp->GetCommandInterpreter(),name,help);
472     new_command->SetRemovable (true);
473     lldb::CommandObjectSP new_command_sp(new_command);
474     if (new_command_sp && m_opaque_sp->LoadSubCommand(name,new_command_sp))
475         return lldb::SBCommand(new_command_sp);
476     return lldb::SBCommand();
477 }
478 
479 lldb::SBCommand
480 SBCommand::AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, const char* help)
481 {
482     if (!IsValid ())
483         return lldb::SBCommand();
484     if (m_opaque_sp->IsMultiwordObject() == false)
485         return lldb::SBCommand();
486     lldb::CommandObjectSP new_command_sp;
487     new_command_sp.reset(new CommandPluginInterfaceImplementation(m_opaque_sp->GetCommandInterpreter(),name,impl,help));
488     if (new_command_sp && m_opaque_sp->LoadSubCommand(name,new_command_sp))
489         return lldb::SBCommand(new_command_sp);
490     return lldb::SBCommand();
491 }
492 
493