blob: 970aa692bd27eeb5cd6b1cd4dd418ee4006f5e8e [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>
Greg Claytonfd184262011-02-05 02:27:52 +000014#if defined(__APPLE__) || defined(__linux__)
Jim Ingham7cc478b2010-07-02 00:45:55 +000015#include <pwd.h>
Greg Claytonfd184262011-02-05 02:27:52 +000016#endif
Jim Ingham558ce122010-06-30 05:02:46 +000017
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018// C++ Includes
19// Other libraries and framework includes
20// Project includes
Greg Clayton53239f02011-02-08 05:05:52 +000021#include "lldb/Host/FileSpec.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000022#include "lldb/Core/FileSpecList.h"
Greg Claytonab65b342011-04-13 22:47:15 +000023#include "lldb/Core/PluginManager.h"
Greg Clayton1f746072012-08-29 21:13:06 +000024#include "lldb/Core/Module.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000025#include "lldb/Interpreter/Args.h"
26#include "lldb/Interpreter/CommandCompletions.h"
27#include "lldb/Interpreter/CommandInterpreter.h"
Greg Clayton1f746072012-08-29 21:13:06 +000028#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000029#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000030#include "lldb/Target/Target.h"
31#include "lldb/Utility/CleanUp.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032
33using namespace lldb_private;
34
35CommandCompletions::CommonCompletionElement
36CommandCompletions::g_common_completions[] =
37{
Jim Ingham558ce122010-06-30 05:02:46 +000038 {eCustomCompletion, NULL},
39 {eSourceFileCompletion, CommandCompletions::SourceFiles},
40 {eDiskFileCompletion, CommandCompletions::DiskFiles},
41 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
42 {eSymbolCompletion, CommandCompletions::Symbols},
43 {eModuleCompletion, CommandCompletions::Modules},
Caroline Tice3df9a8d2010-09-04 00:03:46 +000044 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
Greg Claytonab65b342011-04-13 22:47:15 +000045 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
46 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
Greg Claytonf21fead2013-05-14 23:43:18 +000047 {eVariablePathCompletion, CommandCompletions::VariablePath},
Jim Ingham558ce122010-06-30 05:02:46 +000048 {eNoCompletion, NULL} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000049};
50
51bool
Greg Clayton66111032010-06-23 01:19:29 +000052CommandCompletions::InvokeCommonCompletionCallbacks
53(
54 CommandInterpreter &interpreter,
55 uint32_t completion_mask,
56 const char *completion_str,
57 int match_start_point,
58 int max_return_elements,
59 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000060 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +000061 StringList &matches
62)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000063{
64 bool handled = false;
65
66 if (completion_mask & eCustomCompletion)
67 return false;
68
69 for (int i = 0; ; i++)
70 {
71 if (g_common_completions[i].type == eNoCompletion)
72 break;
73 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
74 && g_common_completions[i].callback != NULL)
75 {
76 handled = true;
Greg Clayton66111032010-06-23 01:19:29 +000077 g_common_completions[i].callback (interpreter,
78 completion_str,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079 match_start_point,
80 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081 searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000082 word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000083 matches);
84 }
85 }
86 return handled;
87}
88
89int
Greg Clayton66111032010-06-23 01:19:29 +000090CommandCompletions::SourceFiles
91(
92 CommandInterpreter &interpreter,
93 const char *partial_file_name,
94 int match_start_point,
95 int max_return_elements,
96 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000097 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +000098 StringList &matches
99)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100{
Jim Ingham558ce122010-06-30 05:02:46 +0000101 word_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000102 // Find some way to switch "include support files..."
Greg Clayton66111032010-06-23 01:19:29 +0000103 SourceFileCompleter completer (interpreter,
104 false,
105 partial_file_name,
106 match_start_point,
107 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000108 matches);
109
110 if (searcher == NULL)
111 {
Jim Ingham2976d002010-08-26 21:32:51 +0000112 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113 SearchFilter null_searcher (target_sp);
114 completer.DoCompletion (&null_searcher);
115 }
116 else
117 {
118 completer.DoCompletion (searcher);
119 }
120 return matches.GetSize();
121}
122
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000123typedef struct DiskFilesOrDirectoriesBaton
124{
125 const char *remainder;
126 char *partial_name_copy;
127 bool only_directories;
128 bool *saw_directory;
129 StringList *matches;
130 char *end_ptr;
131 size_t baselen;
Michael Sartain0b5e5f42013-08-26 17:07:34 +0000132} DiskFilesOrDirectoriesBaton;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000133
134FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
135{
136 const char *name = spec.GetFilename().AsCString();
137
138 const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
139 char *end_ptr = parameters->end_ptr;
140 char *partial_name_copy = parameters->partial_name_copy;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000141 const char *remainder = parameters->remainder;
142
143 // Omit ".", ".." and any . files if the match string doesn't start with .
144 if (name[0] == '.')
145 {
146 if (name[1] == '\0')
147 return FileSpec::eEnumerateDirectoryResultNext;
148 else if (name[1] == '.' && name[2] == '\0')
149 return FileSpec::eEnumerateDirectoryResultNext;
150 else if (remainder[0] != '.')
151 return FileSpec::eEnumerateDirectoryResultNext;
152 }
153
154 // If we found a directory, we put a "/" at the end of the name.
155
156 if (remainder[0] == '\0' || strstr(name, remainder) == name)
157 {
158 if (strlen(name) + parameters->baselen >= PATH_MAX)
159 return FileSpec::eEnumerateDirectoryResultNext;
160
161 strcpy(end_ptr, name);
162
163 bool isa_directory = false;
164 if (file_type == FileSpec::eFileTypeDirectory)
165 isa_directory = true;
166 else if (file_type == FileSpec::eFileTypeSymbolicLink)
167 {
168 struct stat stat_buf;
169 if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
170 isa_directory = true;
171 }
172
173 if (isa_directory)
174 {
175 *parameters->saw_directory = true;
176 size_t len = strlen(parameters->partial_name_copy);
177 partial_name_copy[len] = '/';
178 partial_name_copy[len + 1] = '\0';
179 }
180 if (parameters->only_directories && !isa_directory)
181 return FileSpec::eEnumerateDirectoryResultNext;
182 parameters->matches->AppendString(partial_name_copy);
183 }
184
185 return FileSpec::eEnumerateDirectoryResultNext;
186}
187
Jim Ingham558ce122010-06-30 05:02:46 +0000188static int
189DiskFilesOrDirectories
190(
191 const char *partial_file_name,
192 bool only_directories,
193 bool &saw_directory,
194 StringList &matches
195)
196{
197 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
198 // If it is not defined on your host system, you'll need to implement it yourself...
199
Greg Claytonc7bece562013-01-25 18:06:21 +0000200 size_t partial_name_len = strlen(partial_file_name);
Jim Ingham558ce122010-06-30 05:02:46 +0000201
202 if (partial_name_len >= PATH_MAX)
203 return matches.GetSize();
204
205 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
206 // below will point to the place of the remainder in this string. Then when we've resolved the
207 // containing directory, and opened it, we'll read the directory contents and overwrite the
208 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
209 // the form the user originally typed.
210
211 char partial_name_copy[PATH_MAX];
Benjamin Kramer021b6052010-06-30 13:43:47 +0000212 memcpy(partial_name_copy, partial_file_name, partial_name_len);
Jim Ingham558ce122010-06-30 05:02:46 +0000213 partial_name_copy[partial_name_len] = '\0';
214
Greg Clayton710dd5a2011-01-08 20:28:42 +0000215 // We'll need to save a copy of the remainder for comparison, which we do here.
Jim Ingham558ce122010-06-30 05:02:46 +0000216 char remainder[PATH_MAX];
217
218 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
219 char *end_ptr;
220
221 end_ptr = strrchr(partial_name_copy, '/');
222
223 // This will store the resolved form of the containing directory
224 char containing_part[PATH_MAX];
225
226 if (end_ptr == NULL)
227 {
228 // There's no directory. If the thing begins with a "~" then this is a bare
229 // user name.
230 if (*partial_name_copy == '~')
231 {
232 // Nothing here but the user name. We could just put a slash on the end,
Jim Ingham7cc478b2010-07-02 00:45:55 +0000233 // but for completeness sake we'll resolve the user name and only put a slash
Jim Ingham558ce122010-06-30 05:02:46 +0000234 // on the end if it exists.
Jim Ingham7cc478b2010-07-02 00:45:55 +0000235 char resolved_username[PATH_MAX];
Greg Claytonc982c762010-07-09 20:39:50 +0000236 size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username,
Jim Ingham7cc478b2010-07-02 00:45:55 +0000237 sizeof (resolved_username));
238
239 // Not sure how this would happen, a username longer than PATH_MAX? Still...
240 if (resolved_username_len >= sizeof (resolved_username))
241 return matches.GetSize();
Jim Ingham84363072011-02-08 23:24:09 +0000242 else if (resolved_username_len == 0)
Jim Ingham7cc478b2010-07-02 00:45:55 +0000243 {
244 // The user name didn't resolve, let's look in the password database for matches.
245 // The user name database contains duplicates, and is not in alphabetical order, so
246 // we'll use a set to manage that for us.
Jim Ingham84363072011-02-08 23:24:09 +0000247 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
248 if (matches.GetSize() > 0)
249 saw_directory = true;
Jim Ingham7cc478b2010-07-02 00:45:55 +0000250 return matches.GetSize();
Jim Ingham84363072011-02-08 23:24:09 +0000251 }
252 else
253 {
254 //The thing exists, put a '/' on the end, and return it...
255 // FIXME: complete user names here:
256 partial_name_copy[partial_name_len] = '/';
257 partial_name_copy[partial_name_len+1] = '\0';
258 matches.AppendString(partial_name_copy);
259 saw_directory = true;
260 return matches.GetSize();
261 }
Jim Ingham558ce122010-06-30 05:02:46 +0000262 }
263 else
264 {
265 // The containing part is the CWD, and the whole string is the remainder.
266 containing_part[0] = '.';
267 containing_part[1] = '\0';
268 strcpy(remainder, partial_name_copy);
269 end_ptr = partial_name_copy;
270 }
271 }
272 else
273 {
274 if (end_ptr == partial_name_copy)
275 {
276 // We're completing a file or directory in the root volume.
277 containing_part[0] = '/';
278 containing_part[1] = '\0';
279 }
280 else
281 {
282 size_t len = end_ptr - partial_name_copy;
283 memcpy(containing_part, partial_name_copy, len);
284 containing_part[len] = '\0';
285 }
286 // Push end_ptr past the final "/" and set remainder.
287 end_ptr++;
288 strcpy(remainder, end_ptr);
289 }
290
Jim Ingham7cc478b2010-07-02 00:45:55 +0000291 // 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 +0000292 // result back into the containing_part:
Greg Claytonfd184262011-02-05 02:27:52 +0000293
Jim Ingham558ce122010-06-30 05:02:46 +0000294 if (*partial_name_copy == '~')
295 {
Jim Ingham84363072011-02-08 23:24:09 +0000296 size_t resolved_username_len = FileSpec::ResolveUsername(containing_part,
297 containing_part,
298 sizeof (containing_part));
Jim Ingham558ce122010-06-30 05:02:46 +0000299 // User name doesn't exist, we're not getting any further...
Greg Claytona0807352010-07-06 16:11:44 +0000300 if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
Jim Ingham558ce122010-06-30 05:02:46 +0000301 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000302 }
Greg Claytonfd184262011-02-05 02:27:52 +0000303
Jim Ingham558ce122010-06-30 05:02:46 +0000304 // Okay, containing_part is now the directory we want to open and look for files:
Greg Clayton9b62fd22011-02-01 05:15:22 +0000305
Jim Ingham558ce122010-06-30 05:02:46 +0000306 size_t baselen = end_ptr - partial_name_copy;
307
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000308 DiskFilesOrDirectoriesBaton parameters;
309 parameters.remainder = remainder;
310 parameters.partial_name_copy = partial_name_copy;
311 parameters.only_directories = only_directories;
312 parameters.saw_directory = &saw_directory;
313 parameters.matches = &matches;
314 parameters.end_ptr = end_ptr;
315 parameters.baselen = baselen;
316
317 FileSpec::EnumerateDirectory(containing_part, true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
Jim Ingham558ce122010-06-30 05:02:46 +0000318
319 return matches.GetSize();
320}
321
322int
323CommandCompletions::DiskFiles
324(
325 CommandInterpreter &interpreter,
326 const char *partial_file_name,
327 int match_start_point,
328 int max_return_elements,
329 SearchFilter *searcher,
330 bool &word_complete,
331 StringList &matches
332)
333{
334
335 int ret_val = DiskFilesOrDirectories (partial_file_name,
336 false,
337 word_complete,
338 matches);
339 word_complete = !word_complete;
340 return ret_val;
341}
342
343int
344CommandCompletions::DiskDirectories
345(
346 CommandInterpreter &interpreter,
347 const char *partial_file_name,
348 int match_start_point,
349 int max_return_elements,
350 SearchFilter *searcher,
351 bool &word_complete,
352 StringList &matches
353)
354{
355 int ret_val = DiskFilesOrDirectories (partial_file_name,
356 true,
357 word_complete,
358 matches);
359 word_complete = false;
360 return ret_val;
361}
362
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000363int
Greg Clayton66111032010-06-23 01:19:29 +0000364CommandCompletions::Modules
365(
366 CommandInterpreter &interpreter,
367 const char *partial_file_name,
368 int match_start_point,
369 int max_return_elements,
370 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000371 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000372 StringList &matches
373)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000374{
Jim Ingham558ce122010-06-30 05:02:46 +0000375 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000376 ModuleCompleter completer (interpreter,
377 partial_file_name,
378 match_start_point,
379 max_return_elements,
380 matches);
381
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000382 if (searcher == NULL)
383 {
Jim Ingham2976d002010-08-26 21:32:51 +0000384 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385 SearchFilter null_searcher (target_sp);
386 completer.DoCompletion (&null_searcher);
387 }
388 else
389 {
390 completer.DoCompletion (searcher);
391 }
392 return matches.GetSize();
393}
394
395int
Greg Clayton66111032010-06-23 01:19:29 +0000396CommandCompletions::Symbols
397(
398 CommandInterpreter &interpreter,
399 const char *partial_file_name,
400 int match_start_point,
401 int max_return_elements,
402 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000403 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000404 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000405{
Jim Ingham558ce122010-06-30 05:02:46 +0000406 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000407 SymbolCompleter completer (interpreter,
408 partial_file_name,
409 match_start_point,
410 max_return_elements,
411 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000412
413 if (searcher == NULL)
414 {
Jim Ingham2976d002010-08-26 21:32:51 +0000415 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000416 SearchFilter null_searcher (target_sp);
417 completer.DoCompletion (&null_searcher);
418 }
419 else
420 {
421 completer.DoCompletion (searcher);
422 }
423 return matches.GetSize();
424}
425
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000426int
427CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
428 const char *partial_setting_name,
429 int match_start_point,
430 int max_return_elements,
431 SearchFilter *searcher,
432 bool &word_complete,
433 StringList &matches)
434{
Greg Clayton67cc0632012-08-22 17:17:09 +0000435 // Cache the full setting name list
436 static StringList g_property_names;
437 if (g_property_names.GetSize() == 0)
438 {
439 // Generate the full setting name list on demand
440 lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
441 if (properties_sp)
442 {
443 StreamString strm;
444 properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
445 const std::string &str = strm.GetString();
446 g_property_names.SplitIntoLines(str.c_str(), str.size());
447 }
448 }
449
450 size_t exact_matches_idx = SIZE_MAX;
451 const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
Greg Clayton67cc0632012-08-22 17:17:09 +0000452 word_complete = exact_matches_idx != SIZE_MAX;
453 return num_matches;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000454}
455
Greg Claytonab65b342011-04-13 22:47:15 +0000456
457int
458CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
459 const char *partial_name,
460 int match_start_point,
461 int max_return_elements,
462 SearchFilter *searcher,
463 bool &word_complete,
464 lldb_private::StringList &matches)
465{
466 const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
467 word_complete = num_matches == 1;
468 return num_matches;
469}
470
471int
472CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
473 const char *partial_name,
474 int match_start_point,
475 int max_return_elements,
476 SearchFilter *searcher,
477 bool &word_complete,
478 lldb_private::StringList &matches)
479{
480 const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
481 word_complete = num_matches == 1;
482 return num_matches;
483}
484
485
Greg Claytonf21fead2013-05-14 23:43:18 +0000486int
487CommandCompletions::VariablePath (CommandInterpreter &interpreter,
488 const char *partial_name,
489 int match_start_point,
490 int max_return_elements,
491 SearchFilter *searcher,
492 bool &word_complete,
493 lldb_private::StringList &matches)
494{
495 return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
496}
497
498
Greg Clayton66111032010-06-23 01:19:29 +0000499CommandCompletions::Completer::Completer
500(
501 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000502 const char *completion_str,
503 int match_start_point,
504 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000505 StringList &matches
506) :
Greg Clayton66111032010-06-23 01:19:29 +0000507 m_interpreter (interpreter),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000508 m_completion_str (completion_str),
509 m_match_start_point (match_start_point),
510 m_max_return_elements (max_return_elements),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000511 m_matches (matches)
512{
513}
514
515CommandCompletions::Completer::~Completer ()
516{
517
518}
519
520//----------------------------------------------------------------------
521// SourceFileCompleter
522//----------------------------------------------------------------------
523
Greg Clayton66111032010-06-23 01:19:29 +0000524CommandCompletions::SourceFileCompleter::SourceFileCompleter
525(
526 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000527 bool include_support_files,
528 const char *completion_str,
529 int match_start_point,
530 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000531 StringList &matches
532) :
Greg Clayton66111032010-06-23 01:19:29 +0000533 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000534 m_include_support_files (include_support_files),
535 m_matching_files()
536{
Greg Clayton274060b2010-10-20 20:54:39 +0000537 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000538 m_file_name = partial_spec.GetFilename().GetCString();
539 m_dir_name = partial_spec.GetDirectory().GetCString();
540}
541
542Searcher::Depth
543CommandCompletions::SourceFileCompleter::GetDepth()
544{
545 return eDepthCompUnit;
546}
547
548Searcher::CallbackReturn
549CommandCompletions::SourceFileCompleter::SearchCallback (
550 SearchFilter &filter,
551 SymbolContext &context,
552 Address *addr,
553 bool complete
554)
555{
556 if (context.comp_unit != NULL)
557 {
558 if (m_include_support_files)
559 {
560 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
561 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
562 {
563 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
564 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
565 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
566 bool match = false;
567 if (m_file_name && sfile_file_name
568 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
569 match = true;
570 if (match && m_dir_name && sfile_dir_name
571 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
572 match = false;
573
574 if (match)
575 {
576 m_matching_files.AppendIfUnique(sfile_spec);
577 }
578 }
579
580 }
581 else
582 {
583 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
584 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
585
586 bool match = false;
587 if (m_file_name && cur_file_name
588 && strstr (cur_file_name, m_file_name) == cur_file_name)
589 match = true;
590
591 if (match && m_dir_name && cur_dir_name
592 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
593 match = false;
594
595 if (match)
596 {
597 m_matching_files.AppendIfUnique(context.comp_unit);
598 }
599 }
600 }
601 return Searcher::eCallbackReturnContinue;
602}
603
604size_t
605CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
606{
607 filter->Search (*this);
608 // Now convert the filelist to completions:
609 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
610 {
611 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
612 }
613 return m_matches.GetSize();
614
615}
616
617//----------------------------------------------------------------------
618// SymbolCompleter
619//----------------------------------------------------------------------
620
621static bool
622regex_chars (const char comp)
623{
Greg Clayton649f8b92013-06-07 00:35:40 +0000624 if (comp == '[' || comp == ']' ||
625 comp == '(' || comp == ')' ||
626 comp == '{' || comp == '}' ||
627 comp == '+' ||
628 comp == '.' ||
629 comp == '*' ||
630 comp == '|' ||
631 comp == '^' ||
632 comp == '$' ||
633 comp == '\\' ||
634 comp == '?')
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000635 return true;
636 else
637 return false;
638}
Greg Clayton66111032010-06-23 01:19:29 +0000639CommandCompletions::SymbolCompleter::SymbolCompleter
640(
641 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000642 const char *completion_str,
643 int match_start_point,
644 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000645 StringList &matches
646) :
Greg Clayton66111032010-06-23 01:19:29 +0000647 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000648{
Greg Clayton649f8b92013-06-07 00:35:40 +0000649 std::string regex_str;
650 if (completion_str && completion_str[0])
651 {
652 regex_str.append("^");
653 regex_str.append(completion_str);
654 }
655 else
656 {
657 // Match anything since the completion string is empty
658 regex_str.append(".");
659 }
660 std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
661 while (pos < regex_str.end())
662 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000663 pos = regex_str.insert(pos, '\\');
Greg Clayton649f8b92013-06-07 00:35:40 +0000664 pos = find_if(pos + 2, regex_str.end(), regex_chars);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000665 }
666 m_regex.Compile(regex_str.c_str());
667}
668
669Searcher::Depth
670CommandCompletions::SymbolCompleter::GetDepth()
671{
672 return eDepthModule;
673}
674
675Searcher::CallbackReturn
676CommandCompletions::SymbolCompleter::SearchCallback (
677 SearchFilter &filter,
678 SymbolContext &context,
679 Address *addr,
680 bool complete
681)
682{
Greg Clayton931180e2011-01-27 06:44:37 +0000683 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000684 {
Greg Clayton931180e2011-01-27 06:44:37 +0000685 SymbolContextList sc_list;
686 const bool include_symbols = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000687 const bool include_inlines = true;
Greg Clayton931180e2011-01-27 06:44:37 +0000688 const bool append = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000689 context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000690
691 SymbolContext sc;
692 // Now add the functions & symbols to the list - only add if unique:
Greg Clayton931180e2011-01-27 06:44:37 +0000693 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000694 {
Greg Clayton931180e2011-01-27 06:44:37 +0000695 if (sc_list.GetContextAtIndex(i, sc))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000696 {
Jim Ingham530a4132011-09-27 19:48:20 +0000697 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
698 if (!func_name.IsEmpty())
699 m_match_set.insert (func_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000700 }
701 }
702 }
703 return Searcher::eCallbackReturnContinue;
704}
705
706size_t
707CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
708{
709 filter->Search (*this);
710 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
711 for (pos = m_match_set.begin(); pos != end; pos++)
712 m_matches.AppendString((*pos).GetCString());
713
714 return m_matches.GetSize();
715}
716
717//----------------------------------------------------------------------
718// ModuleCompleter
719//----------------------------------------------------------------------
Greg Clayton66111032010-06-23 01:19:29 +0000720CommandCompletions::ModuleCompleter::ModuleCompleter
721(
722 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000723 const char *completion_str,
724 int match_start_point,
725 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000726 StringList &matches
727) :
Greg Clayton66111032010-06-23 01:19:29 +0000728 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000729{
Greg Clayton274060b2010-10-20 20:54:39 +0000730 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000731 m_file_name = partial_spec.GetFilename().GetCString();
732 m_dir_name = partial_spec.GetDirectory().GetCString();
733}
734
735Searcher::Depth
736CommandCompletions::ModuleCompleter::GetDepth()
737{
738 return eDepthModule;
739}
740
741Searcher::CallbackReturn
742CommandCompletions::ModuleCompleter::SearchCallback (
743 SearchFilter &filter,
744 SymbolContext &context,
745 Address *addr,
746 bool complete
747)
748{
Greg Clayton747bcb02011-09-17 06:21:20 +0000749 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000750 {
751 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
752 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
753
754 bool match = false;
755 if (m_file_name && cur_file_name
756 && strstr (cur_file_name, m_file_name) == cur_file_name)
757 match = true;
758
759 if (match && m_dir_name && cur_dir_name
760 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
761 match = false;
762
763 if (match)
764 {
765 m_matches.AppendString (cur_file_name);
766 }
767 }
768 return Searcher::eCallbackReturnContinue;
769}
770
771size_t
772CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
773{
774 filter->Search (*this);
775 return m_matches.GetSize();
776}