blob: 5698b28c958f5c2f353b903d4d23bd89c27c82e5 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Options.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
Jim Ingham84cdc152010-06-15 19:49:27 +000010#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000011
12// C Includes
13// C++ Includes
14#include <bitset>
15
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Interpreter/CommandObject.h"
19#include "lldb/Interpreter/CommandReturnObject.h"
20#include "lldb/Interpreter/CommandCompletions.h"
21#include "lldb/Interpreter/CommandInterpreter.h"
22#include "lldb/Core/StreamString.h"
23#include "lldb/Target/Target.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28//-------------------------------------------------------------------------
29// Options
30//-------------------------------------------------------------------------
31Options::Options () :
32 m_getopt_table ()
33{
Jim Ingham34e9a982010-06-15 18:47:14 +000034 BuildValidOptionSets();
Chris Lattner24943d22010-06-08 16:52:24 +000035}
36
37Options::~Options ()
38{
39}
40
41
42void
43Options::ResetOptionValues ()
44{
45 m_seen_options.clear();
46}
47
48void
49Options::OptionSeen (int option_idx)
50{
51 m_seen_options.insert ((char) option_idx);
52}
53
54// Returns true is set_a is a subset of set_b; Otherwise returns false.
55
56bool
57Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
58{
59 bool is_a_subset = true;
60 OptionSet::const_iterator pos_a;
61 OptionSet::const_iterator pos_b;
62
63 // set_a is a subset of set_b if every member of set_a is also a member of set_b
64
65 for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
66 {
67 pos_b = set_b.find(*pos_a);
68 if (pos_b == set_b.end())
69 is_a_subset = false;
70 }
71
72 return is_a_subset;
73}
74
75// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
76
77size_t
78Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
79{
80 size_t num_diffs = 0;
81 OptionSet::const_iterator pos_a;
82 OptionSet::const_iterator pos_b;
83
84 for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
85 {
86 pos_b = set_b.find(*pos_a);
87 if (pos_b == set_b.end())
88 {
89 ++num_diffs;
90 diffs.insert(*pos_a);
91 }
92 }
93
94 return num_diffs;
95}
96
97// Returns the union of set_a and set_b. Does not put duplicate members into the union.
98
99void
100Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
101{
102 OptionSet::const_iterator pos;
103 OptionSet::iterator pos_union;
104
105 // Put all the elements of set_a into the union.
106
107 for (pos = set_a.begin(); pos != set_a.end(); ++pos)
108 union_set.insert(*pos);
109
110 // Put all the elements of set_b that are not already there into the union.
111 for (pos = set_b.begin(); pos != set_b.end(); ++pos)
112 {
113 pos_union = union_set.find(*pos);
114 if (pos_union == union_set.end())
115 union_set.insert(*pos);
116 }
117}
118
119bool
120Options::VerifyOptions (CommandReturnObject &result)
121{
122 bool options_are_valid = false;
123
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000124 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000125 if (num_levels)
126 {
127 for (int i = 0; i < num_levels && !options_are_valid; ++i)
128 {
129 // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i]
130 // (i.e. all the required options at this level are a subset of m_seen_options); AND
131 // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
132 // m_seen_options are in the set of optional options at this level.
133
134 // Check to see if all of m_required_options[i] are a subset of m_seen_options
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000135 if (IsASubset (GetRequiredOptions()[i], m_seen_options))
Chris Lattner24943d22010-06-08 16:52:24 +0000136 {
137 // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
138 OptionSet remaining_options;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000139 OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000140 // Check to see if remaining_options is a subset of m_optional_options[i]
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000141 if (IsASubset (remaining_options, GetOptionalOptions()[i]))
Chris Lattner24943d22010-06-08 16:52:24 +0000142 options_are_valid = true;
143 }
144 }
145 }
146 else
147 {
148 options_are_valid = true;
149 }
150
151 if (options_are_valid)
152 {
153 result.SetStatus (eReturnStatusSuccessFinishNoResult);
154 }
155 else
156 {
157 result.AppendError ("invalid combination of options for the given command");
158 result.SetStatus (eReturnStatusFailed);
159 }
160
161 return options_are_valid;
162}
163
Jim Ingham34e9a982010-06-15 18:47:14 +0000164// This is called in the Options constructor, though we could call it lazily if that ends up being
165// a performance problem.
166
Chris Lattner24943d22010-06-08 16:52:24 +0000167void
168Options::BuildValidOptionSets ()
169{
170 // Check to see if we already did this.
171 if (m_required_options.size() != 0)
172 return;
173
174 // Check to see if there are any options.
175 int num_options = NumCommandOptions ();
176 if (num_options == 0)
177 return;
178
179 const lldb::OptionDefinition *full_options_table = GetDefinitions();
Chris Lattner24943d22010-06-08 16:52:24 +0000180 m_required_options.resize(1);
181 m_optional_options.resize(1);
Jim Ingham34e9a982010-06-15 18:47:14 +0000182
183 // First count the number of option sets we've got. Ignore LLDB_ALL_OPTION_SETS...
184
185 uint32_t num_option_sets = 0;
186
187 for (int i = 0; i < num_options; i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000188 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000189 uint32_t this_usage_mask = full_options_table[i].usage_mask;
190 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000191 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000192 if (num_option_sets == 0)
193 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000194 }
195 else
196 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000197 for (int j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
198 {
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000199 if (this_usage_mask & (1 << j))
Jim Ingham34e9a982010-06-15 18:47:14 +0000200 {
201 if (num_option_sets <= j)
202 num_option_sets = j + 1;
203 }
204 }
Chris Lattner24943d22010-06-08 16:52:24 +0000205 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000206 }
Chris Lattner24943d22010-06-08 16:52:24 +0000207
Jim Ingham34e9a982010-06-15 18:47:14 +0000208 if (num_option_sets > 0)
209 {
210 m_required_options.resize(num_option_sets);
211 m_optional_options.resize(num_option_sets);
212
213 for (int i = 0; i < num_options; ++i)
214 {
215 for (int j = 0; j < num_option_sets; j++)
216 {
217 if (full_options_table[i].usage_mask & 1 << j)
218 {
219 if (full_options_table[i].required)
220 m_required_options[j].insert(full_options_table[i].short_option);
221 else
222 m_optional_options[j].insert(full_options_table[i].short_option);
223 }
224 }
225 }
Chris Lattner24943d22010-06-08 16:52:24 +0000226 }
227}
228
229uint32_t
230Options::NumCommandOptions ()
231{
232 const lldb::OptionDefinition *full_options_table = GetDefinitions ();
Jim Ingham34e9a982010-06-15 18:47:14 +0000233 if (full_options_table == NULL)
234 return 0;
235
Chris Lattner24943d22010-06-08 16:52:24 +0000236 int i = 0;
237
238 if (full_options_table != NULL)
239 {
240 while (full_options_table[i].long_option != NULL)
241 ++i;
242 }
243
244 return i;
245}
246
247struct option *
248Options::GetLongOptions ()
249{
250 // Check to see if this has already been done.
251 if (m_getopt_table.empty())
252 {
253 // Check to see if there are any options.
254 const uint32_t num_options = NumCommandOptions();
255 if (num_options == 0)
256 return NULL;
257
258 uint32_t i;
259 uint32_t j;
260 const lldb::OptionDefinition *full_options_table = GetDefinitions();
261
262 std::bitset<256> option_seen;
263
264 m_getopt_table.resize(num_options + 1);
265 for (i = 0, j = 0; i < num_options; ++i)
266 {
267 char short_opt = full_options_table[i].short_option;
268
269 if (option_seen.test(short_opt) == false)
270 {
271 m_getopt_table[j].name = full_options_table[i].long_option;
272 m_getopt_table[j].has_arg = full_options_table[i].option_has_arg;
273 m_getopt_table[j].flag = NULL;
274 m_getopt_table[j].val = full_options_table[i].short_option;
275 option_seen.set(short_opt);
276 ++j;
277 }
278 }
279
280 //getopt_long requires a NULL final entry in the table:
281
282 m_getopt_table[j].name = NULL;
283 m_getopt_table[j].has_arg = 0;
284 m_getopt_table[j].flag = NULL;
285 m_getopt_table[j].val = 0;
286 }
287
288 return m_getopt_table.data();
289}
290
291
292// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
293// a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on
294// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces,
295// tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each
296// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
297
298
299void
300Options::OutputFormattedUsageText
301(
302 Stream &strm,
303 const char *text,
304 uint32_t output_max_columns
305)
306{
307 int len = strlen (text);
308
309 // Will it all fit on one line?
310
311 if ((len + strm.GetIndentLevel()) < output_max_columns)
312 {
313 // Output it as a single line.
314 strm.Indent (text);
315 strm.EOL();
316 }
317 else
318 {
319 // We need to break it up into multiple lines.
320
321 int text_width = output_max_columns - strm.GetIndentLevel() - 1;
322 int start = 0;
323 int end = start;
324 int final_end = strlen (text);
325 int sub_len;
326
327 while (end < final_end)
328 {
329 // Don't start the 'text' on a space, since we're already outputting the indentation.
330 while ((start < final_end) && (text[start] == ' '))
331 start++;
332
333 end = start + text_width;
334 if (end > final_end)
335 end = final_end;
336 else
337 {
338 // If we're not at the end of the text, make sure we break the line on white space.
339 while (end > start
340 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
341 end--;
342 }
343
344 sub_len = end - start;
345 if (start != 0)
346 strm.EOL();
347 strm.Indent();
348 assert (start < final_end);
349 assert (start + sub_len <= final_end);
350 strm.Write(text + start, sub_len);
351 start = end + 1;
352 }
353 strm.EOL();
354 }
355}
356
357void
358Options::GenerateOptionUsage
359(
360 Stream &strm,
361 CommandObject *cmd,
362 const char *program_name)
363{
364 uint32_t screen_width = 80;
365 const lldb::OptionDefinition *full_options_table = GetDefinitions();
366 const uint32_t save_indent_level = strm.GetIndentLevel();
367 const char *name;
368
369 if (cmd)
370 name = cmd->GetCommandName();
371 else
372 name = program_name;
373
374 strm.PutCString ("\nCommand Options Usage:\n");
375
376 strm.IndentMore(2);
377
378 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
379 // <cmd> [options-for-level-1]
380 // etc.
381
Chris Lattner24943d22010-06-08 16:52:24 +0000382 const uint32_t num_options = NumCommandOptions();
Jim Ingham34e9a982010-06-15 18:47:14 +0000383 if (num_options == 0)
384 return;
385
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000386 int num_option_sets = GetRequiredOptions().size();
Jim Ingham34e9a982010-06-15 18:47:14 +0000387
Chris Lattner24943d22010-06-08 16:52:24 +0000388 uint32_t i;
Jim Ingham34e9a982010-06-15 18:47:14 +0000389
390 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
Chris Lattner24943d22010-06-08 16:52:24 +0000391 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000392 uint32_t opt_set_mask;
393
394 opt_set_mask = 1 << opt_set;
395 if (opt_set > 0)
396 strm.Printf ("\n");
397 strm.Indent (name);
398
399 for (i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000400 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000401 if (full_options_table[i].usage_mask & opt_set_mask)
Chris Lattner24943d22010-06-08 16:52:24 +0000402 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000403 // Add current option to the end of out_stream.
Chris Lattner24943d22010-06-08 16:52:24 +0000404
Jim Ingham34e9a982010-06-15 18:47:14 +0000405 if (full_options_table[i].required)
406 {
407 if (full_options_table[i].option_has_arg == required_argument)
408 {
409 strm.Printf (" -%c %s",
410 full_options_table[i].short_option,
411 full_options_table[i].argument_name);
412 }
413 else if (full_options_table[i].option_has_arg == optional_argument)
414 {
415 strm.Printf (" -%c [%s]",
416 full_options_table[i].short_option,
417 full_options_table[i].argument_name);
418 }
419 else
420 strm.Printf (" -%c", full_options_table[i].short_option);
421 }
422 else
423 {
424 if (full_options_table[i].option_has_arg == required_argument)
425 strm.Printf (" [-%c %s]", full_options_table[i].short_option,
426 full_options_table[i].argument_name);
427 else if (full_options_table[i].option_has_arg == optional_argument)
428 strm.Printf (" [-%c [%s]]", full_options_table[i].short_option,
429 full_options_table[i].argument_name);
430 else
431 strm.Printf (" [-%c]", full_options_table[i].short_option);
432 }
Chris Lattner24943d22010-06-08 16:52:24 +0000433 }
Chris Lattner24943d22010-06-08 16:52:24 +0000434 }
435 }
Chris Lattner24943d22010-06-08 16:52:24 +0000436 strm.Printf ("\n\n");
437
438 // Now print out all the detailed information about the various options: long form, short form and help text:
439 // -- long_name <argument>
440 // - short <argument>
441 // help text
442
443 // This variable is used to keep track of which options' info we've printed out, because some options can be in
444 // more than one usage level, but we only want to print the long form of its information once.
445
446 OptionSet options_seen;
447 OptionSet::iterator pos;
448 strm.IndentMore (5);
449
450 int first_option_printed = 1;
451 for (i = 0; i < num_options; ++i)
452 {
453 // Only print out this option if we haven't already seen it.
454 pos = options_seen.find (full_options_table[i].short_option);
455 if (pos == options_seen.end())
456 {
457 // Put a newline separation between arguments
458 if (first_option_printed)
459 first_option_printed = 0;
460 else
461 strm.EOL();
462
463 options_seen.insert (full_options_table[i].short_option);
464 strm.Indent ();
465 strm.Printf ("-%c ", full_options_table[i].short_option);
466 if (full_options_table[i].argument_name != NULL)
467 strm.PutCString(full_options_table[i].argument_name);
468 strm.EOL();
469 strm.Indent ();
470 strm.Printf ("--%s ", full_options_table[i].long_option);
471 if (full_options_table[i].argument_name != NULL)
472 strm.PutCString(full_options_table[i].argument_name);
473 strm.EOL();
474
475 strm.IndentMore (5);
476
477 if (full_options_table[i].usage_text)
478 OutputFormattedUsageText (strm,
479 full_options_table[i].usage_text,
480 screen_width);
481 if (full_options_table[i].enum_values != NULL)
482 {
483 strm.Indent ();
484 strm.Printf("Values: ");
485 for (int j = 0; full_options_table[i].enum_values[j].string_value != NULL; j++)
486 {
487 if (j == 0)
488 strm.Printf("%s", full_options_table[i].enum_values[j].string_value);
489 else
490 strm.Printf(" | %s", full_options_table[i].enum_values[j].string_value);
491 }
492 strm.EOL();
493 }
494 strm.IndentLess (5);
495 }
496 }
497
498 // Restore the indent level
499 strm.SetIndentLevel (save_indent_level);
500}
501
502// This function is called when we have been given a potentially incomplete set of
503// options, such as when an alias has been defined (more options might be added at
504// at the time the alias is invoked). We need to verify that the options in the set
505// m_seen_options are all part of a set that may be used together, but m_seen_options
506// may be missing some of the "required" options.
507
508bool
509Options::VerifyPartialOptions (CommandReturnObject &result)
510{
511 bool options_are_valid = false;
512
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000513 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000514 if (num_levels)
515 {
516 for (int i = 0; i < num_levels && !options_are_valid; ++i)
517 {
518 // In this case we are treating all options as optional rather than required.
519 // Therefore a set of options is correct if m_seen_options is a subset of the
520 // union of m_required_options and m_optional_options.
521 OptionSet union_set;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000522 OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
Chris Lattner24943d22010-06-08 16:52:24 +0000523 if (IsASubset (m_seen_options, union_set))
524 options_are_valid = true;
525 }
526 }
527
528 return options_are_valid;
529}
530
531bool
532Options::HandleOptionCompletion
533(
Greg Clayton63094e02010-06-23 01:19:29 +0000534 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000535 Args &input,
536 OptionElementVector &opt_element_vector,
537 int cursor_index,
538 int char_pos,
539 int match_start_point,
540 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000541 lldb_private::StringList &matches
542)
543{
544 // For now we just scan the completions to see if the cursor position is in
545 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
546 // In the future we can use completion to validate options as well if we want.
547
548 const OptionDefinition *opt_defs = GetDefinitions();
549
550 std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
551 cur_opt_std_str.erase(char_pos);
552 const char *cur_opt_str = cur_opt_std_str.c_str();
553
554 for (int i = 0; i < opt_element_vector.size(); i++)
555 {
556 int opt_pos = opt_element_vector[i].opt_pos;
557 int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
558 int opt_defs_index = opt_element_vector[i].opt_defs_index;
559 if (opt_pos == cursor_index)
560 {
561 // We're completing the option itself.
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000562
563 if (opt_defs_index == OptionArgElement::eBareDash)
564 {
565 // We're completing a bare dash. That means all options are open.
566 // FIXME: We should scan the other options provided and only complete options
567 // within the option group they belong to.
568 char opt_str[3] = {'-', 'a', '\0'};
569
570 for (int i = 0 ; opt_defs[i].short_option != 0 ; i++)
571 {
572 opt_str[1] = opt_defs[i].short_option;
573 matches.AppendString (opt_str);
574 }
575 return true;
576 }
577 else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
578 {
579 std::string full_name ("--");
580 for (int i = 0 ; opt_defs[i].short_option != 0 ; i++)
581 {
582 full_name.erase(full_name.begin() + 2, full_name.end());
583 full_name.append (opt_defs[i].long_option);
584 matches.AppendString (full_name.c_str());
585 }
586 return true;
587 }
588 else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
Chris Lattner24943d22010-06-08 16:52:24 +0000589 {
590 // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
591 // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
592 // The string so the upper level code will know this is a full match and add the " ".
593 if (cur_opt_str && strlen (cur_opt_str) > 2
594 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
595 && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
596 {
597 std::string full_name ("--");
598 full_name.append (opt_defs[opt_defs_index].long_option);
599 matches.AppendString(full_name.c_str());
600 return true;
601 }
602 else
603 {
604 matches.AppendString(input.GetArgumentAtIndex(cursor_index));
605 return true;
606 }
607 }
608 else
609 {
610 // FIXME - not handling wrong options yet:
611 // Check to see if they are writing a long option & complete it.
612 // I think we will only get in here if the long option table has two elements
613 // that are not unique up to this point. getopt_long does shortest unique match
614 // for long options already.
615
616 if (cur_opt_str && strlen (cur_opt_str) > 2
617 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
618 {
619 for (int i = 0 ; opt_defs[i].short_option != 0 ; i++)
620 {
621 if (strstr(opt_defs[i].long_option, cur_opt_str + 2) == opt_defs[i].long_option)
622 {
623 std::string full_name ("--");
624 full_name.append (opt_defs[i].long_option);
625 // The options definitions table has duplicates because of the
626 // way the grouping information is stored, so only add once.
627 bool duplicate = false;
628 for (int j = 0; j < matches.GetSize(); j++)
629 {
630 if (matches.GetStringAtIndex(j) == full_name)
631 {
632 duplicate = true;
633 break;
634 }
635 }
636 if (!duplicate)
637 matches.AppendString(full_name.c_str());
638 }
639 }
640 }
641 return true;
642 }
643
644
645 }
646 else if (opt_arg_pos == cursor_index)
647 {
648 // Okay the cursor is on the completion of an argument.
649 // See if it has a completion, otherwise return no matches.
650
651 if (opt_defs_index != -1)
652 {
Greg Clayton63094e02010-06-23 01:19:29 +0000653 HandleOptionArgumentCompletion (interpreter,
654 input,
655 cursor_index,
656 strlen (input.GetArgumentAtIndex(cursor_index)),
657 opt_element_vector,
658 i,
659 match_start_point,
660 max_return_elements,
661 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000662 return true;
663 }
664 else
665 {
666 // No completion callback means no completions...
667 return true;
668 }
669
670 }
671 else
672 {
673 // Not the last element, keep going.
674 continue;
675 }
676 }
677 return false;
678}
679
680bool
681Options::HandleOptionArgumentCompletion
682(
Greg Clayton63094e02010-06-23 01:19:29 +0000683 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000684 Args &input,
685 int cursor_index,
686 int char_pos,
687 OptionElementVector &opt_element_vector,
688 int opt_element_index,
689 int match_start_point,
690 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000691 lldb_private::StringList &matches
692)
693{
694 const OptionDefinition *opt_defs = GetDefinitions();
695 std::auto_ptr<SearchFilter> filter_ap;
696
697 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
698 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
699
700 // See if this is an enumeration type option, and if so complete it here:
701
702 OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
703 if (enum_values != NULL)
704 {
705 bool return_value = false;
706 std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
707 for (int i = 0; enum_values[i].string_value != NULL; i++)
708 {
709 if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
710 {
711 matches.AppendString (enum_values[i].string_value);
712 return_value = true;
713 }
714 }
715 return return_value;
716 }
717
718 // If this is a source file or symbol type completion, and there is a
719 // -shlib option somewhere in the supplied arguments, then make a search filter
720 // for that shared library.
721 // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
722
723 uint32_t completion_mask = opt_defs[opt_defs_index].completionType;
724 if (completion_mask & CommandCompletions::eSourceFileCompletion
725 || completion_mask & CommandCompletions::eSymbolCompletion)
726 {
727 for (int i = 0; i < opt_element_vector.size(); i++)
728 {
729 int cur_defs_index = opt_element_vector[i].opt_defs_index;
730 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
731 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
732
733 // If this is the "shlib" option and there was an argument provided,
734 // restrict it to that shared library.
735 if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
736 {
737 const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
738 if (module_name)
739 {
740 FileSpec module_spec(module_name);
Greg Clayton63094e02010-06-23 01:19:29 +0000741 lldb::TargetSP target_sp = interpreter.GetDebugger().GetCurrentTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000742 // Search filters require a target...
743 if (target_sp != NULL)
744 filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
745 }
746 break;
747 }
748 }
749 }
750
Greg Clayton63094e02010-06-23 01:19:29 +0000751 return CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
752 completion_mask,
753 input.GetArgumentAtIndex (opt_arg_pos),
754 match_start_point,
755 max_return_elements,
756 filter_ap.get(),
757 matches);
758
Chris Lattner24943d22010-06-08 16:52:24 +0000759}