blob: 3102f558488f3c108f3e227329e9e62796b33113 [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
10
11// C Includes
Jim Ingham802f8b02010-06-30 05:02:46 +000012#include <sys/stat.h>
13#include <dirent.h>
14#include <libgen.h>
15#include <glob.h>
Jim Ingham84a0d332010-07-02 00:45:55 +000016#include <pwd.h>
17#include <sys/types.h>
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
Jim Ingham84cdc152010-06-15 19:49:27 +000022#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Core/FileSpecList.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Interpreter/CommandCompletions.h"
Jim Ingham84a0d332010-07-02 00:45:55 +000027#include "lldb/Core/FileSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000028
29
30using namespace lldb_private;
31
32CommandCompletions::CommonCompletionElement
33CommandCompletions::g_common_completions[] =
34{
Jim Ingham802f8b02010-06-30 05:02:46 +000035 {eCustomCompletion, NULL},
36 {eSourceFileCompletion, CommandCompletions::SourceFiles},
37 {eDiskFileCompletion, CommandCompletions::DiskFiles},
38 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
39 {eSymbolCompletion, CommandCompletions::Symbols},
40 {eModuleCompletion, CommandCompletions::Modules},
Caroline Tice6e4c5ce2010-09-04 00:03:46 +000041 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
Jim Ingham802f8b02010-06-30 05:02:46 +000042 {eNoCompletion, NULL} // This one has to be last in the list.
Chris Lattner24943d22010-06-08 16:52:24 +000043};
44
45bool
Greg Clayton63094e02010-06-23 01:19:29 +000046CommandCompletions::InvokeCommonCompletionCallbacks
47(
48 CommandInterpreter &interpreter,
49 uint32_t completion_mask,
50 const char *completion_str,
51 int match_start_point,
52 int max_return_elements,
53 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +000054 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +000055 StringList &matches
56)
Chris Lattner24943d22010-06-08 16:52:24 +000057{
58 bool handled = false;
59
60 if (completion_mask & eCustomCompletion)
61 return false;
62
63 for (int i = 0; ; i++)
64 {
65 if (g_common_completions[i].type == eNoCompletion)
66 break;
67 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
68 && g_common_completions[i].callback != NULL)
69 {
70 handled = true;
Greg Clayton63094e02010-06-23 01:19:29 +000071 g_common_completions[i].callback (interpreter,
72 completion_str,
Chris Lattner24943d22010-06-08 16:52:24 +000073 match_start_point,
74 max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +000075 searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +000076 word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +000077 matches);
78 }
79 }
80 return handled;
81}
82
83int
Greg Clayton63094e02010-06-23 01:19:29 +000084CommandCompletions::SourceFiles
85(
86 CommandInterpreter &interpreter,
87 const char *partial_file_name,
88 int match_start_point,
89 int max_return_elements,
90 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +000091 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +000092 StringList &matches
93)
Chris Lattner24943d22010-06-08 16:52:24 +000094{
Jim Ingham802f8b02010-06-30 05:02:46 +000095 word_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +000096 // Find some way to switch "include support files..."
Greg Clayton63094e02010-06-23 01:19:29 +000097 SourceFileCompleter completer (interpreter,
98 false,
99 partial_file_name,
100 match_start_point,
101 max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000102 matches);
103
104 if (searcher == NULL)
105 {
Jim Inghamc8332952010-08-26 21:32:51 +0000106 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000107 SearchFilter null_searcher (target_sp);
108 completer.DoCompletion (&null_searcher);
109 }
110 else
111 {
112 completer.DoCompletion (searcher);
113 }
114 return matches.GetSize();
115}
116
Jim Ingham802f8b02010-06-30 05:02:46 +0000117static int
118DiskFilesOrDirectories
119(
120 const char *partial_file_name,
121 bool only_directories,
122 bool &saw_directory,
123 StringList &matches
124)
125{
126 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
127 // If it is not defined on your host system, you'll need to implement it yourself...
128
129 int partial_name_len = strlen(partial_file_name);
130
131 if (partial_name_len >= PATH_MAX)
132 return matches.GetSize();
133
134 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
135 // below will point to the place of the remainder in this string. Then when we've resolved the
136 // containing directory, and opened it, we'll read the directory contents and overwrite the
137 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
138 // the form the user originally typed.
139
140 char partial_name_copy[PATH_MAX];
Benjamin Kramerbdbb9af2010-06-30 13:43:47 +0000141 memcpy(partial_name_copy, partial_file_name, partial_name_len);
Jim Ingham802f8b02010-06-30 05:02:46 +0000142 partial_name_copy[partial_name_len] = '\0';
143
Greg Clayton5d187e52011-01-08 20:28:42 +0000144 // We'll need to save a copy of the remainder for comparison, which we do here.
Jim Ingham802f8b02010-06-30 05:02:46 +0000145 char remainder[PATH_MAX];
146
147 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
148 char *end_ptr;
149
150 end_ptr = strrchr(partial_name_copy, '/');
151
152 // This will store the resolved form of the containing directory
153 char containing_part[PATH_MAX];
154
155 if (end_ptr == NULL)
156 {
157 // There's no directory. If the thing begins with a "~" then this is a bare
158 // user name.
159 if (*partial_name_copy == '~')
160 {
161 // Nothing here but the user name. We could just put a slash on the end,
Jim Ingham84a0d332010-07-02 00:45:55 +0000162 // but for completeness sake we'll resolve the user name and only put a slash
Jim Ingham802f8b02010-06-30 05:02:46 +0000163 // on the end if it exists.
Jim Ingham84a0d332010-07-02 00:45:55 +0000164 char resolved_username[PATH_MAX];
Greg Clayton54e7afa2010-07-09 20:39:50 +0000165 size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username,
Jim Ingham84a0d332010-07-02 00:45:55 +0000166 sizeof (resolved_username));
167
168 // Not sure how this would happen, a username longer than PATH_MAX? Still...
169 if (resolved_username_len >= sizeof (resolved_username))
170 return matches.GetSize();
171 else if (resolved_username_len == 0)
172 {
173 // The user name didn't resolve, let's look in the password database for matches.
174 // The user name database contains duplicates, and is not in alphabetical order, so
175 // we'll use a set to manage that for us.
176
177 setpwent();
178 struct passwd *user_entry;
179 const char *name_start = partial_name_copy + 1;
180 std::set<std::string> name_list;
181
182 while ((user_entry = getpwent()) != NULL)
183 {
184 if (strstr(user_entry->pw_name, name_start) == user_entry->pw_name)
185 {
186 std::string tmp_buf("~");
187 tmp_buf.append(user_entry->pw_name);
188 tmp_buf.push_back('/');
189 name_list.insert(tmp_buf);
190 saw_directory = true;
191 }
192 }
193 std::set<std::string>::iterator pos, end = name_list.end();
194 for (pos = name_list.begin(); pos != end; pos++)
195 {
196 matches.AppendString((*pos).c_str());
197 }
198 return matches.GetSize();
199 }
200
201 //The thing exists, put a '/' on the end, and return it...
202 // FIXME: complete user names here:
203 partial_name_copy[partial_name_len] = '/';
204 partial_name_copy[partial_name_len+1] = '\0';
205 matches.AppendString(partial_name_copy);
206 saw_directory = true;
207 return matches.GetSize();
Jim Ingham802f8b02010-06-30 05:02:46 +0000208 }
209 else
210 {
211 // The containing part is the CWD, and the whole string is the remainder.
212 containing_part[0] = '.';
213 containing_part[1] = '\0';
214 strcpy(remainder, partial_name_copy);
215 end_ptr = partial_name_copy;
216 }
217 }
218 else
219 {
220 if (end_ptr == partial_name_copy)
221 {
222 // We're completing a file or directory in the root volume.
223 containing_part[0] = '/';
224 containing_part[1] = '\0';
225 }
226 else
227 {
228 size_t len = end_ptr - partial_name_copy;
229 memcpy(containing_part, partial_name_copy, len);
230 containing_part[len] = '\0';
231 }
232 // Push end_ptr past the final "/" and set remainder.
233 end_ptr++;
234 strcpy(remainder, end_ptr);
235 }
236
Jim Ingham84a0d332010-07-02 00:45:55 +0000237 // 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 +0000238 // result back into the containing_part:
239
240 if (*partial_name_copy == '~')
241 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000242 size_t resolved_username_len = FileSpec::ResolveUsername(containing_part, containing_part, sizeof (containing_part));
Jim Ingham802f8b02010-06-30 05:02:46 +0000243 // User name doesn't exist, we're not getting any further...
Greg Clayton099c7972010-07-06 16:11:44 +0000244 if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
Jim Ingham802f8b02010-06-30 05:02:46 +0000245 return matches.GetSize();
Jim Ingham802f8b02010-06-30 05:02:46 +0000246 }
247
248 // Okay, containing_part is now the directory we want to open and look for files:
249
250 DIR *dir_stream;
251
252 dir_stream = opendir(containing_part);
253 if (dir_stream == NULL)
254 return matches.GetSize();
255
256 struct dirent *dirent_buf;
257
258 size_t baselen = end_ptr - partial_name_copy;
259
260 while ((dirent_buf = readdir(dir_stream)) != NULL)
261 {
262 char *name = dirent_buf->d_name;
263
264 // Omit ".", ".." and any . files if the match string doesn't start with .
265 if (name[0] == '.')
266 {
267 if (name[1] == '\0')
268 continue;
269 else if (name[1] == '.' && name[2] == '\0')
270 continue;
271 else if (remainder[0] != '.')
272 continue;
273 }
274
Jim Ingham84a0d332010-07-02 00:45:55 +0000275 // If we found a directory, we put a "/" at the end of the name.
276
Jim Ingham802f8b02010-06-30 05:02:46 +0000277 if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name)
278 {
279 if (strlen(name) + baselen >= PATH_MAX)
280 continue;
281
282 strcpy(end_ptr, name);
283
284 bool isa_directory = false;
285 if (dirent_buf->d_type & DT_DIR)
286 isa_directory = true;
287 else if (dirent_buf->d_type & DT_LNK)
288 {
289 struct stat stat_buf;
290 if ((stat(partial_name_copy, &stat_buf) == 0) && (stat_buf.st_mode & S_IFDIR))
291 isa_directory = true;
292 }
293
294 if (isa_directory)
295 {
296 saw_directory = true;
297 size_t len = strlen(partial_name_copy);
298 partial_name_copy[len] = '/';
299 partial_name_copy[len + 1] = '\0';
300 }
301 if (only_directories && !isa_directory)
302 continue;
303 matches.AppendString(partial_name_copy);
304 }
305 }
306
307 return matches.GetSize();
308}
309
310int
311CommandCompletions::DiskFiles
312(
313 CommandInterpreter &interpreter,
314 const char *partial_file_name,
315 int match_start_point,
316 int max_return_elements,
317 SearchFilter *searcher,
318 bool &word_complete,
319 StringList &matches
320)
321{
322
323 int ret_val = DiskFilesOrDirectories (partial_file_name,
324 false,
325 word_complete,
326 matches);
327 word_complete = !word_complete;
328 return ret_val;
329}
330
331int
332CommandCompletions::DiskDirectories
333(
334 CommandInterpreter &interpreter,
335 const char *partial_file_name,
336 int match_start_point,
337 int max_return_elements,
338 SearchFilter *searcher,
339 bool &word_complete,
340 StringList &matches
341)
342{
343 int ret_val = DiskFilesOrDirectories (partial_file_name,
344 true,
345 word_complete,
346 matches);
347 word_complete = false;
348 return ret_val;
349}
350
Chris Lattner24943d22010-06-08 16:52:24 +0000351int
Greg Clayton63094e02010-06-23 01:19:29 +0000352CommandCompletions::Modules
353(
354 CommandInterpreter &interpreter,
355 const char *partial_file_name,
356 int match_start_point,
357 int max_return_elements,
358 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +0000359 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000360 StringList &matches
361)
Chris Lattner24943d22010-06-08 16:52:24 +0000362{
Jim Ingham802f8b02010-06-30 05:02:46 +0000363 word_complete = true;
Greg Clayton63094e02010-06-23 01:19:29 +0000364 ModuleCompleter completer (interpreter,
365 partial_file_name,
366 match_start_point,
367 max_return_elements,
368 matches);
369
Chris Lattner24943d22010-06-08 16:52:24 +0000370 if (searcher == NULL)
371 {
Jim Inghamc8332952010-08-26 21:32:51 +0000372 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000373 SearchFilter null_searcher (target_sp);
374 completer.DoCompletion (&null_searcher);
375 }
376 else
377 {
378 completer.DoCompletion (searcher);
379 }
380 return matches.GetSize();
381}
382
383int
Greg Clayton63094e02010-06-23 01:19:29 +0000384CommandCompletions::Symbols
385(
386 CommandInterpreter &interpreter,
387 const char *partial_file_name,
388 int match_start_point,
389 int max_return_elements,
390 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +0000391 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000392 StringList &matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000393{
Jim Ingham802f8b02010-06-30 05:02:46 +0000394 word_complete = true;
Greg Clayton63094e02010-06-23 01:19:29 +0000395 SymbolCompleter completer (interpreter,
396 partial_file_name,
397 match_start_point,
398 max_return_elements,
399 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000400
401 if (searcher == NULL)
402 {
Jim Inghamc8332952010-08-26 21:32:51 +0000403 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000404 SearchFilter null_searcher (target_sp);
405 completer.DoCompletion (&null_searcher);
406 }
407 else
408 {
409 completer.DoCompletion (searcher);
410 }
411 return matches.GetSize();
412}
413
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000414int
415CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
416 const char *partial_setting_name,
417 int match_start_point,
418 int max_return_elements,
419 SearchFilter *searcher,
420 bool &word_complete,
421 StringList &matches)
422{
423 lldb::UserSettingsControllerSP root_settings = Debugger::GetSettingsController();
424 Args partial_setting_name_pieces = UserSettingsController::BreakNameIntoPieces (partial_setting_name);
425
426 return UserSettingsController::CompleteSettingsNames (root_settings,
427 partial_setting_name_pieces,
428 word_complete,
429 matches);
430
431 //return matches.GetSize();
432}
433
Greg Clayton63094e02010-06-23 01:19:29 +0000434CommandCompletions::Completer::Completer
435(
436 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000437 const char *completion_str,
438 int match_start_point,
439 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000440 StringList &matches
441) :
Greg Clayton63094e02010-06-23 01:19:29 +0000442 m_interpreter (interpreter),
Chris Lattner24943d22010-06-08 16:52:24 +0000443 m_completion_str (completion_str),
444 m_match_start_point (match_start_point),
445 m_max_return_elements (max_return_elements),
Chris Lattner24943d22010-06-08 16:52:24 +0000446 m_matches (matches)
447{
448}
449
450CommandCompletions::Completer::~Completer ()
451{
452
453}
454
455//----------------------------------------------------------------------
456// SourceFileCompleter
457//----------------------------------------------------------------------
458
Greg Clayton63094e02010-06-23 01:19:29 +0000459CommandCompletions::SourceFileCompleter::SourceFileCompleter
460(
461 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000462 bool include_support_files,
463 const char *completion_str,
464 int match_start_point,
465 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000466 StringList &matches
467) :
Greg Clayton63094e02010-06-23 01:19:29 +0000468 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner24943d22010-06-08 16:52:24 +0000469 m_include_support_files (include_support_files),
470 m_matching_files()
471{
Greg Clayton537a7a82010-10-20 20:54:39 +0000472 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000473 m_file_name = partial_spec.GetFilename().GetCString();
474 m_dir_name = partial_spec.GetDirectory().GetCString();
475}
476
477Searcher::Depth
478CommandCompletions::SourceFileCompleter::GetDepth()
479{
480 return eDepthCompUnit;
481}
482
483Searcher::CallbackReturn
484CommandCompletions::SourceFileCompleter::SearchCallback (
485 SearchFilter &filter,
486 SymbolContext &context,
487 Address *addr,
488 bool complete
489)
490{
491 if (context.comp_unit != NULL)
492 {
493 if (m_include_support_files)
494 {
495 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
496 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
497 {
498 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
499 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
500 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
501 bool match = false;
502 if (m_file_name && sfile_file_name
503 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
504 match = true;
505 if (match && m_dir_name && sfile_dir_name
506 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
507 match = false;
508
509 if (match)
510 {
511 m_matching_files.AppendIfUnique(sfile_spec);
512 }
513 }
514
515 }
516 else
517 {
518 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
519 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
520
521 bool match = false;
522 if (m_file_name && cur_file_name
523 && strstr (cur_file_name, m_file_name) == cur_file_name)
524 match = true;
525
526 if (match && m_dir_name && cur_dir_name
527 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
528 match = false;
529
530 if (match)
531 {
532 m_matching_files.AppendIfUnique(context.comp_unit);
533 }
534 }
535 }
536 return Searcher::eCallbackReturnContinue;
537}
538
539size_t
540CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
541{
542 filter->Search (*this);
543 // Now convert the filelist to completions:
544 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
545 {
546 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
547 }
548 return m_matches.GetSize();
549
550}
551
552//----------------------------------------------------------------------
553// SymbolCompleter
554//----------------------------------------------------------------------
555
556static bool
557regex_chars (const char comp)
558{
559 if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
560 return true;
561 else
562 return false;
563}
Greg Clayton63094e02010-06-23 01:19:29 +0000564CommandCompletions::SymbolCompleter::SymbolCompleter
565(
566 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000567 const char *completion_str,
568 int match_start_point,
569 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000570 StringList &matches
571) :
Greg Clayton63094e02010-06-23 01:19:29 +0000572 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000573{
574 std::string regex_str ("^");
575 regex_str.append(completion_str);
576 regex_str.append(".*");
577 std::string::iterator pos;
578
579 pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
580 while (pos < regex_str.end()) {
581 pos = regex_str.insert(pos, '\\');
582 pos += 2;
583 pos = find_if(pos, regex_str.end(), regex_chars);
584 }
585 m_regex.Compile(regex_str.c_str());
586}
587
588Searcher::Depth
589CommandCompletions::SymbolCompleter::GetDepth()
590{
591 return eDepthModule;
592}
593
594Searcher::CallbackReturn
595CommandCompletions::SymbolCompleter::SearchCallback (
596 SearchFilter &filter,
597 SymbolContext &context,
598 Address *addr,
599 bool complete
600)
601{
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000602 if (context.module_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000603 {
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000604 SymbolContextList sc_list;
605 const bool include_symbols = true;
606 const bool append = true;
607 context.module_sp->FindFunctions (m_regex, include_symbols, append, sc_list);
Chris Lattner24943d22010-06-08 16:52:24 +0000608
609 SymbolContext sc;
610 // Now add the functions & symbols to the list - only add if unique:
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000611 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000612 {
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000613 if (sc_list.GetContextAtIndex(i, sc))
Chris Lattner24943d22010-06-08 16:52:24 +0000614 {
615 if (sc.function)
616 {
617 m_match_set.insert (sc.function->GetMangled().GetDemangledName());
618 }
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000619 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
Chris Lattner24943d22010-06-08 16:52:24 +0000620 {
621 m_match_set.insert (sc.symbol->GetMangled().GetDemangledName());
622 }
623 }
624 }
625 }
626 return Searcher::eCallbackReturnContinue;
627}
628
629size_t
630CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
631{
632 filter->Search (*this);
633 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
634 for (pos = m_match_set.begin(); pos != end; pos++)
635 m_matches.AppendString((*pos).GetCString());
636
637 return m_matches.GetSize();
638}
639
640//----------------------------------------------------------------------
641// ModuleCompleter
642//----------------------------------------------------------------------
Greg Clayton63094e02010-06-23 01:19:29 +0000643CommandCompletions::ModuleCompleter::ModuleCompleter
644(
645 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000646 const char *completion_str,
647 int match_start_point,
648 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000649 StringList &matches
650) :
Greg Clayton63094e02010-06-23 01:19:29 +0000651 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000652{
Greg Clayton537a7a82010-10-20 20:54:39 +0000653 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000654 m_file_name = partial_spec.GetFilename().GetCString();
655 m_dir_name = partial_spec.GetDirectory().GetCString();
656}
657
658Searcher::Depth
659CommandCompletions::ModuleCompleter::GetDepth()
660{
661 return eDepthModule;
662}
663
664Searcher::CallbackReturn
665CommandCompletions::ModuleCompleter::SearchCallback (
666 SearchFilter &filter,
667 SymbolContext &context,
668 Address *addr,
669 bool complete
670)
671{
672 if (context.module_sp != NULL)
673 {
674 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
675 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
676
677 bool match = false;
678 if (m_file_name && cur_file_name
679 && strstr (cur_file_name, m_file_name) == cur_file_name)
680 match = true;
681
682 if (match && m_dir_name && cur_dir_name
683 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
684 match = false;
685
686 if (match)
687 {
688 m_matches.AppendString (cur_file_name);
689 }
690 }
691 return Searcher::eCallbackReturnContinue;
692}
693
694size_t
695CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
696{
697 filter->Search (*this);
698 return m_matches.GetSize();
699}