Options.cpp revision 987c7ebe1daa425ba7abfa9643800e3237146fc0
1//===-- 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
10#include "lldb/Interpreter/Options.h"
11
12// C Includes
13// C++ Includes
14#include <algorithm>
15#include <bitset>
16#include <set>
17
18// Other libraries and framework includes
19// Project includes
20#include "lldb/Interpreter/CommandObject.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
22#include "lldb/Interpreter/CommandCompletions.h"
23#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Core/StreamString.h"
25#include "lldb/Target/Target.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30//-------------------------------------------------------------------------
31// Options
32//-------------------------------------------------------------------------
33Options::Options (CommandInterpreter &interpreter) :
34    m_interpreter (interpreter),
35    m_getopt_table ()
36{
37    BuildValidOptionSets();
38}
39
40Options::~Options ()
41{
42}
43
44void
45Options::NotifyOptionParsingStarting ()
46{
47    m_seen_options.clear();
48    // Let the subclass reset its option values
49    OptionParsingStarting ();
50}
51
52Error
53Options::NotifyOptionParsingFinished ()
54{
55    return OptionParsingFinished ();
56}
57
58void
59Options::OptionSeen (int option_idx)
60{
61    m_seen_options.insert ((char) option_idx);
62}
63
64// Returns true is set_a is a subset of set_b;  Otherwise returns false.
65
66bool
67Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
68{
69    bool is_a_subset = true;
70    OptionSet::const_iterator pos_a;
71    OptionSet::const_iterator pos_b;
72
73    // set_a is a subset of set_b if every member of set_a is also a member of set_b
74
75    for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
76    {
77        pos_b = set_b.find(*pos_a);
78        if (pos_b == set_b.end())
79            is_a_subset = false;
80    }
81
82    return is_a_subset;
83}
84
85// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
86
87size_t
88Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
89{
90    size_t num_diffs = 0;
91    OptionSet::const_iterator pos_a;
92    OptionSet::const_iterator pos_b;
93
94    for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
95    {
96        pos_b = set_b.find(*pos_a);
97        if (pos_b == set_b.end())
98        {
99            ++num_diffs;
100            diffs.insert(*pos_a);
101        }
102    }
103
104    return num_diffs;
105}
106
107// Returns the union of set_a and set_b.  Does not put duplicate members into the union.
108
109void
110Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
111{
112    OptionSet::const_iterator pos;
113    OptionSet::iterator pos_union;
114
115    // Put all the elements of set_a into the union.
116
117    for (pos = set_a.begin(); pos != set_a.end(); ++pos)
118        union_set.insert(*pos);
119
120    // Put all the elements of set_b that are not already there into the union.
121    for (pos = set_b.begin(); pos != set_b.end(); ++pos)
122    {
123        pos_union = union_set.find(*pos);
124        if (pos_union == union_set.end())
125            union_set.insert(*pos);
126    }
127}
128
129bool
130Options::VerifyOptions (CommandReturnObject &result)
131{
132    bool options_are_valid = false;
133
134    int num_levels = GetRequiredOptions().size();
135    if (num_levels)
136    {
137        for (int i = 0; i < num_levels && !options_are_valid; ++i)
138        {
139            // This is the correct set of options if:  1). m_seen_options contains all of m_required_options[i]
140            // (i.e. all the required options at this level are a subset of m_seen_options); AND
141            // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
142            // m_seen_options are in the set of optional options at this level.
143
144            // Check to see if all of m_required_options[i] are a subset of m_seen_options
145            if (IsASubset (GetRequiredOptions()[i], m_seen_options))
146            {
147                // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
148                OptionSet remaining_options;
149                OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options);
150                // Check to see if remaining_options is a subset of m_optional_options[i]
151                if (IsASubset (remaining_options, GetOptionalOptions()[i]))
152                    options_are_valid = true;
153            }
154        }
155    }
156    else
157    {
158        options_are_valid = true;
159    }
160
161    if (options_are_valid)
162    {
163        result.SetStatus (eReturnStatusSuccessFinishNoResult);
164    }
165    else
166    {
167        result.AppendError ("invalid combination of options for the given command");
168        result.SetStatus (eReturnStatusFailed);
169    }
170
171    return options_are_valid;
172}
173
174// This is called in the Options constructor, though we could call it lazily if that ends up being
175// a performance problem.
176
177void
178Options::BuildValidOptionSets ()
179{
180    // Check to see if we already did this.
181    if (m_required_options.size() != 0)
182        return;
183
184    // Check to see if there are any options.
185    int num_options = NumCommandOptions ();
186    if (num_options == 0)
187        return;
188
189    const OptionDefinition *full_options_table = GetDefinitions();
190    m_required_options.resize(1);
191    m_optional_options.resize(1);
192
193    // First count the number of option sets we've got.  Ignore LLDB_ALL_OPTION_SETS...
194
195    uint32_t num_option_sets = 0;
196
197    for (int i = 0; i < num_options; i++)
198    {
199        uint32_t this_usage_mask = full_options_table[i].usage_mask;
200        if (this_usage_mask == LLDB_OPT_SET_ALL)
201        {
202            if (num_option_sets == 0)
203                num_option_sets = 1;
204        }
205        else
206        {
207            for (int j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
208            {
209                if (this_usage_mask & (1 << j))
210                {
211                    if (num_option_sets <= j)
212                        num_option_sets = j + 1;
213                }
214            }
215        }
216    }
217
218    if (num_option_sets > 0)
219    {
220        m_required_options.resize(num_option_sets);
221        m_optional_options.resize(num_option_sets);
222
223        for (int i = 0; i < num_options; ++i)
224        {
225            for (int j = 0; j < num_option_sets; j++)
226            {
227                if (full_options_table[i].usage_mask & 1 << j)
228                {
229                    if (full_options_table[i].required)
230                        m_required_options[j].insert(full_options_table[i].short_option);
231                    else
232                        m_optional_options[j].insert(full_options_table[i].short_option);
233                }
234            }
235        }
236    }
237}
238
239uint32_t
240Options::NumCommandOptions ()
241{
242    const OptionDefinition *full_options_table = GetDefinitions ();
243    if (full_options_table == NULL)
244        return 0;
245
246    int i = 0;
247
248    if (full_options_table != NULL)
249    {
250        while (full_options_table[i].long_option != NULL)
251            ++i;
252    }
253
254    return i;
255}
256
257struct option *
258Options::GetLongOptions ()
259{
260    // Check to see if this has already been done.
261    if (m_getopt_table.empty())
262    {
263        // Check to see if there are any options.
264        const uint32_t num_options = NumCommandOptions();
265        if (num_options == 0)
266            return NULL;
267
268        uint32_t i;
269        uint32_t j;
270        const OptionDefinition *full_options_table = GetDefinitions();
271
272        std::bitset<256> option_seen;
273
274        m_getopt_table.resize(num_options + 1);
275        for (i = 0, j = 0; i < num_options; ++i)
276        {
277            char short_opt = full_options_table[i].short_option;
278
279            if (option_seen.test(short_opt) == false)
280            {
281                m_getopt_table[j].name    = full_options_table[i].long_option;
282                m_getopt_table[j].has_arg = full_options_table[i].option_has_arg;
283                m_getopt_table[j].flag    = NULL;
284                m_getopt_table[j].val     = full_options_table[i].short_option;
285                option_seen.set(short_opt);
286                ++j;
287            }
288        }
289
290        //getopt_long requires a NULL final entry in the table:
291
292        m_getopt_table[j].name    = NULL;
293        m_getopt_table[j].has_arg = 0;
294        m_getopt_table[j].flag    = NULL;
295        m_getopt_table[j].val     = 0;
296    }
297
298    if (m_getopt_table.empty())
299        return NULL;
300
301    return &m_getopt_table.front();
302}
303
304
305// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
306// a string containing 80 spaces; and TEXT, which is the text that is to be output.   It outputs the text, on
307// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line.  It breaks lines on spaces,
308// tabs or newlines, shortening the line if necessary to not break in the middle of a word.  It assumes that each
309// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
310
311
312void
313Options::OutputFormattedUsageText
314(
315    Stream &strm,
316    const char *text,
317    uint32_t output_max_columns
318)
319{
320    int len = strlen (text);
321
322    // Will it all fit on one line?
323
324    if ((len + strm.GetIndentLevel()) < output_max_columns)
325    {
326        // Output it as a single line.
327        strm.Indent (text);
328        strm.EOL();
329    }
330    else
331    {
332        // We need to break it up into multiple lines.
333
334        int text_width = output_max_columns - strm.GetIndentLevel() - 1;
335        int start = 0;
336        int end = start;
337        int final_end = strlen (text);
338        int sub_len;
339
340        while (end < final_end)
341        {
342            // Don't start the 'text' on a space, since we're already outputting the indentation.
343            while ((start < final_end) && (text[start] == ' '))
344                start++;
345
346            end = start + text_width;
347            if (end > final_end)
348                end = final_end;
349            else
350            {
351                // If we're not at the end of the text, make sure we break the line on white space.
352                while (end > start
353                       && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
354                    end--;
355            }
356
357            sub_len = end - start;
358            if (start != 0)
359                strm.EOL();
360            strm.Indent();
361            assert (start < final_end);
362            assert (start + sub_len <= final_end);
363            strm.Write(text + start, sub_len);
364            start = end + 1;
365        }
366        strm.EOL();
367    }
368}
369
370void
371Options::GenerateOptionUsage
372(
373    Stream &strm,
374    CommandObject *cmd
375)
376{
377    const uint32_t screen_width = m_interpreter.GetDebugger().GetTerminalWidth();
378
379    const OptionDefinition *full_options_table = GetDefinitions();
380    const uint32_t save_indent_level = strm.GetIndentLevel();
381    const char *name;
382
383    StreamString arguments_str;
384
385    if (cmd)
386    {
387        name = cmd->GetCommandName();
388        cmd->GetFormattedCommandArguments (arguments_str);
389    }
390    else
391        name = "";
392
393    strm.PutCString ("\nCommand Options Usage:\n");
394
395    strm.IndentMore(2);
396
397    // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
398    //                                                   <cmd> [options-for-level-1]
399    //                                                   etc.
400
401    const uint32_t num_options = NumCommandOptions();
402    if (num_options == 0)
403        return;
404
405    int num_option_sets = GetRequiredOptions().size();
406
407    uint32_t i;
408
409    for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
410    {
411        uint32_t opt_set_mask;
412
413        opt_set_mask = 1 << opt_set;
414        if (opt_set > 0)
415            strm.Printf ("\n");
416        strm.Indent (name);
417
418        // First go through and print all options that take no arguments as
419        // a single string. If a command has "-a" "-b" and "-c", this will show
420        // up as [-abc]
421
422        std::set<char> options;
423        std::set<char>::const_iterator options_pos, options_end;
424        bool first;
425        for (i = 0, first = true; i < num_options; ++i)
426        {
427            if (full_options_table[i].usage_mask & opt_set_mask)
428            {
429                // Add current option to the end of out_stream.
430
431                if (full_options_table[i].required == true &&
432                    full_options_table[i].option_has_arg == no_argument)
433                {
434                    options.insert (full_options_table[i].short_option);
435                }
436            }
437        }
438
439        if (options.empty() == false)
440        {
441            // We have some required options with no arguments
442            strm.PutCString(" -");
443            for (i=0; i<2; ++i)
444                for (options_pos = options.begin(), options_end = options.end();
445                     options_pos != options_end;
446                     ++options_pos)
447                {
448                    if (i==0 && ::isupper (*options_pos))
449                        continue;
450                    if (i==1 && ::islower (*options_pos))
451                        continue;
452                    strm << *options_pos;
453                }
454        }
455
456        for (i = 0, options.clear(); i < num_options; ++i)
457        {
458            if (full_options_table[i].usage_mask & opt_set_mask)
459            {
460                // Add current option to the end of out_stream.
461
462                if (full_options_table[i].required == false &&
463                    full_options_table[i].option_has_arg == no_argument)
464                {
465                    options.insert (full_options_table[i].short_option);
466                }
467            }
468        }
469
470        if (options.empty() == false)
471        {
472            // We have some required options with no arguments
473            strm.PutCString(" [-");
474            for (i=0; i<2; ++i)
475                for (options_pos = options.begin(), options_end = options.end();
476                     options_pos != options_end;
477                     ++options_pos)
478                {
479                    if (i==0 && ::isupper (*options_pos))
480                        continue;
481                    if (i==1 && ::islower (*options_pos))
482                        continue;
483                    strm << *options_pos;
484                }
485            strm.PutChar(']');
486        }
487
488        // First go through and print the required options (list them up front).
489
490        for (i = 0; i < num_options; ++i)
491        {
492            if (full_options_table[i].usage_mask & opt_set_mask)
493            {
494                // Add current option to the end of out_stream.
495                CommandArgumentType arg_type = full_options_table[i].argument_type;
496
497                if (full_options_table[i].required)
498                {
499                    if (full_options_table[i].option_has_arg == required_argument)
500                    {
501                        strm.Printf (" -%c <%s>",
502                                     full_options_table[i].short_option,
503                                     CommandObject::GetArgumentName (arg_type));
504                    }
505                    else if (full_options_table[i].option_has_arg == optional_argument)
506                    {
507                        strm.Printf (" -%c [<%s>]",
508                                     full_options_table[i].short_option,
509                                     CommandObject::GetArgumentName (arg_type));
510                    }
511                }
512            }
513        }
514
515        // Now go through again, and this time only print the optional options.
516
517        for (i = 0; i < num_options; ++i)
518        {
519            if (full_options_table[i].usage_mask & opt_set_mask)
520            {
521                // Add current option to the end of out_stream.
522
523                CommandArgumentType arg_type = full_options_table[i].argument_type;
524
525                if (! full_options_table[i].required)
526                {
527                    if (full_options_table[i].option_has_arg == required_argument)
528                        strm.Printf (" [-%c <%s>]", full_options_table[i].short_option,
529                                     CommandObject::GetArgumentName (arg_type));
530                    else if (full_options_table[i].option_has_arg == optional_argument)
531                        strm.Printf (" [-%c [<%s>]]", full_options_table[i].short_option,
532                                     CommandObject::GetArgumentName (arg_type));
533                }
534            }
535        }
536        if (arguments_str.GetSize() > 0)
537            strm.Printf (" %s", arguments_str.GetData());
538    }
539    strm.Printf ("\n\n");
540
541    // Now print out all the detailed information about the various options:  long form, short form and help text:
542    //   --long_name <argument>  ( -short <argument> )
543    //   help text
544
545    // This variable is used to keep track of which options' info we've printed out, because some options can be in
546    // more than one usage level, but we only want to print the long form of its information once.
547
548    OptionSet options_seen;
549    OptionSet::iterator pos;
550    strm.IndentMore (5);
551
552    std::vector<char> sorted_options;
553
554
555    // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option)
556    // when writing out detailed help for each option.
557
558    for (i = 0; i < num_options; ++i)
559    {
560        pos = options_seen.find (full_options_table[i].short_option);
561        if (pos == options_seen.end())
562        {
563            options_seen.insert (full_options_table[i].short_option);
564            sorted_options.push_back (full_options_table[i].short_option);
565        }
566    }
567
568    std::sort (sorted_options.begin(), sorted_options.end());
569
570    // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option
571    // and write out the detailed help information for that option.
572
573    int first_option_printed = 1;
574    size_t end = sorted_options.size();
575    for (size_t j = 0; j < end; ++j)
576    {
577        char option = sorted_options[j];
578        bool found = false;
579        for (i = 0; i < num_options && !found; ++i)
580        {
581            if (full_options_table[i].short_option == option)
582            {
583                found = true;
584                //Print out the help information for this option.
585
586                // Put a newline separation between arguments
587                if (first_option_printed)
588                    first_option_printed = 0;
589                else
590                    strm.EOL();
591
592                CommandArgumentType arg_type = full_options_table[i].argument_type;
593
594                StreamString arg_name_str;
595                arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type));
596
597                strm.Indent ();
598                strm.Printf ("-%c", full_options_table[i].short_option);
599                if (arg_type != eArgTypeNone)
600                    strm.Printf (" <%s>",  CommandObject::GetArgumentName (arg_type));
601                strm.Printf ("  ( --%s", full_options_table[i].long_option);
602                if (arg_type != eArgTypeNone)
603                    strm.Printf (" <%s>", CommandObject::GetArgumentName (arg_type));
604                strm.PutCString(" )\n");
605
606                strm.IndentMore (5);
607
608                if (full_options_table[i].usage_text)
609                    OutputFormattedUsageText (strm,
610                                              full_options_table[i].usage_text,
611                                              screen_width);
612                if (full_options_table[i].enum_values != NULL)
613                {
614                    strm.Indent ();
615                    strm.Printf("Values: ");
616                    for (int k = 0; full_options_table[i].enum_values[k].string_value != NULL; k++)
617                    {
618                        if (k == 0)
619                            strm.Printf("%s", full_options_table[i].enum_values[k].string_value);
620                        else
621                            strm.Printf(" | %s", full_options_table[i].enum_values[k].string_value);
622                    }
623                    strm.EOL();
624                }
625                strm.IndentLess (5);
626            }
627        }
628    }
629
630    // Restore the indent level
631    strm.SetIndentLevel (save_indent_level);
632}
633
634// This function is called when we have been given a potentially incomplete set of
635// options, such as when an alias has been defined (more options might be added at
636// at the time the alias is invoked).  We need to verify that the options in the set
637// m_seen_options are all part of a set that may be used together, but m_seen_options
638// may be missing some of the "required" options.
639
640bool
641Options::VerifyPartialOptions (CommandReturnObject &result)
642{
643    bool options_are_valid = false;
644
645    int num_levels = GetRequiredOptions().size();
646    if (num_levels)
647      {
648        for (int i = 0; i < num_levels && !options_are_valid; ++i)
649          {
650            // In this case we are treating all options as optional rather than required.
651            // Therefore a set of options is correct if m_seen_options is a subset of the
652            // union of m_required_options and m_optional_options.
653            OptionSet union_set;
654            OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
655            if (IsASubset (m_seen_options, union_set))
656                options_are_valid = true;
657          }
658      }
659
660    return options_are_valid;
661}
662
663bool
664Options::HandleOptionCompletion
665(
666    Args &input,
667    OptionElementVector &opt_element_vector,
668    int cursor_index,
669    int char_pos,
670    int match_start_point,
671    int max_return_elements,
672    bool &word_complete,
673    lldb_private::StringList &matches
674)
675{
676    word_complete = true;
677
678    // For now we just scan the completions to see if the cursor position is in
679    // an option or its argument.  Otherwise we'll call HandleArgumentCompletion.
680    // In the future we can use completion to validate options as well if we want.
681
682    const OptionDefinition *opt_defs = GetDefinitions();
683
684    std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
685    cur_opt_std_str.erase(char_pos);
686    const char *cur_opt_str = cur_opt_std_str.c_str();
687
688    for (int i = 0; i < opt_element_vector.size(); i++)
689    {
690        int opt_pos = opt_element_vector[i].opt_pos;
691        int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
692        int opt_defs_index = opt_element_vector[i].opt_defs_index;
693        if (opt_pos == cursor_index)
694        {
695            // We're completing the option itself.
696
697            if (opt_defs_index == OptionArgElement::eBareDash)
698            {
699                // We're completing a bare dash.  That means all options are open.
700                // FIXME: We should scan the other options provided and only complete options
701                // within the option group they belong to.
702                char opt_str[3] = {'-', 'a', '\0'};
703
704                for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
705                {
706                    opt_str[1] = opt_defs[j].short_option;
707                    matches.AppendString (opt_str);
708                }
709                return true;
710            }
711            else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
712            {
713                std::string full_name ("--");
714                for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
715                {
716                    full_name.erase(full_name.begin() + 2, full_name.end());
717                    full_name.append (opt_defs[j].long_option);
718                    matches.AppendString (full_name.c_str());
719                }
720                return true;
721            }
722            else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
723            {
724                // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
725                // happy with shortest unique string, but it's still a nice thing to do.)  Otherwise return
726                // The string so the upper level code will know this is a full match and add the " ".
727                if (cur_opt_str && strlen (cur_opt_str) > 2
728                    && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
729                    && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
730                {
731                        std::string full_name ("--");
732                        full_name.append (opt_defs[opt_defs_index].long_option);
733                        matches.AppendString(full_name.c_str());
734                        return true;
735                }
736                else
737                {
738                    matches.AppendString(input.GetArgumentAtIndex(cursor_index));
739                    return true;
740                }
741            }
742            else
743            {
744                // FIXME - not handling wrong options yet:
745                // Check to see if they are writing a long option & complete it.
746                // I think we will only get in here if the long option table has two elements
747                // that are not unique up to this point.  getopt_long does shortest unique match
748                // for long options already.
749
750                if (cur_opt_str && strlen (cur_opt_str) > 2
751                    && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
752                {
753                    for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
754                    {
755                        if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option)
756                        {
757                            std::string full_name ("--");
758                            full_name.append (opt_defs[j].long_option);
759                            // The options definitions table has duplicates because of the
760                            // way the grouping information is stored, so only add once.
761                            bool duplicate = false;
762                            for (int k = 0; k < matches.GetSize(); k++)
763                            {
764                                if (matches.GetStringAtIndex(k) == full_name)
765                                {
766                                    duplicate = true;
767                                    break;
768                                }
769                            }
770                            if (!duplicate)
771                                matches.AppendString(full_name.c_str());
772                        }
773                    }
774                }
775                return true;
776            }
777
778
779        }
780        else if (opt_arg_pos == cursor_index)
781        {
782            // Okay the cursor is on the completion of an argument.
783            // See if it has a completion, otherwise return no matches.
784
785            if (opt_defs_index != -1)
786            {
787                HandleOptionArgumentCompletion (input,
788                                                cursor_index,
789                                                strlen (input.GetArgumentAtIndex(cursor_index)),
790                                                opt_element_vector,
791                                                i,
792                                                match_start_point,
793                                                max_return_elements,
794                                                word_complete,
795                                                matches);
796                return true;
797            }
798            else
799            {
800                // No completion callback means no completions...
801                return true;
802            }
803
804        }
805        else
806        {
807            // Not the last element, keep going.
808            continue;
809        }
810    }
811    return false;
812}
813
814bool
815Options::HandleOptionArgumentCompletion
816(
817    Args &input,
818    int cursor_index,
819    int char_pos,
820    OptionElementVector &opt_element_vector,
821    int opt_element_index,
822    int match_start_point,
823    int max_return_elements,
824    bool &word_complete,
825    lldb_private::StringList &matches
826)
827{
828    const OptionDefinition *opt_defs = GetDefinitions();
829    std::auto_ptr<SearchFilter> filter_ap;
830
831    int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
832    int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
833
834    // See if this is an enumeration type option, and if so complete it here:
835
836    OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
837    if (enum_values != NULL)
838    {
839        bool return_value = false;
840        std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
841        for (int i = 0; enum_values[i].string_value != NULL; i++)
842        {
843            if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
844            {
845                matches.AppendString (enum_values[i].string_value);
846                return_value = true;
847            }
848        }
849        return return_value;
850    }
851
852    // If this is a source file or symbol type completion, and  there is a
853    // -shlib option somewhere in the supplied arguments, then make a search filter
854    // for that shared library.
855    // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
856
857    uint32_t completion_mask = opt_defs[opt_defs_index].completion_type;
858
859    if (completion_mask == 0)
860    {
861        lldb::CommandArgumentType option_arg_type = opt_defs[opt_defs_index].argument_type;
862        if (option_arg_type != eArgTypeNone)
863        {
864            CommandObject::ArgumentTableEntry *arg_entry = CommandObject::FindArgumentDataByType (opt_defs[opt_defs_index].argument_type);
865            if (arg_entry)
866                completion_mask = arg_entry->completion_type;
867        }
868    }
869
870    if (completion_mask & CommandCompletions::eSourceFileCompletion
871        || completion_mask & CommandCompletions::eSymbolCompletion)
872    {
873        for (int i = 0; i < opt_element_vector.size(); i++)
874        {
875            int cur_defs_index = opt_element_vector[i].opt_defs_index;
876            int cur_arg_pos    = opt_element_vector[i].opt_arg_pos;
877            const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
878
879            // If this is the "shlib" option and there was an argument provided,
880            // restrict it to that shared library.
881            if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
882            {
883                const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
884                if (module_name)
885                {
886                    FileSpec module_spec(module_name, false);
887                    lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
888                    // Search filters require a target...
889                    if (target_sp)
890                        filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
891                }
892                break;
893            }
894        }
895    }
896
897    return CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
898                                                                completion_mask,
899                                                                input.GetArgumentAtIndex (opt_arg_pos),
900                                                                match_start_point,
901                                                                max_return_elements,
902                                                                filter_ap.get(),
903                                                                word_complete,
904                                                                matches);
905
906}
907
908
909void
910OptionGroupOptions::Append (OptionGroup* group)
911{
912    const OptionDefinition* group_option_defs = group->GetDefinitions ();
913    const uint32_t group_option_count = group->GetNumDefinitions();
914    for (uint32_t i=0; i<group_option_count; ++i)
915    {
916        m_option_infos.push_back (OptionInfo (group, i));
917        m_option_defs.push_back (group_option_defs[i]);
918    }
919}
920
921void
922OptionGroupOptions::Append (OptionGroup* group,
923                            uint32_t src_mask,
924                            uint32_t dst_mask)
925{
926    const OptionDefinition* group_option_defs = group->GetDefinitions ();
927    const uint32_t group_option_count = group->GetNumDefinitions();
928    for (uint32_t i=0; i<group_option_count; ++i)
929    {
930        if (group_option_defs[i].usage_mask & src_mask)
931        {
932            m_option_infos.push_back (OptionInfo (group, i));
933            m_option_defs.push_back (group_option_defs[i]);
934            m_option_defs.back().usage_mask = dst_mask;
935        }
936    }
937}
938
939void
940OptionGroupOptions::Finalize ()
941{
942    m_did_finalize = true;
943    OptionDefinition empty_option_def = { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL };
944    m_option_defs.push_back (empty_option_def);
945}
946
947Error
948OptionGroupOptions::SetOptionValue (uint32_t option_idx,
949                                    const char *option_value)
950{
951    // After calling OptionGroupOptions::Append(...), you must finalize the groups
952    // by calling OptionGroupOptions::Finlize()
953    assert (m_did_finalize);
954    assert (m_option_infos.size() + 1 == m_option_defs.size());
955    Error error;
956    if (option_idx < m_option_infos.size())
957    {
958        error = m_option_infos[option_idx].option_group->SetOptionValue (m_interpreter,
959                                                                         m_option_infos[option_idx].option_index,
960                                                                         option_value);
961
962    }
963    else
964    {
965        error.SetErrorString ("invalid option index"); // Shouldn't happen...
966    }
967    return error;
968}
969
970void
971OptionGroupOptions::OptionParsingStarting ()
972{
973    std::set<OptionGroup*> group_set;
974    OptionInfos::iterator pos, end = m_option_infos.end();
975    for (pos = m_option_infos.begin(); pos != end; ++pos)
976    {
977        OptionGroup* group = pos->option_group;
978        if (group_set.find(group) == group_set.end())
979        {
980            group->OptionParsingStarting (m_interpreter);
981            group_set.insert(group);
982        }
983    }
984}
985Error
986OptionGroupOptions::OptionParsingFinished ()
987{
988    std::set<OptionGroup*> group_set;
989    Error error;
990    OptionInfos::iterator pos, end = m_option_infos.end();
991    for (pos = m_option_infos.begin(); pos != end; ++pos)
992    {
993        OptionGroup* group = pos->option_group;
994        if (group_set.find(group) == group_set.end())
995        {
996            error = group->OptionParsingFinished (m_interpreter);
997            group_set.insert(group);
998            if (error.Fail())
999                return error;
1000        }
1001    }
1002    return error;
1003}
1004