blob: 5d42229917b63fd0dc4607298f5d6b8cebef4629 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandCompletions.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
11// C Includes
12// C++ Includes
13// Other libraries and framework includes
14// Project includes
Jim Ingham84cdc152010-06-15 19:49:27 +000015#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Interpreter/CommandInterpreter.h"
17#include "lldb/Core/FileSpecList.h"
18#include "lldb/Target/Target.h"
19#include "lldb/Interpreter/CommandCompletions.h"
20
21
22using namespace lldb_private;
23
24CommandCompletions::CommonCompletionElement
25CommandCompletions::g_common_completions[] =
26{
27 {eCustomCompletion, NULL},
28 {eSourceFileCompletion, CommandCompletions::SourceFiles},
29 {eDiskFileCompletion, NULL},
30 {eSymbolCompletion, CommandCompletions::Symbols},
31 {eModuleCompletion, CommandCompletions::Modules},
32 {eNoCompletion, NULL} // This one has to be last in the list.
33};
34
35bool
Greg Clayton63094e02010-06-23 01:19:29 +000036CommandCompletions::InvokeCommonCompletionCallbacks
37(
38 CommandInterpreter &interpreter,
39 uint32_t completion_mask,
40 const char *completion_str,
41 int match_start_point,
42 int max_return_elements,
43 SearchFilter *searcher,
44 StringList &matches
45)
Chris Lattner24943d22010-06-08 16:52:24 +000046{
47 bool handled = false;
48
49 if (completion_mask & eCustomCompletion)
50 return false;
51
52 for (int i = 0; ; i++)
53 {
54 if (g_common_completions[i].type == eNoCompletion)
55 break;
56 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
57 && g_common_completions[i].callback != NULL)
58 {
59 handled = true;
Greg Clayton63094e02010-06-23 01:19:29 +000060 g_common_completions[i].callback (interpreter,
61 completion_str,
Chris Lattner24943d22010-06-08 16:52:24 +000062 match_start_point,
63 max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +000064 searcher,
65 matches);
66 }
67 }
68 return handled;
69}
70
71int
Greg Clayton63094e02010-06-23 01:19:29 +000072CommandCompletions::SourceFiles
73(
74 CommandInterpreter &interpreter,
75 const char *partial_file_name,
76 int match_start_point,
77 int max_return_elements,
78 SearchFilter *searcher,
79 StringList &matches
80)
Chris Lattner24943d22010-06-08 16:52:24 +000081{
82 // Find some way to switch "include support files..."
Greg Clayton63094e02010-06-23 01:19:29 +000083 SourceFileCompleter completer (interpreter,
84 false,
85 partial_file_name,
86 match_start_point,
87 max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +000088 matches);
89
90 if (searcher == NULL)
91 {
Greg Clayton63094e02010-06-23 01:19:29 +000092 lldb::TargetSP target_sp = interpreter.GetDebugger().GetCurrentTarget();
Chris Lattner24943d22010-06-08 16:52:24 +000093 SearchFilter null_searcher (target_sp);
94 completer.DoCompletion (&null_searcher);
95 }
96 else
97 {
98 completer.DoCompletion (searcher);
99 }
100 return matches.GetSize();
101}
102
103int
Greg Clayton63094e02010-06-23 01:19:29 +0000104CommandCompletions::Modules
105(
106 CommandInterpreter &interpreter,
107 const char *partial_file_name,
108 int match_start_point,
109 int max_return_elements,
110 SearchFilter *searcher,
111 StringList &matches
112)
Chris Lattner24943d22010-06-08 16:52:24 +0000113{
Greg Clayton63094e02010-06-23 01:19:29 +0000114 ModuleCompleter completer (interpreter,
115 partial_file_name,
116 match_start_point,
117 max_return_elements,
118 matches);
119
Chris Lattner24943d22010-06-08 16:52:24 +0000120 if (searcher == NULL)
121 {
Greg Clayton63094e02010-06-23 01:19:29 +0000122 lldb::TargetSP target_sp = interpreter.GetDebugger().GetCurrentTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000123 SearchFilter null_searcher (target_sp);
124 completer.DoCompletion (&null_searcher);
125 }
126 else
127 {
128 completer.DoCompletion (searcher);
129 }
130 return matches.GetSize();
131}
132
133int
Greg Clayton63094e02010-06-23 01:19:29 +0000134CommandCompletions::Symbols
135(
136 CommandInterpreter &interpreter,
137 const char *partial_file_name,
138 int match_start_point,
139 int max_return_elements,
140 SearchFilter *searcher,
141 StringList &matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000142{
Greg Clayton63094e02010-06-23 01:19:29 +0000143 SymbolCompleter completer (interpreter,
144 partial_file_name,
145 match_start_point,
146 max_return_elements,
147 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000148
149 if (searcher == NULL)
150 {
Greg Clayton63094e02010-06-23 01:19:29 +0000151 lldb::TargetSP target_sp = interpreter.GetDebugger().GetCurrentTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000152 SearchFilter null_searcher (target_sp);
153 completer.DoCompletion (&null_searcher);
154 }
155 else
156 {
157 completer.DoCompletion (searcher);
158 }
159 return matches.GetSize();
160}
161
Greg Clayton63094e02010-06-23 01:19:29 +0000162CommandCompletions::Completer::Completer
163(
164 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000165 const char *completion_str,
166 int match_start_point,
167 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000168 StringList &matches
169) :
Greg Clayton63094e02010-06-23 01:19:29 +0000170 m_interpreter (interpreter),
Chris Lattner24943d22010-06-08 16:52:24 +0000171 m_completion_str (completion_str),
172 m_match_start_point (match_start_point),
173 m_max_return_elements (max_return_elements),
Chris Lattner24943d22010-06-08 16:52:24 +0000174 m_matches (matches)
175{
176}
177
178CommandCompletions::Completer::~Completer ()
179{
180
181}
182
183//----------------------------------------------------------------------
184// SourceFileCompleter
185//----------------------------------------------------------------------
186
Greg Clayton63094e02010-06-23 01:19:29 +0000187CommandCompletions::SourceFileCompleter::SourceFileCompleter
188(
189 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000190 bool include_support_files,
191 const char *completion_str,
192 int match_start_point,
193 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000194 StringList &matches
195) :
Greg Clayton63094e02010-06-23 01:19:29 +0000196 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner24943d22010-06-08 16:52:24 +0000197 m_include_support_files (include_support_files),
198 m_matching_files()
199{
200 FileSpec partial_spec (m_completion_str.c_str());
201 m_file_name = partial_spec.GetFilename().GetCString();
202 m_dir_name = partial_spec.GetDirectory().GetCString();
203}
204
205Searcher::Depth
206CommandCompletions::SourceFileCompleter::GetDepth()
207{
208 return eDepthCompUnit;
209}
210
211Searcher::CallbackReturn
212CommandCompletions::SourceFileCompleter::SearchCallback (
213 SearchFilter &filter,
214 SymbolContext &context,
215 Address *addr,
216 bool complete
217)
218{
219 if (context.comp_unit != NULL)
220 {
221 if (m_include_support_files)
222 {
223 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
224 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
225 {
226 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
227 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
228 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
229 bool match = false;
230 if (m_file_name && sfile_file_name
231 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
232 match = true;
233 if (match && m_dir_name && sfile_dir_name
234 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
235 match = false;
236
237 if (match)
238 {
239 m_matching_files.AppendIfUnique(sfile_spec);
240 }
241 }
242
243 }
244 else
245 {
246 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
247 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
248
249 bool match = false;
250 if (m_file_name && cur_file_name
251 && strstr (cur_file_name, m_file_name) == cur_file_name)
252 match = true;
253
254 if (match && m_dir_name && cur_dir_name
255 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
256 match = false;
257
258 if (match)
259 {
260 m_matching_files.AppendIfUnique(context.comp_unit);
261 }
262 }
263 }
264 return Searcher::eCallbackReturnContinue;
265}
266
267size_t
268CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
269{
270 filter->Search (*this);
271 // Now convert the filelist to completions:
272 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
273 {
274 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
275 }
276 return m_matches.GetSize();
277
278}
279
280//----------------------------------------------------------------------
281// SymbolCompleter
282//----------------------------------------------------------------------
283
284static bool
285regex_chars (const char comp)
286{
287 if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
288 return true;
289 else
290 return false;
291}
Greg Clayton63094e02010-06-23 01:19:29 +0000292CommandCompletions::SymbolCompleter::SymbolCompleter
293(
294 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000295 const char *completion_str,
296 int match_start_point,
297 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000298 StringList &matches
299) :
Greg Clayton63094e02010-06-23 01:19:29 +0000300 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000301{
302 std::string regex_str ("^");
303 regex_str.append(completion_str);
304 regex_str.append(".*");
305 std::string::iterator pos;
306
307 pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
308 while (pos < regex_str.end()) {
309 pos = regex_str.insert(pos, '\\');
310 pos += 2;
311 pos = find_if(pos, regex_str.end(), regex_chars);
312 }
313 m_regex.Compile(regex_str.c_str());
314}
315
316Searcher::Depth
317CommandCompletions::SymbolCompleter::GetDepth()
318{
319 return eDepthModule;
320}
321
322Searcher::CallbackReturn
323CommandCompletions::SymbolCompleter::SearchCallback (
324 SearchFilter &filter,
325 SymbolContext &context,
326 Address *addr,
327 bool complete
328)
329{
330 SymbolContextList func_list;
331 SymbolContextList sym_list;
332
333 if (context.module_sp != NULL)
334 {
335 if (context.module_sp)
336 {
337 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, lldb::eSymbolTypeCode, sym_list);
338 context.module_sp->FindFunctions (m_regex, true, func_list);
339 }
340
341 SymbolContext sc;
342 // Now add the functions & symbols to the list - only add if unique:
343 for (int i = 0; i < func_list.GetSize(); i++)
344 {
345 if (func_list.GetContextAtIndex(i, sc))
346 {
347 if (sc.function)
348 {
349 m_match_set.insert (sc.function->GetMangled().GetDemangledName());
350 }
351 }
352 }
353
354 for (int i = 0; i < sym_list.GetSize(); i++)
355 {
356 if (sym_list.GetContextAtIndex(i, sc))
357 {
358 if (sc.symbol && sc.symbol->GetAddressRangePtr())
359 {
360 m_match_set.insert (sc.symbol->GetMangled().GetDemangledName());
361 }
362 }
363 }
364 }
365 return Searcher::eCallbackReturnContinue;
366}
367
368size_t
369CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
370{
371 filter->Search (*this);
372 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
373 for (pos = m_match_set.begin(); pos != end; pos++)
374 m_matches.AppendString((*pos).GetCString());
375
376 return m_matches.GetSize();
377}
378
379//----------------------------------------------------------------------
380// ModuleCompleter
381//----------------------------------------------------------------------
Greg Clayton63094e02010-06-23 01:19:29 +0000382CommandCompletions::ModuleCompleter::ModuleCompleter
383(
384 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000385 const char *completion_str,
386 int match_start_point,
387 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000388 StringList &matches
389) :
Greg Clayton63094e02010-06-23 01:19:29 +0000390 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000391{
392 FileSpec partial_spec (m_completion_str.c_str());
393 m_file_name = partial_spec.GetFilename().GetCString();
394 m_dir_name = partial_spec.GetDirectory().GetCString();
395}
396
397Searcher::Depth
398CommandCompletions::ModuleCompleter::GetDepth()
399{
400 return eDepthModule;
401}
402
403Searcher::CallbackReturn
404CommandCompletions::ModuleCompleter::SearchCallback (
405 SearchFilter &filter,
406 SymbolContext &context,
407 Address *addr,
408 bool complete
409)
410{
411 if (context.module_sp != NULL)
412 {
413 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
414 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
415
416 bool match = false;
417 if (m_file_name && cur_file_name
418 && strstr (cur_file_name, m_file_name) == cur_file_name)
419 match = true;
420
421 if (match && m_dir_name && cur_dir_name
422 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
423 match = false;
424
425 if (match)
426 {
427 m_matches.AppendString (cur_file_name);
428 }
429 }
430 return Searcher::eCallbackReturnContinue;
431}
432
433size_t
434CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
435{
436 filter->Search (*this);
437 return m_matches.GetSize();
438}
439
440
441