blob: f2bf7da63aaa4d636bc614bd29f176a563c7c501 [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
36CommandCompletions::InvokeCommonCompletionCallbacks (uint32_t completion_mask,
37 const char *completion_str,
38 int match_start_point,
39 int max_return_elements,
40 lldb_private::CommandInterpreter *interpreter,
41 SearchFilter *searcher,
42 lldb_private::StringList &matches)
43{
44 bool handled = false;
45
46 if (completion_mask & eCustomCompletion)
47 return false;
48
49 for (int i = 0; ; i++)
50 {
51 if (g_common_completions[i].type == eNoCompletion)
52 break;
53 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
54 && g_common_completions[i].callback != NULL)
55 {
56 handled = true;
57 g_common_completions[i].callback (completion_str,
58 match_start_point,
59 max_return_elements,
60 interpreter,
61 searcher,
62 matches);
63 }
64 }
65 return handled;
66}
67
68int
69CommandCompletions::SourceFiles (const char *partial_file_name,
70 int match_start_point,
71 int max_return_elements,
72 lldb_private::CommandInterpreter *interpreter,
73 SearchFilter *searcher,
74 lldb_private::StringList &matches)
75{
76 // Find some way to switch "include support files..."
77 SourceFileCompleter completer (false, partial_file_name, match_start_point, max_return_elements, interpreter,
78 matches);
79
80 if (searcher == NULL)
81 {
82 lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
83 SearchFilter null_searcher (target_sp);
84 completer.DoCompletion (&null_searcher);
85 }
86 else
87 {
88 completer.DoCompletion (searcher);
89 }
90 return matches.GetSize();
91}
92
93int
94CommandCompletions::Modules (const char *partial_file_name,
95 int match_start_point,
96 int max_return_elements,
97 lldb_private::CommandInterpreter *interpreter,
98 SearchFilter *searcher,
99 lldb_private::StringList &matches)
100{
101 ModuleCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
102
103 if (searcher == NULL)
104 {
105 lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
106 SearchFilter null_searcher (target_sp);
107 completer.DoCompletion (&null_searcher);
108 }
109 else
110 {
111 completer.DoCompletion (searcher);
112 }
113 return matches.GetSize();
114}
115
116int
117CommandCompletions::Symbols (const char *partial_file_name,
118 int match_start_point,
119 int max_return_elements,
120 lldb_private::CommandInterpreter *interpreter,
121 SearchFilter *searcher,
122 lldb_private::StringList &matches)
123{
124 SymbolCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
125
126 if (searcher == NULL)
127 {
128 lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
129 SearchFilter null_searcher (target_sp);
130 completer.DoCompletion (&null_searcher);
131 }
132 else
133 {
134 completer.DoCompletion (searcher);
135 }
136 return matches.GetSize();
137}
138
139CommandCompletions::Completer::Completer (
140 const char *completion_str,
141 int match_start_point,
142 int max_return_elements,
143 CommandInterpreter *interpreter,
144 StringList &matches
145) :
146 m_completion_str (completion_str),
147 m_match_start_point (match_start_point),
148 m_max_return_elements (max_return_elements),
149 m_interpreter (interpreter),
150 m_matches (matches)
151{
152}
153
154CommandCompletions::Completer::~Completer ()
155{
156
157}
158
159//----------------------------------------------------------------------
160// SourceFileCompleter
161//----------------------------------------------------------------------
162
163CommandCompletions::SourceFileCompleter::SourceFileCompleter (
164 bool include_support_files,
165 const char *completion_str,
166 int match_start_point,
167 int max_return_elements,
168 CommandInterpreter *interpreter,
169 StringList &matches
170) :
171 CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches),
172 m_include_support_files (include_support_files),
173 m_matching_files()
174{
175 FileSpec partial_spec (m_completion_str.c_str());
176 m_file_name = partial_spec.GetFilename().GetCString();
177 m_dir_name = partial_spec.GetDirectory().GetCString();
178}
179
180Searcher::Depth
181CommandCompletions::SourceFileCompleter::GetDepth()
182{
183 return eDepthCompUnit;
184}
185
186Searcher::CallbackReturn
187CommandCompletions::SourceFileCompleter::SearchCallback (
188 SearchFilter &filter,
189 SymbolContext &context,
190 Address *addr,
191 bool complete
192)
193{
194 if (context.comp_unit != NULL)
195 {
196 if (m_include_support_files)
197 {
198 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
199 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
200 {
201 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
202 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
203 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
204 bool match = false;
205 if (m_file_name && sfile_file_name
206 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
207 match = true;
208 if (match && m_dir_name && sfile_dir_name
209 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
210 match = false;
211
212 if (match)
213 {
214 m_matching_files.AppendIfUnique(sfile_spec);
215 }
216 }
217
218 }
219 else
220 {
221 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
222 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
223
224 bool match = false;
225 if (m_file_name && cur_file_name
226 && strstr (cur_file_name, m_file_name) == cur_file_name)
227 match = true;
228
229 if (match && m_dir_name && cur_dir_name
230 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
231 match = false;
232
233 if (match)
234 {
235 m_matching_files.AppendIfUnique(context.comp_unit);
236 }
237 }
238 }
239 return Searcher::eCallbackReturnContinue;
240}
241
242size_t
243CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
244{
245 filter->Search (*this);
246 // Now convert the filelist to completions:
247 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
248 {
249 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
250 }
251 return m_matches.GetSize();
252
253}
254
255//----------------------------------------------------------------------
256// SymbolCompleter
257//----------------------------------------------------------------------
258
259static bool
260regex_chars (const char comp)
261{
262 if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
263 return true;
264 else
265 return false;
266}
267CommandCompletions::SymbolCompleter::SymbolCompleter (
268 const char *completion_str,
269 int match_start_point,
270 int max_return_elements,
271 CommandInterpreter *interpreter,
272 StringList &matches
273) :
274 CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
275{
276 std::string regex_str ("^");
277 regex_str.append(completion_str);
278 regex_str.append(".*");
279 std::string::iterator pos;
280
281 pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
282 while (pos < regex_str.end()) {
283 pos = regex_str.insert(pos, '\\');
284 pos += 2;
285 pos = find_if(pos, regex_str.end(), regex_chars);
286 }
287 m_regex.Compile(regex_str.c_str());
288}
289
290Searcher::Depth
291CommandCompletions::SymbolCompleter::GetDepth()
292{
293 return eDepthModule;
294}
295
296Searcher::CallbackReturn
297CommandCompletions::SymbolCompleter::SearchCallback (
298 SearchFilter &filter,
299 SymbolContext &context,
300 Address *addr,
301 bool complete
302)
303{
304 SymbolContextList func_list;
305 SymbolContextList sym_list;
306
307 if (context.module_sp != NULL)
308 {
309 if (context.module_sp)
310 {
311 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, lldb::eSymbolTypeCode, sym_list);
312 context.module_sp->FindFunctions (m_regex, true, func_list);
313 }
314
315 SymbolContext sc;
316 // Now add the functions & symbols to the list - only add if unique:
317 for (int i = 0; i < func_list.GetSize(); i++)
318 {
319 if (func_list.GetContextAtIndex(i, sc))
320 {
321 if (sc.function)
322 {
323 m_match_set.insert (sc.function->GetMangled().GetDemangledName());
324 }
325 }
326 }
327
328 for (int i = 0; i < sym_list.GetSize(); i++)
329 {
330 if (sym_list.GetContextAtIndex(i, sc))
331 {
332 if (sc.symbol && sc.symbol->GetAddressRangePtr())
333 {
334 m_match_set.insert (sc.symbol->GetMangled().GetDemangledName());
335 }
336 }
337 }
338 }
339 return Searcher::eCallbackReturnContinue;
340}
341
342size_t
343CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
344{
345 filter->Search (*this);
346 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
347 for (pos = m_match_set.begin(); pos != end; pos++)
348 m_matches.AppendString((*pos).GetCString());
349
350 return m_matches.GetSize();
351}
352
353//----------------------------------------------------------------------
354// ModuleCompleter
355//----------------------------------------------------------------------
356CommandCompletions::ModuleCompleter::ModuleCompleter (
357 const char *completion_str,
358 int match_start_point,
359 int max_return_elements,
360 CommandInterpreter *interpreter,
361 StringList &matches
362) :
363 CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
364{
365 FileSpec partial_spec (m_completion_str.c_str());
366 m_file_name = partial_spec.GetFilename().GetCString();
367 m_dir_name = partial_spec.GetDirectory().GetCString();
368}
369
370Searcher::Depth
371CommandCompletions::ModuleCompleter::GetDepth()
372{
373 return eDepthModule;
374}
375
376Searcher::CallbackReturn
377CommandCompletions::ModuleCompleter::SearchCallback (
378 SearchFilter &filter,
379 SymbolContext &context,
380 Address *addr,
381 bool complete
382)
383{
384 if (context.module_sp != NULL)
385 {
386 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
387 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
388
389 bool match = false;
390 if (m_file_name && cur_file_name
391 && strstr (cur_file_name, m_file_name) == cur_file_name)
392 match = true;
393
394 if (match && m_dir_name && cur_dir_name
395 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
396 match = false;
397
398 if (match)
399 {
400 m_matches.AppendString (cur_file_name);
401 }
402 }
403 return Searcher::eCallbackReturnContinue;
404}
405
406size_t
407CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
408{
409 filter->Search (*this);
410 return m_matches.GetSize();
411}
412
413
414