blob: 6a9d45acac89229b64ba888abe13dd62f2b4cc0c [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"
Zachary Turner633a29c2015-03-04 01:58:01 +000028#include "lldb/Interpreter/OptionValueProperties.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
Zachary Turner3f559742014-08-07 17:33:36 +000034#include "llvm/ADT/SmallString.h"
35
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036using namespace lldb_private;
37
38CommandCompletions::CommonCompletionElement
39CommandCompletions::g_common_completions[] =
40{
Jim Ingham558ce122010-06-30 05:02:46 +000041 {eCustomCompletion, NULL},
42 {eSourceFileCompletion, CommandCompletions::SourceFiles},
43 {eDiskFileCompletion, CommandCompletions::DiskFiles},
44 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
45 {eSymbolCompletion, CommandCompletions::Symbols},
46 {eModuleCompletion, CommandCompletions::Modules},
Caroline Tice3df9a8d2010-09-04 00:03:46 +000047 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
Greg Claytonab65b342011-04-13 22:47:15 +000048 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
49 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
Greg Claytonf21fead2013-05-14 23:43:18 +000050 {eVariablePathCompletion, CommandCompletions::VariablePath},
Jim Ingham558ce122010-06-30 05:02:46 +000051 {eNoCompletion, NULL} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052};
53
54bool
Greg Clayton66111032010-06-23 01:19:29 +000055CommandCompletions::InvokeCommonCompletionCallbacks
56(
57 CommandInterpreter &interpreter,
58 uint32_t completion_mask,
59 const char *completion_str,
60 int match_start_point,
61 int max_return_elements,
62 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000063 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +000064 StringList &matches
65)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000066{
67 bool handled = false;
68
69 if (completion_mask & eCustomCompletion)
70 return false;
71
72 for (int i = 0; ; i++)
73 {
74 if (g_common_completions[i].type == eNoCompletion)
75 break;
76 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
77 && g_common_completions[i].callback != NULL)
78 {
79 handled = true;
Greg Clayton66111032010-06-23 01:19:29 +000080 g_common_completions[i].callback (interpreter,
81 completion_str,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082 match_start_point,
83 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084 searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000085 word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000086 matches);
87 }
88 }
89 return handled;
90}
91
92int
Greg Clayton66111032010-06-23 01:19:29 +000093CommandCompletions::SourceFiles
94(
95 CommandInterpreter &interpreter,
96 const char *partial_file_name,
97 int match_start_point,
98 int max_return_elements,
99 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000100 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000101 StringList &matches
102)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000103{
Jim Ingham558ce122010-06-30 05:02:46 +0000104 word_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000105 // Find some way to switch "include support files..."
Greg Clayton66111032010-06-23 01:19:29 +0000106 SourceFileCompleter completer (interpreter,
107 false,
108 partial_file_name,
109 match_start_point,
110 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111 matches);
112
113 if (searcher == NULL)
114 {
Jim Ingham2976d002010-08-26 21:32:51 +0000115 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Jim Ingham33df7cd2014-12-06 01:28:03 +0000116 SearchFilterForUnconstrainedSearches null_searcher (target_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 completer.DoCompletion (&null_searcher);
118 }
119 else
120 {
121 completer.DoCompletion (searcher);
122 }
123 return matches.GetSize();
124}
125
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000126typedef struct DiskFilesOrDirectoriesBaton
127{
128 const char *remainder;
129 char *partial_name_copy;
130 bool only_directories;
131 bool *saw_directory;
132 StringList *matches;
133 char *end_ptr;
134 size_t baselen;
Michael Sartain0b5e5f42013-08-26 17:07:34 +0000135} DiskFilesOrDirectoriesBaton;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000136
137FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
138{
139 const char *name = spec.GetFilename().AsCString();
140
141 const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
142 char *end_ptr = parameters->end_ptr;
143 char *partial_name_copy = parameters->partial_name_copy;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000144 const char *remainder = parameters->remainder;
145
146 // Omit ".", ".." and any . files if the match string doesn't start with .
147 if (name[0] == '.')
148 {
149 if (name[1] == '\0')
150 return FileSpec::eEnumerateDirectoryResultNext;
151 else if (name[1] == '.' && name[2] == '\0')
152 return FileSpec::eEnumerateDirectoryResultNext;
153 else if (remainder[0] != '.')
154 return FileSpec::eEnumerateDirectoryResultNext;
155 }
156
157 // If we found a directory, we put a "/" at the end of the name.
158
159 if (remainder[0] == '\0' || strstr(name, remainder) == name)
160 {
161 if (strlen(name) + parameters->baselen >= PATH_MAX)
162 return FileSpec::eEnumerateDirectoryResultNext;
163
164 strcpy(end_ptr, name);
165
166 bool isa_directory = false;
167 if (file_type == FileSpec::eFileTypeDirectory)
168 isa_directory = true;
169 else if (file_type == FileSpec::eFileTypeSymbolicLink)
170 {
171 struct stat stat_buf;
172 if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
173 isa_directory = true;
174 }
175
176 if (isa_directory)
177 {
178 *parameters->saw_directory = true;
179 size_t len = strlen(parameters->partial_name_copy);
180 partial_name_copy[len] = '/';
181 partial_name_copy[len + 1] = '\0';
182 }
183 if (parameters->only_directories && !isa_directory)
184 return FileSpec::eEnumerateDirectoryResultNext;
185 parameters->matches->AppendString(partial_name_copy);
186 }
187
188 return FileSpec::eEnumerateDirectoryResultNext;
189}
190
Jim Ingham558ce122010-06-30 05:02:46 +0000191static int
192DiskFilesOrDirectories
193(
194 const char *partial_file_name,
195 bool only_directories,
196 bool &saw_directory,
197 StringList &matches
198)
199{
200 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
201 // If it is not defined on your host system, you'll need to implement it yourself...
202
Greg Claytonc7bece562013-01-25 18:06:21 +0000203 size_t partial_name_len = strlen(partial_file_name);
Jim Ingham558ce122010-06-30 05:02:46 +0000204
205 if (partial_name_len >= PATH_MAX)
206 return matches.GetSize();
207
208 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
209 // below will point to the place of the remainder in this string. Then when we've resolved the
210 // containing directory, and opened it, we'll read the directory contents and overwrite the
211 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
212 // the form the user originally typed.
213
214 char partial_name_copy[PATH_MAX];
Benjamin Kramer021b6052010-06-30 13:43:47 +0000215 memcpy(partial_name_copy, partial_file_name, partial_name_len);
Jim Ingham558ce122010-06-30 05:02:46 +0000216 partial_name_copy[partial_name_len] = '\0';
217
Greg Clayton710dd5a2011-01-08 20:28:42 +0000218 // We'll need to save a copy of the remainder for comparison, which we do here.
Jim Ingham558ce122010-06-30 05:02:46 +0000219 char remainder[PATH_MAX];
220
221 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
222 char *end_ptr;
223
224 end_ptr = strrchr(partial_name_copy, '/');
225
226 // This will store the resolved form of the containing directory
Zachary Turner3f559742014-08-07 17:33:36 +0000227 llvm::SmallString<64> containing_part;
Jim Ingham558ce122010-06-30 05:02:46 +0000228
229 if (end_ptr == NULL)
230 {
231 // There's no directory. If the thing begins with a "~" then this is a bare
232 // user name.
233 if (*partial_name_copy == '~')
234 {
235 // Nothing here but the user name. We could just put a slash on the end,
Jim Ingham7cc478b2010-07-02 00:45:55 +0000236 // but for completeness sake we'll resolve the user name and only put a slash
Jim Ingham558ce122010-06-30 05:02:46 +0000237 // on the end if it exists.
Zachary Turner3f559742014-08-07 17:33:36 +0000238 llvm::SmallString<64> resolved_username(partial_name_copy);
239 FileSpec::ResolveUsername (resolved_username);
Jim Ingham7cc478b2010-07-02 00:45:55 +0000240
241 // Not sure how this would happen, a username longer than PATH_MAX? Still...
Zachary Turner3f559742014-08-07 17:33:36 +0000242 if (resolved_username.size() == 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.
Zachary Turner3f559742014-08-07 17:33:36 +0000266 containing_part = ".";
Jim Ingham558ce122010-06-30 05:02:46 +0000267 strcpy(remainder, partial_name_copy);
268 end_ptr = partial_name_copy;
269 }
270 }
271 else
272 {
273 if (end_ptr == partial_name_copy)
274 {
275 // We're completing a file or directory in the root volume.
Zachary Turner3f559742014-08-07 17:33:36 +0000276 containing_part = "/";
Jim Ingham558ce122010-06-30 05:02:46 +0000277 }
278 else
279 {
Zachary Turner3f559742014-08-07 17:33:36 +0000280 containing_part.append(partial_name_copy, end_ptr);
Jim Ingham558ce122010-06-30 05:02:46 +0000281 }
282 // Push end_ptr past the final "/" and set remainder.
283 end_ptr++;
284 strcpy(remainder, end_ptr);
285 }
286
Jim Ingham7cc478b2010-07-02 00:45:55 +0000287 // 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 +0000288 // result back into the containing_part:
Greg Claytonfd184262011-02-05 02:27:52 +0000289
Jim Ingham558ce122010-06-30 05:02:46 +0000290 if (*partial_name_copy == '~')
291 {
Zachary Turner3f559742014-08-07 17:33:36 +0000292 FileSpec::ResolveUsername(containing_part);
Jim Ingham558ce122010-06-30 05:02:46 +0000293 // User name doesn't exist, we're not getting any further...
Zachary Turner3f559742014-08-07 17:33:36 +0000294 if (containing_part.empty())
Jim Ingham558ce122010-06-30 05:02:46 +0000295 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000296 }
Greg Claytonfd184262011-02-05 02:27:52 +0000297
Jim Ingham558ce122010-06-30 05:02:46 +0000298 // Okay, containing_part is now the directory we want to open and look for files:
Greg Clayton9b62fd22011-02-01 05:15:22 +0000299
Jim Ingham558ce122010-06-30 05:02:46 +0000300 size_t baselen = end_ptr - partial_name_copy;
301
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000302 DiskFilesOrDirectoriesBaton parameters;
303 parameters.remainder = remainder;
304 parameters.partial_name_copy = partial_name_copy;
305 parameters.only_directories = only_directories;
306 parameters.saw_directory = &saw_directory;
307 parameters.matches = &matches;
308 parameters.end_ptr = end_ptr;
309 parameters.baselen = baselen;
310
Zachary Turner3f559742014-08-07 17:33:36 +0000311 FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
Jim Ingham558ce122010-06-30 05:02:46 +0000312
313 return matches.GetSize();
314}
315
316int
317CommandCompletions::DiskFiles
318(
319 CommandInterpreter &interpreter,
320 const char *partial_file_name,
321 int match_start_point,
322 int max_return_elements,
323 SearchFilter *searcher,
324 bool &word_complete,
325 StringList &matches
326)
327{
328
329 int ret_val = DiskFilesOrDirectories (partial_file_name,
330 false,
331 word_complete,
332 matches);
333 word_complete = !word_complete;
334 return ret_val;
335}
336
337int
338CommandCompletions::DiskDirectories
339(
340 CommandInterpreter &interpreter,
341 const char *partial_file_name,
342 int match_start_point,
343 int max_return_elements,
344 SearchFilter *searcher,
345 bool &word_complete,
346 StringList &matches
347)
348{
349 int ret_val = DiskFilesOrDirectories (partial_file_name,
350 true,
351 word_complete,
352 matches);
353 word_complete = false;
354 return ret_val;
355}
356
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357int
Greg Clayton66111032010-06-23 01:19:29 +0000358CommandCompletions::Modules
359(
360 CommandInterpreter &interpreter,
361 const char *partial_file_name,
362 int match_start_point,
363 int max_return_elements,
364 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000365 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000366 StringList &matches
367)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000368{
Jim Ingham558ce122010-06-30 05:02:46 +0000369 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000370 ModuleCompleter completer (interpreter,
371 partial_file_name,
372 match_start_point,
373 max_return_elements,
374 matches);
375
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376 if (searcher == NULL)
377 {
Jim Ingham2976d002010-08-26 21:32:51 +0000378 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Jim Ingham33df7cd2014-12-06 01:28:03 +0000379 SearchFilterForUnconstrainedSearches null_searcher (target_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 completer.DoCompletion (&null_searcher);
381 }
382 else
383 {
384 completer.DoCompletion (searcher);
385 }
386 return matches.GetSize();
387}
388
389int
Greg Clayton66111032010-06-23 01:19:29 +0000390CommandCompletions::Symbols
391(
392 CommandInterpreter &interpreter,
393 const char *partial_file_name,
394 int match_start_point,
395 int max_return_elements,
396 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000397 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000398 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000399{
Jim Ingham558ce122010-06-30 05:02:46 +0000400 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000401 SymbolCompleter completer (interpreter,
402 partial_file_name,
403 match_start_point,
404 max_return_elements,
405 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000406
407 if (searcher == NULL)
408 {
Jim Ingham2976d002010-08-26 21:32:51 +0000409 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Jim Ingham33df7cd2014-12-06 01:28:03 +0000410 SearchFilterForUnconstrainedSearches null_searcher (target_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000411 completer.DoCompletion (&null_searcher);
412 }
413 else
414 {
415 completer.DoCompletion (searcher);
416 }
417 return matches.GetSize();
418}
419
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000420int
421CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
422 const char *partial_setting_name,
423 int match_start_point,
424 int max_return_elements,
425 SearchFilter *searcher,
426 bool &word_complete,
427 StringList &matches)
428{
Greg Clayton67cc0632012-08-22 17:17:09 +0000429 // Cache the full setting name list
430 static StringList g_property_names;
431 if (g_property_names.GetSize() == 0)
432 {
433 // Generate the full setting name list on demand
434 lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
435 if (properties_sp)
436 {
437 StreamString strm;
438 properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
439 const std::string &str = strm.GetString();
440 g_property_names.SplitIntoLines(str.c_str(), str.size());
441 }
442 }
443
444 size_t exact_matches_idx = SIZE_MAX;
445 const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
Greg Clayton67cc0632012-08-22 17:17:09 +0000446 word_complete = exact_matches_idx != SIZE_MAX;
447 return num_matches;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000448}
449
Greg Claytonab65b342011-04-13 22:47:15 +0000450
451int
452CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
453 const char *partial_name,
454 int match_start_point,
455 int max_return_elements,
456 SearchFilter *searcher,
457 bool &word_complete,
458 lldb_private::StringList &matches)
459{
460 const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
461 word_complete = num_matches == 1;
462 return num_matches;
463}
464
465int
466CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
467 const char *partial_name,
468 int match_start_point,
469 int max_return_elements,
470 SearchFilter *searcher,
471 bool &word_complete,
472 lldb_private::StringList &matches)
473{
474 const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
475 word_complete = num_matches == 1;
476 return num_matches;
477}
478
479
Greg Claytonf21fead2013-05-14 23:43:18 +0000480int
481CommandCompletions::VariablePath (CommandInterpreter &interpreter,
482 const char *partial_name,
483 int match_start_point,
484 int max_return_elements,
485 SearchFilter *searcher,
486 bool &word_complete,
487 lldb_private::StringList &matches)
488{
489 return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
490}
491
492
Greg Clayton66111032010-06-23 01:19:29 +0000493CommandCompletions::Completer::Completer
494(
495 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000496 const char *completion_str,
497 int match_start_point,
498 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000499 StringList &matches
500) :
Greg Clayton66111032010-06-23 01:19:29 +0000501 m_interpreter (interpreter),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000502 m_completion_str (completion_str),
503 m_match_start_point (match_start_point),
504 m_max_return_elements (max_return_elements),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000505 m_matches (matches)
506{
507}
508
509CommandCompletions::Completer::~Completer ()
510{
511
512}
513
514//----------------------------------------------------------------------
515// SourceFileCompleter
516//----------------------------------------------------------------------
517
Greg Clayton66111032010-06-23 01:19:29 +0000518CommandCompletions::SourceFileCompleter::SourceFileCompleter
519(
520 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000521 bool include_support_files,
522 const char *completion_str,
523 int match_start_point,
524 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000525 StringList &matches
526) :
Greg Clayton66111032010-06-23 01:19:29 +0000527 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000528 m_include_support_files (include_support_files),
529 m_matching_files()
530{
Greg Clayton274060b2010-10-20 20:54:39 +0000531 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000532 m_file_name = partial_spec.GetFilename().GetCString();
533 m_dir_name = partial_spec.GetDirectory().GetCString();
534}
535
536Searcher::Depth
537CommandCompletions::SourceFileCompleter::GetDepth()
538{
539 return eDepthCompUnit;
540}
541
542Searcher::CallbackReturn
543CommandCompletions::SourceFileCompleter::SearchCallback (
544 SearchFilter &filter,
545 SymbolContext &context,
546 Address *addr,
547 bool complete
548)
549{
550 if (context.comp_unit != NULL)
551 {
552 if (m_include_support_files)
553 {
554 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
555 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
556 {
557 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
558 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
559 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
560 bool match = false;
561 if (m_file_name && sfile_file_name
562 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
563 match = true;
564 if (match && m_dir_name && sfile_dir_name
565 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
566 match = false;
567
568 if (match)
569 {
570 m_matching_files.AppendIfUnique(sfile_spec);
571 }
572 }
573
574 }
575 else
576 {
577 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
578 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
579
580 bool match = false;
581 if (m_file_name && cur_file_name
582 && strstr (cur_file_name, m_file_name) == cur_file_name)
583 match = true;
584
585 if (match && m_dir_name && cur_dir_name
586 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
587 match = false;
588
589 if (match)
590 {
591 m_matching_files.AppendIfUnique(context.comp_unit);
592 }
593 }
594 }
595 return Searcher::eCallbackReturnContinue;
596}
597
598size_t
599CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
600{
601 filter->Search (*this);
602 // Now convert the filelist to completions:
603 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
604 {
605 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
606 }
607 return m_matches.GetSize();
608
609}
610
611//----------------------------------------------------------------------
612// SymbolCompleter
613//----------------------------------------------------------------------
614
615static bool
616regex_chars (const char comp)
617{
Greg Clayton649f8b92013-06-07 00:35:40 +0000618 if (comp == '[' || comp == ']' ||
619 comp == '(' || comp == ')' ||
620 comp == '{' || comp == '}' ||
621 comp == '+' ||
622 comp == '.' ||
623 comp == '*' ||
624 comp == '|' ||
625 comp == '^' ||
626 comp == '$' ||
627 comp == '\\' ||
628 comp == '?')
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000629 return true;
630 else
631 return false;
632}
Greg Clayton66111032010-06-23 01:19:29 +0000633CommandCompletions::SymbolCompleter::SymbolCompleter
634(
635 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000636 const char *completion_str,
637 int match_start_point,
638 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000639 StringList &matches
640) :
Greg Clayton66111032010-06-23 01:19:29 +0000641 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000642{
Greg Clayton649f8b92013-06-07 00:35:40 +0000643 std::string regex_str;
644 if (completion_str && completion_str[0])
645 {
646 regex_str.append("^");
647 regex_str.append(completion_str);
648 }
649 else
650 {
651 // Match anything since the completion string is empty
652 regex_str.append(".");
653 }
654 std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
655 while (pos < regex_str.end())
656 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000657 pos = regex_str.insert(pos, '\\');
Greg Clayton649f8b92013-06-07 00:35:40 +0000658 pos = find_if(pos + 2, regex_str.end(), regex_chars);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000659 }
660 m_regex.Compile(regex_str.c_str());
661}
662
663Searcher::Depth
664CommandCompletions::SymbolCompleter::GetDepth()
665{
666 return eDepthModule;
667}
668
669Searcher::CallbackReturn
670CommandCompletions::SymbolCompleter::SearchCallback (
671 SearchFilter &filter,
672 SymbolContext &context,
673 Address *addr,
674 bool complete
675)
676{
Greg Clayton931180e2011-01-27 06:44:37 +0000677 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000678 {
Greg Clayton931180e2011-01-27 06:44:37 +0000679 SymbolContextList sc_list;
680 const bool include_symbols = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000681 const bool include_inlines = true;
Greg Clayton931180e2011-01-27 06:44:37 +0000682 const bool append = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000683 context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000684
685 SymbolContext sc;
686 // Now add the functions & symbols to the list - only add if unique:
Greg Clayton931180e2011-01-27 06:44:37 +0000687 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000688 {
Greg Clayton931180e2011-01-27 06:44:37 +0000689 if (sc_list.GetContextAtIndex(i, sc))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000690 {
Jim Ingham530a4132011-09-27 19:48:20 +0000691 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
692 if (!func_name.IsEmpty())
693 m_match_set.insert (func_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000694 }
695 }
696 }
697 return Searcher::eCallbackReturnContinue;
698}
699
700size_t
701CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
702{
703 filter->Search (*this);
704 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
705 for (pos = m_match_set.begin(); pos != end; pos++)
706 m_matches.AppendString((*pos).GetCString());
707
708 return m_matches.GetSize();
709}
710
711//----------------------------------------------------------------------
712// ModuleCompleter
713//----------------------------------------------------------------------
Greg Clayton66111032010-06-23 01:19:29 +0000714CommandCompletions::ModuleCompleter::ModuleCompleter
715(
716 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000717 const char *completion_str,
718 int match_start_point,
719 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000720 StringList &matches
721) :
Greg Clayton66111032010-06-23 01:19:29 +0000722 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000723{
Greg Clayton274060b2010-10-20 20:54:39 +0000724 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000725 m_file_name = partial_spec.GetFilename().GetCString();
726 m_dir_name = partial_spec.GetDirectory().GetCString();
727}
728
729Searcher::Depth
730CommandCompletions::ModuleCompleter::GetDepth()
731{
732 return eDepthModule;
733}
734
735Searcher::CallbackReturn
736CommandCompletions::ModuleCompleter::SearchCallback (
737 SearchFilter &filter,
738 SymbolContext &context,
739 Address *addr,
740 bool complete
741)
742{
Greg Clayton747bcb02011-09-17 06:21:20 +0000743 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000744 {
745 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
746 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
747
748 bool match = false;
749 if (m_file_name && cur_file_name
750 && strstr (cur_file_name, m_file_name) == cur_file_name)
751 match = true;
752
753 if (match && m_dir_name && cur_dir_name
754 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
755 match = false;
756
757 if (match)
758 {
759 m_matches.AppendString (cur_file_name);
760 }
761 }
762 return Searcher::eCallbackReturnContinue;
763}
764
765size_t
766CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
767{
768 filter->Search (*this);
769 return m_matches.GetSize();
770}