blob: 37696e3bbfdb56a80048b372cc5b1f7f7a043a25 [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
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
Jim Ingham558ce122010-06-30 05:02:46 +000011#include <sys/stat.h>
Greg Claytonfd184262011-02-05 02:27:52 +000012#if defined(__APPLE__) || defined(__linux__)
Jim Ingham7cc478b2010-07-02 00:45:55 +000013#include <pwd.h>
Greg Claytonfd184262011-02-05 02:27:52 +000014#endif
Jim Ingham558ce122010-06-30 05:02:46 +000015
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016// C++ Includes
17// Other libraries and framework includes
18// Project includes
Greg Clayton53239f02011-02-08 05:05:52 +000019#include "lldb/Host/FileSpec.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000020#include "lldb/Core/FileSpecList.h"
Greg Claytonab65b342011-04-13 22:47:15 +000021#include "lldb/Core/PluginManager.h"
Greg Clayton1f746072012-08-29 21:13:06 +000022#include "lldb/Core/Module.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000023#include "lldb/Interpreter/Args.h"
24#include "lldb/Interpreter/CommandCompletions.h"
25#include "lldb/Interpreter/CommandInterpreter.h"
Zachary Turner633a29c2015-03-04 01:58:01 +000026#include "lldb/Interpreter/OptionValueProperties.h"
Greg Clayton1f746072012-08-29 21:13:06 +000027#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000028#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000029#include "lldb/Target/Target.h"
30#include "lldb/Utility/CleanUp.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031
Zachary Turner3f559742014-08-07 17:33:36 +000032#include "llvm/ADT/SmallString.h"
33
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034using 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();
Jim Ingham33df7cd2014-12-06 01:28:03 +0000114 SearchFilterForUnconstrainedSearches null_searcher (target_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115 completer.DoCompletion (&null_searcher);
116 }
117 else
118 {
119 completer.DoCompletion (searcher);
120 }
121 return matches.GetSize();
122}
123
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000124typedef struct DiskFilesOrDirectoriesBaton
125{
126 const char *remainder;
127 char *partial_name_copy;
128 bool only_directories;
129 bool *saw_directory;
130 StringList *matches;
131 char *end_ptr;
132 size_t baselen;
Michael Sartain0b5e5f42013-08-26 17:07:34 +0000133} DiskFilesOrDirectoriesBaton;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000134
135FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
136{
137 const char *name = spec.GetFilename().AsCString();
138
139 const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
140 char *end_ptr = parameters->end_ptr;
141 char *partial_name_copy = parameters->partial_name_copy;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000142 const char *remainder = parameters->remainder;
143
144 // Omit ".", ".." and any . files if the match string doesn't start with .
145 if (name[0] == '.')
146 {
147 if (name[1] == '\0')
148 return FileSpec::eEnumerateDirectoryResultNext;
149 else if (name[1] == '.' && name[2] == '\0')
150 return FileSpec::eEnumerateDirectoryResultNext;
151 else if (remainder[0] != '.')
152 return FileSpec::eEnumerateDirectoryResultNext;
153 }
154
155 // If we found a directory, we put a "/" at the end of the name.
156
157 if (remainder[0] == '\0' || strstr(name, remainder) == name)
158 {
159 if (strlen(name) + parameters->baselen >= PATH_MAX)
160 return FileSpec::eEnumerateDirectoryResultNext;
161
162 strcpy(end_ptr, name);
163
164 bool isa_directory = false;
165 if (file_type == FileSpec::eFileTypeDirectory)
166 isa_directory = true;
167 else if (file_type == FileSpec::eFileTypeSymbolicLink)
168 {
169 struct stat stat_buf;
170 if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
171 isa_directory = true;
172 }
173
174 if (isa_directory)
175 {
176 *parameters->saw_directory = true;
177 size_t len = strlen(parameters->partial_name_copy);
178 partial_name_copy[len] = '/';
179 partial_name_copy[len + 1] = '\0';
180 }
181 if (parameters->only_directories && !isa_directory)
182 return FileSpec::eEnumerateDirectoryResultNext;
183 parameters->matches->AppendString(partial_name_copy);
184 }
185
186 return FileSpec::eEnumerateDirectoryResultNext;
187}
188
Jim Ingham558ce122010-06-30 05:02:46 +0000189static int
190DiskFilesOrDirectories
191(
192 const char *partial_file_name,
193 bool only_directories,
194 bool &saw_directory,
195 StringList &matches
196)
197{
198 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
199 // If it is not defined on your host system, you'll need to implement it yourself...
200
Greg Claytonc7bece562013-01-25 18:06:21 +0000201 size_t partial_name_len = strlen(partial_file_name);
Jim Ingham558ce122010-06-30 05:02:46 +0000202
203 if (partial_name_len >= PATH_MAX)
204 return matches.GetSize();
205
206 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
207 // below will point to the place of the remainder in this string. Then when we've resolved the
208 // containing directory, and opened it, we'll read the directory contents and overwrite the
209 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
210 // the form the user originally typed.
211
212 char partial_name_copy[PATH_MAX];
Benjamin Kramer021b6052010-06-30 13:43:47 +0000213 memcpy(partial_name_copy, partial_file_name, partial_name_len);
Jim Ingham558ce122010-06-30 05:02:46 +0000214 partial_name_copy[partial_name_len] = '\0';
215
Greg Clayton710dd5a2011-01-08 20:28:42 +0000216 // We'll need to save a copy of the remainder for comparison, which we do here.
Jim Ingham558ce122010-06-30 05:02:46 +0000217 char remainder[PATH_MAX];
218
219 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
220 char *end_ptr;
221
222 end_ptr = strrchr(partial_name_copy, '/');
223
224 // This will store the resolved form of the containing directory
Zachary Turner3f559742014-08-07 17:33:36 +0000225 llvm::SmallString<64> containing_part;
Jim Ingham558ce122010-06-30 05:02:46 +0000226
227 if (end_ptr == NULL)
228 {
229 // There's no directory. If the thing begins with a "~" then this is a bare
230 // user name.
231 if (*partial_name_copy == '~')
232 {
233 // Nothing here but the user name. We could just put a slash on the end,
Jim Ingham7cc478b2010-07-02 00:45:55 +0000234 // but for completeness sake we'll resolve the user name and only put a slash
Jim Ingham558ce122010-06-30 05:02:46 +0000235 // on the end if it exists.
Zachary Turner3f559742014-08-07 17:33:36 +0000236 llvm::SmallString<64> resolved_username(partial_name_copy);
237 FileSpec::ResolveUsername (resolved_username);
Jim Ingham7cc478b2010-07-02 00:45:55 +0000238
239 // Not sure how this would happen, a username longer than PATH_MAX? Still...
Zachary Turner3f559742014-08-07 17:33:36 +0000240 if (resolved_username.size() == 0)
Jim Ingham7cc478b2010-07-02 00:45:55 +0000241 {
242 // The user name didn't resolve, let's look in the password database for matches.
243 // The user name database contains duplicates, and is not in alphabetical order, so
244 // we'll use a set to manage that for us.
Jim Ingham84363072011-02-08 23:24:09 +0000245 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
246 if (matches.GetSize() > 0)
247 saw_directory = true;
Jim Ingham7cc478b2010-07-02 00:45:55 +0000248 return matches.GetSize();
Jim Ingham84363072011-02-08 23:24:09 +0000249 }
250 else
251 {
252 //The thing exists, put a '/' on the end, and return it...
253 // FIXME: complete user names here:
254 partial_name_copy[partial_name_len] = '/';
255 partial_name_copy[partial_name_len+1] = '\0';
256 matches.AppendString(partial_name_copy);
257 saw_directory = true;
258 return matches.GetSize();
259 }
Jim Ingham558ce122010-06-30 05:02:46 +0000260 }
261 else
262 {
263 // The containing part is the CWD, and the whole string is the remainder.
Zachary Turner3f559742014-08-07 17:33:36 +0000264 containing_part = ".";
Jim Ingham558ce122010-06-30 05:02:46 +0000265 strcpy(remainder, partial_name_copy);
266 end_ptr = partial_name_copy;
267 }
268 }
269 else
270 {
271 if (end_ptr == partial_name_copy)
272 {
273 // We're completing a file or directory in the root volume.
Zachary Turner3f559742014-08-07 17:33:36 +0000274 containing_part = "/";
Jim Ingham558ce122010-06-30 05:02:46 +0000275 }
276 else
277 {
Zachary Turner3f559742014-08-07 17:33:36 +0000278 containing_part.append(partial_name_copy, end_ptr);
Jim Ingham558ce122010-06-30 05:02:46 +0000279 }
280 // Push end_ptr past the final "/" and set remainder.
281 end_ptr++;
282 strcpy(remainder, end_ptr);
283 }
284
Jim Ingham7cc478b2010-07-02 00:45:55 +0000285 // 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 +0000286 // result back into the containing_part:
Greg Claytonfd184262011-02-05 02:27:52 +0000287
Jim Ingham558ce122010-06-30 05:02:46 +0000288 if (*partial_name_copy == '~')
289 {
Zachary Turner3f559742014-08-07 17:33:36 +0000290 FileSpec::ResolveUsername(containing_part);
Jim Ingham558ce122010-06-30 05:02:46 +0000291 // User name doesn't exist, we're not getting any further...
Zachary Turner3f559742014-08-07 17:33:36 +0000292 if (containing_part.empty())
Jim Ingham558ce122010-06-30 05:02:46 +0000293 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000294 }
Greg Claytonfd184262011-02-05 02:27:52 +0000295
Jim Ingham558ce122010-06-30 05:02:46 +0000296 // Okay, containing_part is now the directory we want to open and look for files:
Greg Clayton9b62fd22011-02-01 05:15:22 +0000297
Jim Ingham558ce122010-06-30 05:02:46 +0000298 size_t baselen = end_ptr - partial_name_copy;
299
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000300 DiskFilesOrDirectoriesBaton parameters;
301 parameters.remainder = remainder;
302 parameters.partial_name_copy = partial_name_copy;
303 parameters.only_directories = only_directories;
304 parameters.saw_directory = &saw_directory;
305 parameters.matches = &matches;
306 parameters.end_ptr = end_ptr;
307 parameters.baselen = baselen;
308
Zachary Turner3f559742014-08-07 17:33:36 +0000309 FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
Jim Ingham558ce122010-06-30 05:02:46 +0000310
311 return matches.GetSize();
312}
313
314int
315CommandCompletions::DiskFiles
316(
317 CommandInterpreter &interpreter,
318 const char *partial_file_name,
319 int match_start_point,
320 int max_return_elements,
321 SearchFilter *searcher,
322 bool &word_complete,
323 StringList &matches
324)
325{
326
327 int ret_val = DiskFilesOrDirectories (partial_file_name,
328 false,
329 word_complete,
330 matches);
331 word_complete = !word_complete;
332 return ret_val;
333}
334
335int
336CommandCompletions::DiskDirectories
337(
338 CommandInterpreter &interpreter,
339 const char *partial_file_name,
340 int match_start_point,
341 int max_return_elements,
342 SearchFilter *searcher,
343 bool &word_complete,
344 StringList &matches
345)
346{
347 int ret_val = DiskFilesOrDirectories (partial_file_name,
348 true,
349 word_complete,
350 matches);
351 word_complete = false;
352 return ret_val;
353}
354
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000355int
Greg Clayton66111032010-06-23 01:19:29 +0000356CommandCompletions::Modules
357(
358 CommandInterpreter &interpreter,
359 const char *partial_file_name,
360 int match_start_point,
361 int max_return_elements,
362 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000363 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000364 StringList &matches
365)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000366{
Jim Ingham558ce122010-06-30 05:02:46 +0000367 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000368 ModuleCompleter completer (interpreter,
369 partial_file_name,
370 match_start_point,
371 max_return_elements,
372 matches);
373
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000374 if (searcher == NULL)
375 {
Jim Ingham2976d002010-08-26 21:32:51 +0000376 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Jim Ingham33df7cd2014-12-06 01:28:03 +0000377 SearchFilterForUnconstrainedSearches null_searcher (target_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000378 completer.DoCompletion (&null_searcher);
379 }
380 else
381 {
382 completer.DoCompletion (searcher);
383 }
384 return matches.GetSize();
385}
386
387int
Greg Clayton66111032010-06-23 01:19:29 +0000388CommandCompletions::Symbols
389(
390 CommandInterpreter &interpreter,
391 const char *partial_file_name,
392 int match_start_point,
393 int max_return_elements,
394 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000395 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000396 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397{
Jim Ingham558ce122010-06-30 05:02:46 +0000398 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000399 SymbolCompleter completer (interpreter,
400 partial_file_name,
401 match_start_point,
402 max_return_elements,
403 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000404
405 if (searcher == NULL)
406 {
Jim Ingham2976d002010-08-26 21:32:51 +0000407 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Jim Ingham33df7cd2014-12-06 01:28:03 +0000408 SearchFilterForUnconstrainedSearches null_searcher (target_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409 completer.DoCompletion (&null_searcher);
410 }
411 else
412 {
413 completer.DoCompletion (searcher);
414 }
415 return matches.GetSize();
416}
417
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000418int
419CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
420 const char *partial_setting_name,
421 int match_start_point,
422 int max_return_elements,
423 SearchFilter *searcher,
424 bool &word_complete,
425 StringList &matches)
426{
Greg Clayton67cc0632012-08-22 17:17:09 +0000427 // Cache the full setting name list
428 static StringList g_property_names;
429 if (g_property_names.GetSize() == 0)
430 {
431 // Generate the full setting name list on demand
432 lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
433 if (properties_sp)
434 {
435 StreamString strm;
436 properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
437 const std::string &str = strm.GetString();
438 g_property_names.SplitIntoLines(str.c_str(), str.size());
439 }
440 }
441
442 size_t exact_matches_idx = SIZE_MAX;
443 const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
Greg Clayton67cc0632012-08-22 17:17:09 +0000444 word_complete = exact_matches_idx != SIZE_MAX;
445 return num_matches;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000446}
447
Greg Claytonab65b342011-04-13 22:47:15 +0000448
449int
450CommandCompletions::PlatformPluginNames (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 = PluginManager::AutoCompletePlatformName(partial_name, matches);
459 word_complete = num_matches == 1;
460 return num_matches;
461}
462
463int
464CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
465 const char *partial_name,
466 int match_start_point,
467 int max_return_elements,
468 SearchFilter *searcher,
469 bool &word_complete,
470 lldb_private::StringList &matches)
471{
472 const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
473 word_complete = num_matches == 1;
474 return num_matches;
475}
476
477
Greg Claytonf21fead2013-05-14 23:43:18 +0000478int
479CommandCompletions::VariablePath (CommandInterpreter &interpreter,
480 const char *partial_name,
481 int match_start_point,
482 int max_return_elements,
483 SearchFilter *searcher,
484 bool &word_complete,
485 lldb_private::StringList &matches)
486{
487 return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
488}
489
490
Greg Clayton66111032010-06-23 01:19:29 +0000491CommandCompletions::Completer::Completer
492(
493 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000494 const char *completion_str,
495 int match_start_point,
496 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000497 StringList &matches
498) :
Greg Clayton66111032010-06-23 01:19:29 +0000499 m_interpreter (interpreter),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000500 m_completion_str (completion_str),
501 m_match_start_point (match_start_point),
502 m_max_return_elements (max_return_elements),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000503 m_matches (matches)
504{
505}
506
507CommandCompletions::Completer::~Completer ()
508{
509
510}
511
512//----------------------------------------------------------------------
513// SourceFileCompleter
514//----------------------------------------------------------------------
515
Greg Clayton66111032010-06-23 01:19:29 +0000516CommandCompletions::SourceFileCompleter::SourceFileCompleter
517(
518 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000519 bool include_support_files,
520 const char *completion_str,
521 int match_start_point,
522 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000523 StringList &matches
524) :
Greg Clayton66111032010-06-23 01:19:29 +0000525 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000526 m_include_support_files (include_support_files),
527 m_matching_files()
528{
Greg Clayton274060b2010-10-20 20:54:39 +0000529 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000530 m_file_name = partial_spec.GetFilename().GetCString();
531 m_dir_name = partial_spec.GetDirectory().GetCString();
532}
533
534Searcher::Depth
535CommandCompletions::SourceFileCompleter::GetDepth()
536{
537 return eDepthCompUnit;
538}
539
540Searcher::CallbackReturn
541CommandCompletions::SourceFileCompleter::SearchCallback (
542 SearchFilter &filter,
543 SymbolContext &context,
544 Address *addr,
545 bool complete
546)
547{
548 if (context.comp_unit != NULL)
549 {
550 if (m_include_support_files)
551 {
552 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
553 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
554 {
555 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
556 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
557 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
558 bool match = false;
559 if (m_file_name && sfile_file_name
560 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
561 match = true;
562 if (match && m_dir_name && sfile_dir_name
563 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
564 match = false;
565
566 if (match)
567 {
568 m_matching_files.AppendIfUnique(sfile_spec);
569 }
570 }
571
572 }
573 else
574 {
575 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
576 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
577
578 bool match = false;
579 if (m_file_name && cur_file_name
580 && strstr (cur_file_name, m_file_name) == cur_file_name)
581 match = true;
582
583 if (match && m_dir_name && cur_dir_name
584 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
585 match = false;
586
587 if (match)
588 {
589 m_matching_files.AppendIfUnique(context.comp_unit);
590 }
591 }
592 }
593 return Searcher::eCallbackReturnContinue;
594}
595
596size_t
597CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
598{
599 filter->Search (*this);
600 // Now convert the filelist to completions:
601 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
602 {
603 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
604 }
605 return m_matches.GetSize();
606
607}
608
609//----------------------------------------------------------------------
610// SymbolCompleter
611//----------------------------------------------------------------------
612
613static bool
614regex_chars (const char comp)
615{
Greg Clayton649f8b92013-06-07 00:35:40 +0000616 if (comp == '[' || comp == ']' ||
617 comp == '(' || comp == ')' ||
618 comp == '{' || comp == '}' ||
619 comp == '+' ||
620 comp == '.' ||
621 comp == '*' ||
622 comp == '|' ||
623 comp == '^' ||
624 comp == '$' ||
625 comp == '\\' ||
626 comp == '?')
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000627 return true;
628 else
629 return false;
630}
Greg Clayton66111032010-06-23 01:19:29 +0000631CommandCompletions::SymbolCompleter::SymbolCompleter
632(
633 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000634 const char *completion_str,
635 int match_start_point,
636 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000637 StringList &matches
638) :
Greg Clayton66111032010-06-23 01:19:29 +0000639 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000640{
Greg Clayton649f8b92013-06-07 00:35:40 +0000641 std::string regex_str;
642 if (completion_str && completion_str[0])
643 {
644 regex_str.append("^");
645 regex_str.append(completion_str);
646 }
647 else
648 {
649 // Match anything since the completion string is empty
650 regex_str.append(".");
651 }
652 std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
653 while (pos < regex_str.end())
654 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000655 pos = regex_str.insert(pos, '\\');
Greg Clayton649f8b92013-06-07 00:35:40 +0000656 pos = find_if(pos + 2, regex_str.end(), regex_chars);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000657 }
658 m_regex.Compile(regex_str.c_str());
659}
660
661Searcher::Depth
662CommandCompletions::SymbolCompleter::GetDepth()
663{
664 return eDepthModule;
665}
666
667Searcher::CallbackReturn
668CommandCompletions::SymbolCompleter::SearchCallback (
669 SearchFilter &filter,
670 SymbolContext &context,
671 Address *addr,
672 bool complete
673)
674{
Greg Clayton931180e2011-01-27 06:44:37 +0000675 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000676 {
Greg Clayton931180e2011-01-27 06:44:37 +0000677 SymbolContextList sc_list;
678 const bool include_symbols = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000679 const bool include_inlines = true;
Greg Clayton931180e2011-01-27 06:44:37 +0000680 const bool append = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000681 context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000682
683 SymbolContext sc;
684 // Now add the functions & symbols to the list - only add if unique:
Greg Clayton931180e2011-01-27 06:44:37 +0000685 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000686 {
Greg Clayton931180e2011-01-27 06:44:37 +0000687 if (sc_list.GetContextAtIndex(i, sc))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000688 {
Jim Ingham530a4132011-09-27 19:48:20 +0000689 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
690 if (!func_name.IsEmpty())
691 m_match_set.insert (func_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000692 }
693 }
694 }
695 return Searcher::eCallbackReturnContinue;
696}
697
698size_t
699CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
700{
701 filter->Search (*this);
702 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
703 for (pos = m_match_set.begin(); pos != end; pos++)
704 m_matches.AppendString((*pos).GetCString());
705
706 return m_matches.GetSize();
707}
708
709//----------------------------------------------------------------------
710// ModuleCompleter
711//----------------------------------------------------------------------
Greg Clayton66111032010-06-23 01:19:29 +0000712CommandCompletions::ModuleCompleter::ModuleCompleter
713(
714 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000715 const char *completion_str,
716 int match_start_point,
717 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000718 StringList &matches
719) :
Greg Clayton66111032010-06-23 01:19:29 +0000720 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000721{
Greg Clayton274060b2010-10-20 20:54:39 +0000722 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000723 m_file_name = partial_spec.GetFilename().GetCString();
724 m_dir_name = partial_spec.GetDirectory().GetCString();
725}
726
727Searcher::Depth
728CommandCompletions::ModuleCompleter::GetDepth()
729{
730 return eDepthModule;
731}
732
733Searcher::CallbackReturn
734CommandCompletions::ModuleCompleter::SearchCallback (
735 SearchFilter &filter,
736 SymbolContext &context,
737 Address *addr,
738 bool complete
739)
740{
Greg Clayton747bcb02011-09-17 06:21:20 +0000741 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000742 {
743 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
744 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
745
746 bool match = false;
747 if (m_file_name && cur_file_name
748 && strstr (cur_file_name, m_file_name) == cur_file_name)
749 match = true;
750
751 if (match && m_dir_name && cur_dir_name
752 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
753 match = false;
754
755 if (match)
756 {
757 m_matches.AppendString (cur_file_name);
758 }
759 }
760 return Searcher::eCallbackReturnContinue;
761}
762
763size_t
764CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
765{
766 filter->Search (*this);
767 return m_matches.GetSize();
768}