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