blob: 175c91d875d91279fb49412c028279c8e154244e [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Daniel Malead891f9b2012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
Chris Lattner24943d22010-06-08 16:52:24 +000011
12// C Includes
Jim Ingham802f8b02010-06-30 05:02:46 +000013#include <sys/stat.h>
14#include <dirent.h>
Greg Clayton8da92a72011-02-05 02:27:52 +000015#if defined(__APPLE__) || defined(__linux__)
Jim Ingham84a0d332010-07-02 00:45:55 +000016#include <pwd.h>
Greg Clayton8da92a72011-02-05 02:27:52 +000017#endif
Jim Ingham802f8b02010-06-30 05:02:46 +000018
Chris Lattner24943d22010-06-08 16:52:24 +000019// C++ Includes
20// Other libraries and framework includes
21// Project includes
Greg Clayton5f54ac32011-02-08 05:05:52 +000022#include "lldb/Host/FileSpec.h"
Greg Clayton74800612011-02-01 05:15:22 +000023#include "lldb/Core/FileSpecList.h"
Greg Clayton5e342f52011-04-13 22:47:15 +000024#include "lldb/Core/PluginManager.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000025#include "lldb/Core/Module.h"
Greg Clayton74800612011-02-01 05:15:22 +000026#include "lldb/Interpreter/Args.h"
27#include "lldb/Interpreter/CommandCompletions.h"
28#include "lldb/Interpreter/CommandInterpreter.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000029#include "lldb/Symbol/CompileUnit.h"
Greg Clayton74800612011-02-01 05:15:22 +000030#include "lldb/Target/Target.h"
31#include "lldb/Utility/CleanUp.h"
Chris Lattner24943d22010-06-08 16:52:24 +000032
33using namespace lldb_private;
34
35CommandCompletions::CommonCompletionElement
36CommandCompletions::g_common_completions[] =
37{
Jim Ingham802f8b02010-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 Tice6e4c5ce2010-09-04 00:03:46 +000044 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
Greg Clayton5e342f52011-04-13 22:47:15 +000045 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
46 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
Jim Ingham802f8b02010-06-30 05:02:46 +000047 {eNoCompletion, NULL} // This one has to be last in the list.
Chris Lattner24943d22010-06-08 16:52:24 +000048};
49
50bool
Greg Clayton63094e02010-06-23 01:19:29 +000051CommandCompletions::InvokeCommonCompletionCallbacks
52(
53 CommandInterpreter &interpreter,
54 uint32_t completion_mask,
55 const char *completion_str,
56 int match_start_point,
57 int max_return_elements,
58 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +000059 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +000060 StringList &matches
61)
Chris Lattner24943d22010-06-08 16:52:24 +000062{
63 bool handled = false;
64
65 if (completion_mask & eCustomCompletion)
66 return false;
67
68 for (int i = 0; ; i++)
69 {
70 if (g_common_completions[i].type == eNoCompletion)
71 break;
72 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
73 && g_common_completions[i].callback != NULL)
74 {
75 handled = true;
Greg Clayton63094e02010-06-23 01:19:29 +000076 g_common_completions[i].callback (interpreter,
77 completion_str,
Chris Lattner24943d22010-06-08 16:52:24 +000078 match_start_point,
79 max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +000080 searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +000081 word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +000082 matches);
83 }
84 }
85 return handled;
86}
87
88int
Greg Clayton63094e02010-06-23 01:19:29 +000089CommandCompletions::SourceFiles
90(
91 CommandInterpreter &interpreter,
92 const char *partial_file_name,
93 int match_start_point,
94 int max_return_elements,
95 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +000096 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +000097 StringList &matches
98)
Chris Lattner24943d22010-06-08 16:52:24 +000099{
Jim Ingham802f8b02010-06-30 05:02:46 +0000100 word_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000101 // Find some way to switch "include support files..."
Greg Clayton63094e02010-06-23 01:19:29 +0000102 SourceFileCompleter completer (interpreter,
103 false,
104 partial_file_name,
105 match_start_point,
106 max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000107 matches);
108
109 if (searcher == NULL)
110 {
Jim Inghamc8332952010-08-26 21:32:51 +0000111 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000112 SearchFilter null_searcher (target_sp);
113 completer.DoCompletion (&null_searcher);
114 }
115 else
116 {
117 completer.DoCompletion (searcher);
118 }
119 return matches.GetSize();
120}
121
Jim Ingham802f8b02010-06-30 05:02:46 +0000122static int
123DiskFilesOrDirectories
124(
125 const char *partial_file_name,
126 bool only_directories,
127 bool &saw_directory,
128 StringList &matches
129)
130{
131 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
132 // If it is not defined on your host system, you'll need to implement it yourself...
133
134 int partial_name_len = strlen(partial_file_name);
135
136 if (partial_name_len >= PATH_MAX)
137 return matches.GetSize();
138
139 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
140 // below will point to the place of the remainder in this string. Then when we've resolved the
141 // containing directory, and opened it, we'll read the directory contents and overwrite the
142 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
143 // the form the user originally typed.
144
145 char partial_name_copy[PATH_MAX];
Benjamin Kramerbdbb9af2010-06-30 13:43:47 +0000146 memcpy(partial_name_copy, partial_file_name, partial_name_len);
Jim Ingham802f8b02010-06-30 05:02:46 +0000147 partial_name_copy[partial_name_len] = '\0';
148
Greg Clayton5d187e52011-01-08 20:28:42 +0000149 // We'll need to save a copy of the remainder for comparison, which we do here.
Jim Ingham802f8b02010-06-30 05:02:46 +0000150 char remainder[PATH_MAX];
151
152 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
153 char *end_ptr;
154
155 end_ptr = strrchr(partial_name_copy, '/');
156
157 // This will store the resolved form of the containing directory
158 char containing_part[PATH_MAX];
159
160 if (end_ptr == NULL)
161 {
162 // There's no directory. If the thing begins with a "~" then this is a bare
163 // user name.
164 if (*partial_name_copy == '~')
165 {
166 // Nothing here but the user name. We could just put a slash on the end,
Jim Ingham84a0d332010-07-02 00:45:55 +0000167 // but for completeness sake we'll resolve the user name and only put a slash
Jim Ingham802f8b02010-06-30 05:02:46 +0000168 // on the end if it exists.
Jim Ingham84a0d332010-07-02 00:45:55 +0000169 char resolved_username[PATH_MAX];
Greg Clayton54e7afa2010-07-09 20:39:50 +0000170 size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username,
Jim Ingham84a0d332010-07-02 00:45:55 +0000171 sizeof (resolved_username));
172
173 // Not sure how this would happen, a username longer than PATH_MAX? Still...
174 if (resolved_username_len >= sizeof (resolved_username))
175 return matches.GetSize();
Jim Ingham158842c2011-02-08 23:24:09 +0000176 else if (resolved_username_len == 0)
Jim Ingham84a0d332010-07-02 00:45:55 +0000177 {
178 // The user name didn't resolve, let's look in the password database for matches.
179 // The user name database contains duplicates, and is not in alphabetical order, so
180 // we'll use a set to manage that for us.
Jim Ingham158842c2011-02-08 23:24:09 +0000181 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
182 if (matches.GetSize() > 0)
183 saw_directory = true;
Jim Ingham84a0d332010-07-02 00:45:55 +0000184 return matches.GetSize();
Jim Ingham158842c2011-02-08 23:24:09 +0000185 }
186 else
187 {
188 //The thing exists, put a '/' on the end, and return it...
189 // FIXME: complete user names here:
190 partial_name_copy[partial_name_len] = '/';
191 partial_name_copy[partial_name_len+1] = '\0';
192 matches.AppendString(partial_name_copy);
193 saw_directory = true;
194 return matches.GetSize();
195 }
Jim Ingham802f8b02010-06-30 05:02:46 +0000196 }
197 else
198 {
199 // The containing part is the CWD, and the whole string is the remainder.
200 containing_part[0] = '.';
201 containing_part[1] = '\0';
202 strcpy(remainder, partial_name_copy);
203 end_ptr = partial_name_copy;
204 }
205 }
206 else
207 {
208 if (end_ptr == partial_name_copy)
209 {
210 // We're completing a file or directory in the root volume.
211 containing_part[0] = '/';
212 containing_part[1] = '\0';
213 }
214 else
215 {
216 size_t len = end_ptr - partial_name_copy;
217 memcpy(containing_part, partial_name_copy, len);
218 containing_part[len] = '\0';
219 }
220 // Push end_ptr past the final "/" and set remainder.
221 end_ptr++;
222 strcpy(remainder, end_ptr);
223 }
224
Jim Ingham84a0d332010-07-02 00:45:55 +0000225 // Look for a user name in the containing part, and if it's there, resolve it and stick the
Jim Ingham802f8b02010-06-30 05:02:46 +0000226 // result back into the containing_part:
Greg Clayton8da92a72011-02-05 02:27:52 +0000227
Jim Ingham802f8b02010-06-30 05:02:46 +0000228 if (*partial_name_copy == '~')
229 {
Jim Ingham158842c2011-02-08 23:24:09 +0000230 size_t resolved_username_len = FileSpec::ResolveUsername(containing_part,
231 containing_part,
232 sizeof (containing_part));
Jim Ingham802f8b02010-06-30 05:02:46 +0000233 // User name doesn't exist, we're not getting any further...
Greg Clayton099c7972010-07-06 16:11:44 +0000234 if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
Jim Ingham802f8b02010-06-30 05:02:46 +0000235 return matches.GetSize();
Jim Ingham802f8b02010-06-30 05:02:46 +0000236 }
Greg Clayton8da92a72011-02-05 02:27:52 +0000237
Jim Ingham802f8b02010-06-30 05:02:46 +0000238 // Okay, containing_part is now the directory we want to open and look for files:
Greg Clayton74800612011-02-01 05:15:22 +0000239
240 lldb_utility::CleanUp <DIR *, int> dir_stream (opendir(containing_part), NULL, closedir);
241 if (!dir_stream.is_valid())
Jim Ingham802f8b02010-06-30 05:02:46 +0000242 return matches.GetSize();
Greg Clayton74800612011-02-01 05:15:22 +0000243
Jim Ingham802f8b02010-06-30 05:02:46 +0000244 struct dirent *dirent_buf;
245
246 size_t baselen = end_ptr - partial_name_copy;
247
Greg Clayton74800612011-02-01 05:15:22 +0000248 while ((dirent_buf = readdir(dir_stream.get())) != NULL)
Jim Ingham802f8b02010-06-30 05:02:46 +0000249 {
250 char *name = dirent_buf->d_name;
251
252 // Omit ".", ".." and any . files if the match string doesn't start with .
253 if (name[0] == '.')
254 {
255 if (name[1] == '\0')
256 continue;
257 else if (name[1] == '.' && name[2] == '\0')
258 continue;
259 else if (remainder[0] != '.')
260 continue;
261 }
262
Jim Ingham84a0d332010-07-02 00:45:55 +0000263 // If we found a directory, we put a "/" at the end of the name.
264
Jim Ingham802f8b02010-06-30 05:02:46 +0000265 if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name)
266 {
267 if (strlen(name) + baselen >= PATH_MAX)
268 continue;
269
270 strcpy(end_ptr, name);
271
272 bool isa_directory = false;
273 if (dirent_buf->d_type & DT_DIR)
274 isa_directory = true;
275 else if (dirent_buf->d_type & DT_LNK)
276 {
277 struct stat stat_buf;
Jason Molendaf38b76b2011-07-08 00:38:03 +0000278 if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
Jim Ingham802f8b02010-06-30 05:02:46 +0000279 isa_directory = true;
280 }
281
282 if (isa_directory)
283 {
284 saw_directory = true;
285 size_t len = strlen(partial_name_copy);
286 partial_name_copy[len] = '/';
287 partial_name_copy[len + 1] = '\0';
288 }
289 if (only_directories && !isa_directory)
290 continue;
291 matches.AppendString(partial_name_copy);
292 }
293 }
294
295 return matches.GetSize();
296}
297
298int
299CommandCompletions::DiskFiles
300(
301 CommandInterpreter &interpreter,
302 const char *partial_file_name,
303 int match_start_point,
304 int max_return_elements,
305 SearchFilter *searcher,
306 bool &word_complete,
307 StringList &matches
308)
309{
310
311 int ret_val = DiskFilesOrDirectories (partial_file_name,
312 false,
313 word_complete,
314 matches);
315 word_complete = !word_complete;
316 return ret_val;
317}
318
319int
320CommandCompletions::DiskDirectories
321(
322 CommandInterpreter &interpreter,
323 const char *partial_file_name,
324 int match_start_point,
325 int max_return_elements,
326 SearchFilter *searcher,
327 bool &word_complete,
328 StringList &matches
329)
330{
331 int ret_val = DiskFilesOrDirectories (partial_file_name,
332 true,
333 word_complete,
334 matches);
335 word_complete = false;
336 return ret_val;
337}
338
Chris Lattner24943d22010-06-08 16:52:24 +0000339int
Greg Clayton63094e02010-06-23 01:19:29 +0000340CommandCompletions::Modules
341(
342 CommandInterpreter &interpreter,
343 const char *partial_file_name,
344 int match_start_point,
345 int max_return_elements,
346 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +0000347 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000348 StringList &matches
349)
Chris Lattner24943d22010-06-08 16:52:24 +0000350{
Jim Ingham802f8b02010-06-30 05:02:46 +0000351 word_complete = true;
Greg Clayton63094e02010-06-23 01:19:29 +0000352 ModuleCompleter completer (interpreter,
353 partial_file_name,
354 match_start_point,
355 max_return_elements,
356 matches);
357
Chris Lattner24943d22010-06-08 16:52:24 +0000358 if (searcher == NULL)
359 {
Jim Inghamc8332952010-08-26 21:32:51 +0000360 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000361 SearchFilter null_searcher (target_sp);
362 completer.DoCompletion (&null_searcher);
363 }
364 else
365 {
366 completer.DoCompletion (searcher);
367 }
368 return matches.GetSize();
369}
370
371int
Greg Clayton63094e02010-06-23 01:19:29 +0000372CommandCompletions::Symbols
373(
374 CommandInterpreter &interpreter,
375 const char *partial_file_name,
376 int match_start_point,
377 int max_return_elements,
378 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +0000379 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000380 StringList &matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000381{
Jim Ingham802f8b02010-06-30 05:02:46 +0000382 word_complete = true;
Greg Clayton63094e02010-06-23 01:19:29 +0000383 SymbolCompleter completer (interpreter,
384 partial_file_name,
385 match_start_point,
386 max_return_elements,
387 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000388
389 if (searcher == NULL)
390 {
Jim Inghamc8332952010-08-26 21:32:51 +0000391 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000392 SearchFilter null_searcher (target_sp);
393 completer.DoCompletion (&null_searcher);
394 }
395 else
396 {
397 completer.DoCompletion (searcher);
398 }
399 return matches.GetSize();
400}
401
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000402int
403CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
404 const char *partial_setting_name,
405 int match_start_point,
406 int max_return_elements,
407 SearchFilter *searcher,
408 bool &word_complete,
409 StringList &matches)
410{
Greg Clayton73844aa2012-08-22 17:17:09 +0000411 // Cache the full setting name list
412 static StringList g_property_names;
413 if (g_property_names.GetSize() == 0)
414 {
415 // Generate the full setting name list on demand
416 lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
417 if (properties_sp)
418 {
419 StreamString strm;
420 properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
421 const std::string &str = strm.GetString();
422 g_property_names.SplitIntoLines(str.c_str(), str.size());
423 }
424 }
425
426 size_t exact_matches_idx = SIZE_MAX;
427 const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
Greg Clayton73844aa2012-08-22 17:17:09 +0000428 word_complete = exact_matches_idx != SIZE_MAX;
429 return num_matches;
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000430}
431
Greg Clayton5e342f52011-04-13 22:47:15 +0000432
433int
434CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
435 const char *partial_name,
436 int match_start_point,
437 int max_return_elements,
438 SearchFilter *searcher,
439 bool &word_complete,
440 lldb_private::StringList &matches)
441{
442 const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
443 word_complete = num_matches == 1;
444 return num_matches;
445}
446
447int
448CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
449 const char *partial_name,
450 int match_start_point,
451 int max_return_elements,
452 SearchFilter *searcher,
453 bool &word_complete,
454 lldb_private::StringList &matches)
455{
456 const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
457 word_complete = num_matches == 1;
458 return num_matches;
459}
460
461
Greg Clayton63094e02010-06-23 01:19:29 +0000462CommandCompletions::Completer::Completer
463(
464 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000465 const char *completion_str,
466 int match_start_point,
467 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000468 StringList &matches
469) :
Greg Clayton63094e02010-06-23 01:19:29 +0000470 m_interpreter (interpreter),
Chris Lattner24943d22010-06-08 16:52:24 +0000471 m_completion_str (completion_str),
472 m_match_start_point (match_start_point),
473 m_max_return_elements (max_return_elements),
Chris Lattner24943d22010-06-08 16:52:24 +0000474 m_matches (matches)
475{
476}
477
478CommandCompletions::Completer::~Completer ()
479{
480
481}
482
483//----------------------------------------------------------------------
484// SourceFileCompleter
485//----------------------------------------------------------------------
486
Greg Clayton63094e02010-06-23 01:19:29 +0000487CommandCompletions::SourceFileCompleter::SourceFileCompleter
488(
489 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000490 bool include_support_files,
491 const char *completion_str,
492 int match_start_point,
493 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000494 StringList &matches
495) :
Greg Clayton63094e02010-06-23 01:19:29 +0000496 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner24943d22010-06-08 16:52:24 +0000497 m_include_support_files (include_support_files),
498 m_matching_files()
499{
Greg Clayton537a7a82010-10-20 20:54:39 +0000500 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000501 m_file_name = partial_spec.GetFilename().GetCString();
502 m_dir_name = partial_spec.GetDirectory().GetCString();
503}
504
505Searcher::Depth
506CommandCompletions::SourceFileCompleter::GetDepth()
507{
508 return eDepthCompUnit;
509}
510
511Searcher::CallbackReturn
512CommandCompletions::SourceFileCompleter::SearchCallback (
513 SearchFilter &filter,
514 SymbolContext &context,
515 Address *addr,
516 bool complete
517)
518{
519 if (context.comp_unit != NULL)
520 {
521 if (m_include_support_files)
522 {
523 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
524 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
525 {
526 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
527 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
528 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
529 bool match = false;
530 if (m_file_name && sfile_file_name
531 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
532 match = true;
533 if (match && m_dir_name && sfile_dir_name
534 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
535 match = false;
536
537 if (match)
538 {
539 m_matching_files.AppendIfUnique(sfile_spec);
540 }
541 }
542
543 }
544 else
545 {
546 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
547 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
548
549 bool match = false;
550 if (m_file_name && cur_file_name
551 && strstr (cur_file_name, m_file_name) == cur_file_name)
552 match = true;
553
554 if (match && m_dir_name && cur_dir_name
555 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
556 match = false;
557
558 if (match)
559 {
560 m_matching_files.AppendIfUnique(context.comp_unit);
561 }
562 }
563 }
564 return Searcher::eCallbackReturnContinue;
565}
566
567size_t
568CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
569{
570 filter->Search (*this);
571 // Now convert the filelist to completions:
572 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
573 {
574 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
575 }
576 return m_matches.GetSize();
577
578}
579
580//----------------------------------------------------------------------
581// SymbolCompleter
582//----------------------------------------------------------------------
583
584static bool
585regex_chars (const char comp)
586{
587 if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
588 return true;
589 else
590 return false;
591}
Greg Clayton63094e02010-06-23 01:19:29 +0000592CommandCompletions::SymbolCompleter::SymbolCompleter
593(
594 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000595 const char *completion_str,
596 int match_start_point,
597 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000598 StringList &matches
599) :
Greg Clayton63094e02010-06-23 01:19:29 +0000600 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000601{
602 std::string regex_str ("^");
603 regex_str.append(completion_str);
604 regex_str.append(".*");
605 std::string::iterator pos;
606
607 pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
608 while (pos < regex_str.end()) {
609 pos = regex_str.insert(pos, '\\');
610 pos += 2;
611 pos = find_if(pos, regex_str.end(), regex_chars);
612 }
613 m_regex.Compile(regex_str.c_str());
614}
615
616Searcher::Depth
617CommandCompletions::SymbolCompleter::GetDepth()
618{
619 return eDepthModule;
620}
621
622Searcher::CallbackReturn
623CommandCompletions::SymbolCompleter::SearchCallback (
624 SearchFilter &filter,
625 SymbolContext &context,
626 Address *addr,
627 bool complete
628)
629{
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000630 if (context.module_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000631 {
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000632 SymbolContextList sc_list;
633 const bool include_symbols = true;
Sean Callanan302d78c2012-02-10 22:52:19 +0000634 const bool include_inlines = true;
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000635 const bool append = true;
Sean Callanan302d78c2012-02-10 22:52:19 +0000636 context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
Chris Lattner24943d22010-06-08 16:52:24 +0000637
638 SymbolContext sc;
639 // Now add the functions & symbols to the list - only add if unique:
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000640 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000641 {
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000642 if (sc_list.GetContextAtIndex(i, sc))
Chris Lattner24943d22010-06-08 16:52:24 +0000643 {
Jim Inghama7d89512011-09-27 19:48:20 +0000644 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
645 if (!func_name.IsEmpty())
646 m_match_set.insert (func_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000647 }
648 }
649 }
650 return Searcher::eCallbackReturnContinue;
651}
652
653size_t
654CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
655{
656 filter->Search (*this);
657 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
658 for (pos = m_match_set.begin(); pos != end; pos++)
659 m_matches.AppendString((*pos).GetCString());
660
661 return m_matches.GetSize();
662}
663
664//----------------------------------------------------------------------
665// ModuleCompleter
666//----------------------------------------------------------------------
Greg Clayton63094e02010-06-23 01:19:29 +0000667CommandCompletions::ModuleCompleter::ModuleCompleter
668(
669 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000670 const char *completion_str,
671 int match_start_point,
672 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000673 StringList &matches
674) :
Greg Clayton63094e02010-06-23 01:19:29 +0000675 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000676{
Greg Clayton537a7a82010-10-20 20:54:39 +0000677 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000678 m_file_name = partial_spec.GetFilename().GetCString();
679 m_dir_name = partial_spec.GetDirectory().GetCString();
680}
681
682Searcher::Depth
683CommandCompletions::ModuleCompleter::GetDepth()
684{
685 return eDepthModule;
686}
687
688Searcher::CallbackReturn
689CommandCompletions::ModuleCompleter::SearchCallback (
690 SearchFilter &filter,
691 SymbolContext &context,
692 Address *addr,
693 bool complete
694)
695{
Greg Clayton6e0101c2011-09-17 06:21:20 +0000696 if (context.module_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000697 {
698 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
699 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
700
701 bool match = false;
702 if (m_file_name && cur_file_name
703 && strstr (cur_file_name, m_file_name) == cur_file_name)
704 match = true;
705
706 if (match && m_dir_name && cur_dir_name
707 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
708 match = false;
709
710 if (match)
711 {
712 m_matches.AppendString (cur_file_name);
713 }
714 }
715 return Searcher::eCallbackReturnContinue;
716}
717
718size_t
719CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
720{
721 filter->Search (*this);
722 return m_matches.GetSize();
723}