blob: d25c6fa697be72ad856116b027e487e35880c133 [file] [log] [blame]
Chris Lattner30fdc8d2010-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
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011
12// C Includes
Jim Ingham558ce122010-06-30 05:02:46 +000013#include <sys/stat.h>
14#include <dirent.h>
Greg Claytonfd184262011-02-05 02:27:52 +000015#if defined(__APPLE__) || defined(__linux__)
Jim Ingham7cc478b2010-07-02 00:45:55 +000016#include <pwd.h>
Greg Claytonfd184262011-02-05 02:27:52 +000017#endif
Jim Ingham558ce122010-06-30 05:02:46 +000018
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019// C++ Includes
20// Other libraries and framework includes
21// Project includes
Greg Clayton53239f02011-02-08 05:05:52 +000022#include "lldb/Host/FileSpec.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000023#include "lldb/Core/FileSpecList.h"
Greg Claytonab65b342011-04-13 22:47:15 +000024#include "lldb/Core/PluginManager.h"
Greg Clayton1f746072012-08-29 21:13:06 +000025#include "lldb/Core/Module.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000026#include "lldb/Interpreter/Args.h"
27#include "lldb/Interpreter/CommandCompletions.h"
28#include "lldb/Interpreter/CommandInterpreter.h"
Greg Clayton1f746072012-08-29 21:13:06 +000029#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000030#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000031#include "lldb/Target/Target.h"
32#include "lldb/Utility/CleanUp.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033
34using namespace lldb_private;
35
36CommandCompletions::CommonCompletionElement
37CommandCompletions::g_common_completions[] =
38{
Jim Ingham558ce122010-06-30 05:02:46 +000039 {eCustomCompletion, NULL},
40 {eSourceFileCompletion, CommandCompletions::SourceFiles},
41 {eDiskFileCompletion, CommandCompletions::DiskFiles},
42 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
43 {eSymbolCompletion, CommandCompletions::Symbols},
44 {eModuleCompletion, CommandCompletions::Modules},
Caroline Tice3df9a8d2010-09-04 00:03:46 +000045 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
Greg Claytonab65b342011-04-13 22:47:15 +000046 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
47 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
Greg Claytonf21fead2013-05-14 23:43:18 +000048 {eVariablePathCompletion, CommandCompletions::VariablePath},
Jim Ingham558ce122010-06-30 05:02:46 +000049 {eNoCompletion, NULL} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050};
51
52bool
Greg Clayton66111032010-06-23 01:19:29 +000053CommandCompletions::InvokeCommonCompletionCallbacks
54(
55 CommandInterpreter &interpreter,
56 uint32_t completion_mask,
57 const char *completion_str,
58 int match_start_point,
59 int max_return_elements,
60 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000061 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +000062 StringList &matches
63)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064{
65 bool handled = false;
66
67 if (completion_mask & eCustomCompletion)
68 return false;
69
70 for (int i = 0; ; i++)
71 {
72 if (g_common_completions[i].type == eNoCompletion)
73 break;
74 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
75 && g_common_completions[i].callback != NULL)
76 {
77 handled = true;
Greg Clayton66111032010-06-23 01:19:29 +000078 g_common_completions[i].callback (interpreter,
79 completion_str,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080 match_start_point,
81 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082 searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000083 word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084 matches);
85 }
86 }
87 return handled;
88}
89
90int
Greg Clayton66111032010-06-23 01:19:29 +000091CommandCompletions::SourceFiles
92(
93 CommandInterpreter &interpreter,
94 const char *partial_file_name,
95 int match_start_point,
96 int max_return_elements,
97 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000098 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +000099 StringList &matches
100)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101{
Jim Ingham558ce122010-06-30 05:02:46 +0000102 word_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000103 // Find some way to switch "include support files..."
Greg Clayton66111032010-06-23 01:19:29 +0000104 SourceFileCompleter completer (interpreter,
105 false,
106 partial_file_name,
107 match_start_point,
108 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109 matches);
110
111 if (searcher == NULL)
112 {
Jim Ingham2976d002010-08-26 21:32:51 +0000113 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114 SearchFilter null_searcher (target_sp);
115 completer.DoCompletion (&null_searcher);
116 }
117 else
118 {
119 completer.DoCompletion (searcher);
120 }
121 return matches.GetSize();
122}
123
Jim Ingham558ce122010-06-30 05:02:46 +0000124static int
125DiskFilesOrDirectories
126(
127 const char *partial_file_name,
128 bool only_directories,
129 bool &saw_directory,
130 StringList &matches
131)
132{
133 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
134 // If it is not defined on your host system, you'll need to implement it yourself...
135
Greg Claytonc7bece562013-01-25 18:06:21 +0000136 size_t partial_name_len = strlen(partial_file_name);
Jim Ingham558ce122010-06-30 05:02:46 +0000137
138 if (partial_name_len >= PATH_MAX)
139 return matches.GetSize();
140
141 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
142 // below will point to the place of the remainder in this string. Then when we've resolved the
143 // containing directory, and opened it, we'll read the directory contents and overwrite the
144 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
145 // the form the user originally typed.
146
147 char partial_name_copy[PATH_MAX];
Benjamin Kramer021b6052010-06-30 13:43:47 +0000148 memcpy(partial_name_copy, partial_file_name, partial_name_len);
Jim Ingham558ce122010-06-30 05:02:46 +0000149 partial_name_copy[partial_name_len] = '\0';
150
Greg Clayton710dd5a2011-01-08 20:28:42 +0000151 // We'll need to save a copy of the remainder for comparison, which we do here.
Jim Ingham558ce122010-06-30 05:02:46 +0000152 char remainder[PATH_MAX];
153
154 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
155 char *end_ptr;
156
157 end_ptr = strrchr(partial_name_copy, '/');
158
159 // This will store the resolved form of the containing directory
160 char containing_part[PATH_MAX];
161
162 if (end_ptr == NULL)
163 {
164 // There's no directory. If the thing begins with a "~" then this is a bare
165 // user name.
166 if (*partial_name_copy == '~')
167 {
168 // Nothing here but the user name. We could just put a slash on the end,
Jim Ingham7cc478b2010-07-02 00:45:55 +0000169 // but for completeness sake we'll resolve the user name and only put a slash
Jim Ingham558ce122010-06-30 05:02:46 +0000170 // on the end if it exists.
Jim Ingham7cc478b2010-07-02 00:45:55 +0000171 char resolved_username[PATH_MAX];
Greg Claytonc982c762010-07-09 20:39:50 +0000172 size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username,
Jim Ingham7cc478b2010-07-02 00:45:55 +0000173 sizeof (resolved_username));
174
175 // Not sure how this would happen, a username longer than PATH_MAX? Still...
176 if (resolved_username_len >= sizeof (resolved_username))
177 return matches.GetSize();
Jim Ingham84363072011-02-08 23:24:09 +0000178 else if (resolved_username_len == 0)
Jim Ingham7cc478b2010-07-02 00:45:55 +0000179 {
180 // The user name didn't resolve, let's look in the password database for matches.
181 // The user name database contains duplicates, and is not in alphabetical order, so
182 // we'll use a set to manage that for us.
Jim Ingham84363072011-02-08 23:24:09 +0000183 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
184 if (matches.GetSize() > 0)
185 saw_directory = true;
Jim Ingham7cc478b2010-07-02 00:45:55 +0000186 return matches.GetSize();
Jim Ingham84363072011-02-08 23:24:09 +0000187 }
188 else
189 {
190 //The thing exists, put a '/' on the end, and return it...
191 // FIXME: complete user names here:
192 partial_name_copy[partial_name_len] = '/';
193 partial_name_copy[partial_name_len+1] = '\0';
194 matches.AppendString(partial_name_copy);
195 saw_directory = true;
196 return matches.GetSize();
197 }
Jim Ingham558ce122010-06-30 05:02:46 +0000198 }
199 else
200 {
201 // The containing part is the CWD, and the whole string is the remainder.
202 containing_part[0] = '.';
203 containing_part[1] = '\0';
204 strcpy(remainder, partial_name_copy);
205 end_ptr = partial_name_copy;
206 }
207 }
208 else
209 {
210 if (end_ptr == partial_name_copy)
211 {
212 // We're completing a file or directory in the root volume.
213 containing_part[0] = '/';
214 containing_part[1] = '\0';
215 }
216 else
217 {
218 size_t len = end_ptr - partial_name_copy;
219 memcpy(containing_part, partial_name_copy, len);
220 containing_part[len] = '\0';
221 }
222 // Push end_ptr past the final "/" and set remainder.
223 end_ptr++;
224 strcpy(remainder, end_ptr);
225 }
226
Jim Ingham7cc478b2010-07-02 00:45:55 +0000227 // Look for a user name in the containing part, and if it's there, resolve it and stick the
Jim Ingham558ce122010-06-30 05:02:46 +0000228 // result back into the containing_part:
Greg Claytonfd184262011-02-05 02:27:52 +0000229
Jim Ingham558ce122010-06-30 05:02:46 +0000230 if (*partial_name_copy == '~')
231 {
Jim Ingham84363072011-02-08 23:24:09 +0000232 size_t resolved_username_len = FileSpec::ResolveUsername(containing_part,
233 containing_part,
234 sizeof (containing_part));
Jim Ingham558ce122010-06-30 05:02:46 +0000235 // User name doesn't exist, we're not getting any further...
Greg Claytona0807352010-07-06 16:11:44 +0000236 if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
Jim Ingham558ce122010-06-30 05:02:46 +0000237 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000238 }
Greg Claytonfd184262011-02-05 02:27:52 +0000239
Jim Ingham558ce122010-06-30 05:02:46 +0000240 // Okay, containing_part is now the directory we want to open and look for files:
Greg Clayton9b62fd22011-02-01 05:15:22 +0000241
242 lldb_utility::CleanUp <DIR *, int> dir_stream (opendir(containing_part), NULL, closedir);
243 if (!dir_stream.is_valid())
Jim Ingham558ce122010-06-30 05:02:46 +0000244 return matches.GetSize();
Greg Clayton9b62fd22011-02-01 05:15:22 +0000245
Jim Ingham558ce122010-06-30 05:02:46 +0000246 struct dirent *dirent_buf;
247
248 size_t baselen = end_ptr - partial_name_copy;
249
Greg Clayton9b62fd22011-02-01 05:15:22 +0000250 while ((dirent_buf = readdir(dir_stream.get())) != NULL)
Jim Ingham558ce122010-06-30 05:02:46 +0000251 {
252 char *name = dirent_buf->d_name;
253
254 // Omit ".", ".." and any . files if the match string doesn't start with .
255 if (name[0] == '.')
256 {
257 if (name[1] == '\0')
258 continue;
259 else if (name[1] == '.' && name[2] == '\0')
260 continue;
261 else if (remainder[0] != '.')
262 continue;
263 }
264
Jim Ingham7cc478b2010-07-02 00:45:55 +0000265 // If we found a directory, we put a "/" at the end of the name.
266
Jim Ingham558ce122010-06-30 05:02:46 +0000267 if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name)
268 {
269 if (strlen(name) + baselen >= PATH_MAX)
270 continue;
271
272 strcpy(end_ptr, name);
273
274 bool isa_directory = false;
275 if (dirent_buf->d_type & DT_DIR)
276 isa_directory = true;
277 else if (dirent_buf->d_type & DT_LNK)
278 {
279 struct stat stat_buf;
Jason Molendad9761cd2011-07-08 00:38:03 +0000280 if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
Jim Ingham558ce122010-06-30 05:02:46 +0000281 isa_directory = true;
282 }
283
284 if (isa_directory)
285 {
286 saw_directory = true;
287 size_t len = strlen(partial_name_copy);
288 partial_name_copy[len] = '/';
289 partial_name_copy[len + 1] = '\0';
290 }
291 if (only_directories && !isa_directory)
292 continue;
293 matches.AppendString(partial_name_copy);
294 }
295 }
296
297 return matches.GetSize();
298}
299
300int
301CommandCompletions::DiskFiles
302(
303 CommandInterpreter &interpreter,
304 const char *partial_file_name,
305 int match_start_point,
306 int max_return_elements,
307 SearchFilter *searcher,
308 bool &word_complete,
309 StringList &matches
310)
311{
312
313 int ret_val = DiskFilesOrDirectories (partial_file_name,
314 false,
315 word_complete,
316 matches);
317 word_complete = !word_complete;
318 return ret_val;
319}
320
321int
322CommandCompletions::DiskDirectories
323(
324 CommandInterpreter &interpreter,
325 const char *partial_file_name,
326 int match_start_point,
327 int max_return_elements,
328 SearchFilter *searcher,
329 bool &word_complete,
330 StringList &matches
331)
332{
333 int ret_val = DiskFilesOrDirectories (partial_file_name,
334 true,
335 word_complete,
336 matches);
337 word_complete = false;
338 return ret_val;
339}
340
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000341int
Greg Clayton66111032010-06-23 01:19:29 +0000342CommandCompletions::Modules
343(
344 CommandInterpreter &interpreter,
345 const char *partial_file_name,
346 int match_start_point,
347 int max_return_elements,
348 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000349 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000350 StringList &matches
351)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000352{
Jim Ingham558ce122010-06-30 05:02:46 +0000353 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000354 ModuleCompleter completer (interpreter,
355 partial_file_name,
356 match_start_point,
357 max_return_elements,
358 matches);
359
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000360 if (searcher == NULL)
361 {
Jim Ingham2976d002010-08-26 21:32:51 +0000362 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000363 SearchFilter null_searcher (target_sp);
364 completer.DoCompletion (&null_searcher);
365 }
366 else
367 {
368 completer.DoCompletion (searcher);
369 }
370 return matches.GetSize();
371}
372
373int
Greg Clayton66111032010-06-23 01:19:29 +0000374CommandCompletions::Symbols
375(
376 CommandInterpreter &interpreter,
377 const char *partial_file_name,
378 int match_start_point,
379 int max_return_elements,
380 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000381 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000382 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000383{
Jim Ingham558ce122010-06-30 05:02:46 +0000384 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000385 SymbolCompleter completer (interpreter,
386 partial_file_name,
387 match_start_point,
388 max_return_elements,
389 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390
391 if (searcher == NULL)
392 {
Jim Ingham2976d002010-08-26 21:32:51 +0000393 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000394 SearchFilter null_searcher (target_sp);
395 completer.DoCompletion (&null_searcher);
396 }
397 else
398 {
399 completer.DoCompletion (searcher);
400 }
401 return matches.GetSize();
402}
403
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000404int
405CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
406 const char *partial_setting_name,
407 int match_start_point,
408 int max_return_elements,
409 SearchFilter *searcher,
410 bool &word_complete,
411 StringList &matches)
412{
Greg Clayton67cc0632012-08-22 17:17:09 +0000413 // Cache the full setting name list
414 static StringList g_property_names;
415 if (g_property_names.GetSize() == 0)
416 {
417 // Generate the full setting name list on demand
418 lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
419 if (properties_sp)
420 {
421 StreamString strm;
422 properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
423 const std::string &str = strm.GetString();
424 g_property_names.SplitIntoLines(str.c_str(), str.size());
425 }
426 }
427
428 size_t exact_matches_idx = SIZE_MAX;
429 const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
Greg Clayton67cc0632012-08-22 17:17:09 +0000430 word_complete = exact_matches_idx != SIZE_MAX;
431 return num_matches;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000432}
433
Greg Claytonab65b342011-04-13 22:47:15 +0000434
435int
436CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
437 const char *partial_name,
438 int match_start_point,
439 int max_return_elements,
440 SearchFilter *searcher,
441 bool &word_complete,
442 lldb_private::StringList &matches)
443{
444 const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
445 word_complete = num_matches == 1;
446 return num_matches;
447}
448
449int
450CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
451 const char *partial_name,
452 int match_start_point,
453 int max_return_elements,
454 SearchFilter *searcher,
455 bool &word_complete,
456 lldb_private::StringList &matches)
457{
458 const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
459 word_complete = num_matches == 1;
460 return num_matches;
461}
462
463
Greg Claytonf21fead2013-05-14 23:43:18 +0000464int
465CommandCompletions::VariablePath (CommandInterpreter &interpreter,
466 const char *partial_name,
467 int match_start_point,
468 int max_return_elements,
469 SearchFilter *searcher,
470 bool &word_complete,
471 lldb_private::StringList &matches)
472{
473 return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
474}
475
476
Greg Clayton66111032010-06-23 01:19:29 +0000477CommandCompletions::Completer::Completer
478(
479 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000480 const char *completion_str,
481 int match_start_point,
482 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000483 StringList &matches
484) :
Greg Clayton66111032010-06-23 01:19:29 +0000485 m_interpreter (interpreter),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000486 m_completion_str (completion_str),
487 m_match_start_point (match_start_point),
488 m_max_return_elements (max_return_elements),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000489 m_matches (matches)
490{
491}
492
493CommandCompletions::Completer::~Completer ()
494{
495
496}
497
498//----------------------------------------------------------------------
499// SourceFileCompleter
500//----------------------------------------------------------------------
501
Greg Clayton66111032010-06-23 01:19:29 +0000502CommandCompletions::SourceFileCompleter::SourceFileCompleter
503(
504 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000505 bool include_support_files,
506 const char *completion_str,
507 int match_start_point,
508 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000509 StringList &matches
510) :
Greg Clayton66111032010-06-23 01:19:29 +0000511 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000512 m_include_support_files (include_support_files),
513 m_matching_files()
514{
Greg Clayton274060b2010-10-20 20:54:39 +0000515 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000516 m_file_name = partial_spec.GetFilename().GetCString();
517 m_dir_name = partial_spec.GetDirectory().GetCString();
518}
519
520Searcher::Depth
521CommandCompletions::SourceFileCompleter::GetDepth()
522{
523 return eDepthCompUnit;
524}
525
526Searcher::CallbackReturn
527CommandCompletions::SourceFileCompleter::SearchCallback (
528 SearchFilter &filter,
529 SymbolContext &context,
530 Address *addr,
531 bool complete
532)
533{
534 if (context.comp_unit != NULL)
535 {
536 if (m_include_support_files)
537 {
538 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
539 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
540 {
541 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
542 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
543 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
544 bool match = false;
545 if (m_file_name && sfile_file_name
546 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
547 match = true;
548 if (match && m_dir_name && sfile_dir_name
549 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
550 match = false;
551
552 if (match)
553 {
554 m_matching_files.AppendIfUnique(sfile_spec);
555 }
556 }
557
558 }
559 else
560 {
561 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
562 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
563
564 bool match = false;
565 if (m_file_name && cur_file_name
566 && strstr (cur_file_name, m_file_name) == cur_file_name)
567 match = true;
568
569 if (match && m_dir_name && cur_dir_name
570 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
571 match = false;
572
573 if (match)
574 {
575 m_matching_files.AppendIfUnique(context.comp_unit);
576 }
577 }
578 }
579 return Searcher::eCallbackReturnContinue;
580}
581
582size_t
583CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
584{
585 filter->Search (*this);
586 // Now convert the filelist to completions:
587 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
588 {
589 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
590 }
591 return m_matches.GetSize();
592
593}
594
595//----------------------------------------------------------------------
596// SymbolCompleter
597//----------------------------------------------------------------------
598
599static bool
600regex_chars (const char comp)
601{
602 if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
603 return true;
604 else
605 return false;
606}
Greg Clayton66111032010-06-23 01:19:29 +0000607CommandCompletions::SymbolCompleter::SymbolCompleter
608(
609 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000610 const char *completion_str,
611 int match_start_point,
612 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000613 StringList &matches
614) :
Greg Clayton66111032010-06-23 01:19:29 +0000615 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000616{
617 std::string regex_str ("^");
618 regex_str.append(completion_str);
619 regex_str.append(".*");
620 std::string::iterator pos;
621
622 pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
623 while (pos < regex_str.end()) {
624 pos = regex_str.insert(pos, '\\');
625 pos += 2;
626 pos = find_if(pos, regex_str.end(), regex_chars);
627 }
628 m_regex.Compile(regex_str.c_str());
629}
630
631Searcher::Depth
632CommandCompletions::SymbolCompleter::GetDepth()
633{
634 return eDepthModule;
635}
636
637Searcher::CallbackReturn
638CommandCompletions::SymbolCompleter::SearchCallback (
639 SearchFilter &filter,
640 SymbolContext &context,
641 Address *addr,
642 bool complete
643)
644{
Greg Clayton931180e2011-01-27 06:44:37 +0000645 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000646 {
Greg Clayton931180e2011-01-27 06:44:37 +0000647 SymbolContextList sc_list;
648 const bool include_symbols = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000649 const bool include_inlines = true;
Greg Clayton931180e2011-01-27 06:44:37 +0000650 const bool append = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000651 context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000652
653 SymbolContext sc;
654 // Now add the functions & symbols to the list - only add if unique:
Greg Clayton931180e2011-01-27 06:44:37 +0000655 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000656 {
Greg Clayton931180e2011-01-27 06:44:37 +0000657 if (sc_list.GetContextAtIndex(i, sc))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000658 {
Jim Ingham530a4132011-09-27 19:48:20 +0000659 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
660 if (!func_name.IsEmpty())
661 m_match_set.insert (func_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000662 }
663 }
664 }
665 return Searcher::eCallbackReturnContinue;
666}
667
668size_t
669CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
670{
671 filter->Search (*this);
672 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
673 for (pos = m_match_set.begin(); pos != end; pos++)
674 m_matches.AppendString((*pos).GetCString());
675
676 return m_matches.GetSize();
677}
678
679//----------------------------------------------------------------------
680// ModuleCompleter
681//----------------------------------------------------------------------
Greg Clayton66111032010-06-23 01:19:29 +0000682CommandCompletions::ModuleCompleter::ModuleCompleter
683(
684 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000685 const char *completion_str,
686 int match_start_point,
687 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000688 StringList &matches
689) :
Greg Clayton66111032010-06-23 01:19:29 +0000690 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000691{
Greg Clayton274060b2010-10-20 20:54:39 +0000692 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000693 m_file_name = partial_spec.GetFilename().GetCString();
694 m_dir_name = partial_spec.GetDirectory().GetCString();
695}
696
697Searcher::Depth
698CommandCompletions::ModuleCompleter::GetDepth()
699{
700 return eDepthModule;
701}
702
703Searcher::CallbackReturn
704CommandCompletions::ModuleCompleter::SearchCallback (
705 SearchFilter &filter,
706 SymbolContext &context,
707 Address *addr,
708 bool complete
709)
710{
Greg Clayton747bcb02011-09-17 06:21:20 +0000711 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000712 {
713 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
714 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
715
716 bool match = false;
717 if (m_file_name && cur_file_name
718 && strstr (cur_file_name, m_file_name) == cur_file_name)
719 match = true;
720
721 if (match && m_dir_name && cur_dir_name
722 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
723 match = false;
724
725 if (match)
726 {
727 m_matches.AppendString (cur_file_name);
728 }
729 }
730 return Searcher::eCallbackReturnContinue;
731}
732
733size_t
734CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
735{
736 filter->Search (*this);
737 return m_matches.GetSize();
738}