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