1254721Semaste//===-- Options.cpp ---------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste#include "lldb/Interpreter/Options.h"
13254721Semaste
14254721Semaste// C Includes
15254721Semaste// C++ Includes
16254721Semaste#include <algorithm>
17254721Semaste#include <bitset>
18254721Semaste#include <map>
19254721Semaste
20254721Semaste// Other libraries and framework includes
21254721Semaste// Project includes
22254721Semaste#include "lldb/Interpreter/CommandObject.h"
23254721Semaste#include "lldb/Interpreter/CommandReturnObject.h"
24254721Semaste#include "lldb/Interpreter/CommandCompletions.h"
25254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
26254721Semaste#include "lldb/Core/StreamString.h"
27254721Semaste#include "lldb/Target/Target.h"
28254721Semaste
29254721Semasteusing namespace lldb;
30254721Semasteusing namespace lldb_private;
31254721Semaste
32254721Semaste//-------------------------------------------------------------------------
33254721Semaste// Options
34254721Semaste//-------------------------------------------------------------------------
35254721SemasteOptions::Options (CommandInterpreter &interpreter) :
36254721Semaste    m_interpreter (interpreter),
37254721Semaste    m_getopt_table ()
38254721Semaste{
39254721Semaste    BuildValidOptionSets();
40254721Semaste}
41254721Semaste
42254721SemasteOptions::~Options ()
43254721Semaste{
44254721Semaste}
45254721Semaste
46254721Semastevoid
47254721SemasteOptions::NotifyOptionParsingStarting ()
48254721Semaste{
49254721Semaste    m_seen_options.clear();
50254721Semaste    // Let the subclass reset its option values
51254721Semaste    OptionParsingStarting ();
52254721Semaste}
53254721Semaste
54254721SemasteError
55254721SemasteOptions::NotifyOptionParsingFinished ()
56254721Semaste{
57254721Semaste    return OptionParsingFinished ();
58254721Semaste}
59254721Semaste
60254721Semastevoid
61254721SemasteOptions::OptionSeen (int option_idx)
62254721Semaste{
63254721Semaste    m_seen_options.insert (option_idx);
64254721Semaste}
65254721Semaste
66254721Semaste// Returns true is set_a is a subset of set_b;  Otherwise returns false.
67254721Semaste
68254721Semastebool
69254721SemasteOptions::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
70254721Semaste{
71254721Semaste    bool is_a_subset = true;
72254721Semaste    OptionSet::const_iterator pos_a;
73254721Semaste    OptionSet::const_iterator pos_b;
74254721Semaste
75254721Semaste    // set_a is a subset of set_b if every member of set_a is also a member of set_b
76254721Semaste
77254721Semaste    for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
78254721Semaste    {
79254721Semaste        pos_b = set_b.find(*pos_a);
80254721Semaste        if (pos_b == set_b.end())
81254721Semaste            is_a_subset = false;
82254721Semaste    }
83254721Semaste
84254721Semaste    return is_a_subset;
85254721Semaste}
86254721Semaste
87254721Semaste// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
88254721Semaste
89254721Semastesize_t
90254721SemasteOptions::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
91254721Semaste{
92254721Semaste    size_t num_diffs = 0;
93254721Semaste    OptionSet::const_iterator pos_a;
94254721Semaste    OptionSet::const_iterator pos_b;
95254721Semaste
96254721Semaste    for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
97254721Semaste    {
98254721Semaste        pos_b = set_b.find(*pos_a);
99254721Semaste        if (pos_b == set_b.end())
100254721Semaste        {
101254721Semaste            ++num_diffs;
102254721Semaste            diffs.insert(*pos_a);
103254721Semaste        }
104254721Semaste    }
105254721Semaste
106254721Semaste    return num_diffs;
107254721Semaste}
108254721Semaste
109254721Semaste// Returns the union of set_a and set_b.  Does not put duplicate members into the union.
110254721Semaste
111254721Semastevoid
112254721SemasteOptions::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
113254721Semaste{
114254721Semaste    OptionSet::const_iterator pos;
115254721Semaste    OptionSet::iterator pos_union;
116254721Semaste
117254721Semaste    // Put all the elements of set_a into the union.
118254721Semaste
119254721Semaste    for (pos = set_a.begin(); pos != set_a.end(); ++pos)
120254721Semaste        union_set.insert(*pos);
121254721Semaste
122254721Semaste    // Put all the elements of set_b that are not already there into the union.
123254721Semaste    for (pos = set_b.begin(); pos != set_b.end(); ++pos)
124254721Semaste    {
125254721Semaste        pos_union = union_set.find(*pos);
126254721Semaste        if (pos_union == union_set.end())
127254721Semaste            union_set.insert(*pos);
128254721Semaste    }
129254721Semaste}
130254721Semaste
131254721Semastebool
132254721SemasteOptions::VerifyOptions (CommandReturnObject &result)
133254721Semaste{
134254721Semaste    bool options_are_valid = false;
135254721Semaste
136254721Semaste    int num_levels = GetRequiredOptions().size();
137254721Semaste    if (num_levels)
138254721Semaste    {
139254721Semaste        for (int i = 0; i < num_levels && !options_are_valid; ++i)
140254721Semaste        {
141254721Semaste            // This is the correct set of options if:  1). m_seen_options contains all of m_required_options[i]
142254721Semaste            // (i.e. all the required options at this level are a subset of m_seen_options); AND
143254721Semaste            // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
144254721Semaste            // m_seen_options are in the set of optional options at this level.
145254721Semaste
146254721Semaste            // Check to see if all of m_required_options[i] are a subset of m_seen_options
147254721Semaste            if (IsASubset (GetRequiredOptions()[i], m_seen_options))
148254721Semaste            {
149254721Semaste                // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
150254721Semaste                OptionSet remaining_options;
151254721Semaste                OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options);
152254721Semaste                // Check to see if remaining_options is a subset of m_optional_options[i]
153254721Semaste                if (IsASubset (remaining_options, GetOptionalOptions()[i]))
154254721Semaste                    options_are_valid = true;
155254721Semaste            }
156254721Semaste        }
157254721Semaste    }
158254721Semaste    else
159254721Semaste    {
160254721Semaste        options_are_valid = true;
161254721Semaste    }
162254721Semaste
163254721Semaste    if (options_are_valid)
164254721Semaste    {
165254721Semaste        result.SetStatus (eReturnStatusSuccessFinishNoResult);
166254721Semaste    }
167254721Semaste    else
168254721Semaste    {
169254721Semaste        result.AppendError ("invalid combination of options for the given command");
170254721Semaste        result.SetStatus (eReturnStatusFailed);
171254721Semaste    }
172254721Semaste
173254721Semaste    return options_are_valid;
174254721Semaste}
175254721Semaste
176254721Semaste// This is called in the Options constructor, though we could call it lazily if that ends up being
177254721Semaste// a performance problem.
178254721Semaste
179254721Semastevoid
180254721SemasteOptions::BuildValidOptionSets ()
181254721Semaste{
182254721Semaste    // Check to see if we already did this.
183254721Semaste    if (m_required_options.size() != 0)
184254721Semaste        return;
185254721Semaste
186254721Semaste    // Check to see if there are any options.
187254721Semaste    int num_options = NumCommandOptions ();
188254721Semaste    if (num_options == 0)
189254721Semaste        return;
190254721Semaste
191254721Semaste    const OptionDefinition *opt_defs = GetDefinitions();
192254721Semaste    m_required_options.resize(1);
193254721Semaste    m_optional_options.resize(1);
194254721Semaste
195254721Semaste    // First count the number of option sets we've got.  Ignore LLDB_ALL_OPTION_SETS...
196254721Semaste
197254721Semaste    uint32_t num_option_sets = 0;
198254721Semaste
199254721Semaste    for (int i = 0; i < num_options; i++)
200254721Semaste    {
201254721Semaste        uint32_t this_usage_mask = opt_defs[i].usage_mask;
202254721Semaste        if (this_usage_mask == LLDB_OPT_SET_ALL)
203254721Semaste        {
204254721Semaste            if (num_option_sets == 0)
205254721Semaste                num_option_sets = 1;
206254721Semaste        }
207254721Semaste        else
208254721Semaste        {
209254721Semaste            for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
210254721Semaste            {
211254721Semaste                if (this_usage_mask & (1 << j))
212254721Semaste                {
213254721Semaste                    if (num_option_sets <= j)
214254721Semaste                        num_option_sets = j + 1;
215254721Semaste                }
216254721Semaste            }
217254721Semaste        }
218254721Semaste    }
219254721Semaste
220254721Semaste    if (num_option_sets > 0)
221254721Semaste    {
222254721Semaste        m_required_options.resize(num_option_sets);
223254721Semaste        m_optional_options.resize(num_option_sets);
224254721Semaste
225254721Semaste        for (int i = 0; i < num_options; ++i)
226254721Semaste        {
227254721Semaste            for (uint32_t j = 0; j < num_option_sets; j++)
228254721Semaste            {
229254721Semaste                if (opt_defs[i].usage_mask & 1 << j)
230254721Semaste                {
231254721Semaste                    if (opt_defs[i].required)
232254721Semaste                        m_required_options[j].insert(opt_defs[i].short_option);
233254721Semaste                    else
234254721Semaste                        m_optional_options[j].insert(opt_defs[i].short_option);
235254721Semaste                }
236254721Semaste            }
237254721Semaste        }
238254721Semaste    }
239254721Semaste}
240254721Semaste
241254721Semasteuint32_t
242254721SemasteOptions::NumCommandOptions ()
243254721Semaste{
244254721Semaste    const OptionDefinition *opt_defs = GetDefinitions ();
245254721Semaste    if (opt_defs == NULL)
246254721Semaste        return 0;
247254721Semaste
248254721Semaste    int i = 0;
249254721Semaste
250254721Semaste    if (opt_defs != NULL)
251254721Semaste    {
252254721Semaste        while (opt_defs[i].long_option != NULL)
253254721Semaste            ++i;
254254721Semaste    }
255254721Semaste
256254721Semaste    return i;
257254721Semaste}
258254721Semaste
259263363SemasteOption *
260254721SemasteOptions::GetLongOptions ()
261254721Semaste{
262254721Semaste    // Check to see if this has already been done.
263254721Semaste    if (m_getopt_table.empty())
264254721Semaste    {
265254721Semaste        // Check to see if there are any options.
266254721Semaste        const uint32_t num_options = NumCommandOptions();
267254721Semaste        if (num_options == 0)
268254721Semaste            return NULL;
269254721Semaste
270254721Semaste        uint32_t i;
271254721Semaste        const OptionDefinition *opt_defs = GetDefinitions();
272254721Semaste
273254721Semaste        std::map<int, uint32_t> option_seen;
274254721Semaste
275254721Semaste        m_getopt_table.resize(num_options + 1);
276254721Semaste        for (i = 0; i < num_options; ++i)
277254721Semaste        {
278254721Semaste            const int short_opt = opt_defs[i].short_option;
279254721Semaste
280254721Semaste            m_getopt_table[i].name    = opt_defs[i].long_option;
281254721Semaste            m_getopt_table[i].has_arg = opt_defs[i].option_has_arg;
282254721Semaste            m_getopt_table[i].flag    = NULL;
283254721Semaste            m_getopt_table[i].val     = short_opt;
284254721Semaste
285254721Semaste            if (option_seen.find(short_opt) == option_seen.end())
286254721Semaste            {
287254721Semaste                option_seen[short_opt] = i;
288254721Semaste            }
289254721Semaste            else if (short_opt)
290254721Semaste            {
291254721Semaste                m_getopt_table[i].val = 0;
292254721Semaste                std::map<int, uint32_t>::const_iterator pos = option_seen.find(short_opt);
293254721Semaste                StreamString strm;
294254721Semaste                if (isprint8(short_opt))
295254721Semaste                    Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option -%c that conflicts with option[%u] --%s, short option won't be used for --%s\n",
296254721Semaste                                i,
297254721Semaste                                opt_defs[i].long_option,
298254721Semaste                                short_opt,
299254721Semaste                                pos->second,
300254721Semaste                                m_getopt_table[pos->second].name,
301254721Semaste                                opt_defs[i].long_option);
302254721Semaste                else
303254721Semaste                    Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option 0x%x that conflicts with option[%u] --%s, short option won't be used for --%s\n",
304254721Semaste                                i,
305254721Semaste                                opt_defs[i].long_option,
306254721Semaste                                short_opt,
307254721Semaste                                pos->second,
308254721Semaste                                m_getopt_table[pos->second].name,
309254721Semaste                                opt_defs[i].long_option);
310254721Semaste            }
311254721Semaste        }
312254721Semaste
313254721Semaste        //getopt_long_only requires a NULL final entry in the table:
314254721Semaste
315254721Semaste        m_getopt_table[i].name    = NULL;
316254721Semaste        m_getopt_table[i].has_arg = 0;
317254721Semaste        m_getopt_table[i].flag    = NULL;
318254721Semaste        m_getopt_table[i].val     = 0;
319254721Semaste    }
320254721Semaste
321254721Semaste    if (m_getopt_table.empty())
322254721Semaste        return NULL;
323254721Semaste
324254721Semaste    return &m_getopt_table.front();
325254721Semaste}
326254721Semaste
327254721Semaste
328254721Semaste// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
329254721Semaste// a string containing 80 spaces; and TEXT, which is the text that is to be output.   It outputs the text, on
330254721Semaste// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line.  It breaks lines on spaces,
331254721Semaste// tabs or newlines, shortening the line if necessary to not break in the middle of a word.  It assumes that each
332254721Semaste// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
333254721Semaste
334254721Semaste
335254721Semastevoid
336254721SemasteOptions::OutputFormattedUsageText
337254721Semaste(
338254721Semaste    Stream &strm,
339254721Semaste    const char *text,
340254721Semaste    uint32_t output_max_columns
341254721Semaste)
342254721Semaste{
343254721Semaste    int len = strlen (text);
344254721Semaste
345254721Semaste    // Will it all fit on one line?
346254721Semaste
347254721Semaste    if ((len + strm.GetIndentLevel()) < output_max_columns)
348254721Semaste    {
349254721Semaste        // Output it as a single line.
350254721Semaste        strm.Indent (text);
351254721Semaste        strm.EOL();
352254721Semaste    }
353254721Semaste    else
354254721Semaste    {
355254721Semaste        // We need to break it up into multiple lines.
356254721Semaste
357254721Semaste        int text_width = output_max_columns - strm.GetIndentLevel() - 1;
358254721Semaste        int start = 0;
359254721Semaste        int end = start;
360254721Semaste        int final_end = strlen (text);
361254721Semaste        int sub_len;
362254721Semaste
363254721Semaste        while (end < final_end)
364254721Semaste        {
365254721Semaste            // Don't start the 'text' on a space, since we're already outputting the indentation.
366254721Semaste            while ((start < final_end) && (text[start] == ' '))
367254721Semaste                start++;
368254721Semaste
369254721Semaste            end = start + text_width;
370254721Semaste            if (end > final_end)
371254721Semaste                end = final_end;
372254721Semaste            else
373254721Semaste            {
374254721Semaste                // If we're not at the end of the text, make sure we break the line on white space.
375254721Semaste                while (end > start
376254721Semaste                       && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
377254721Semaste                    end--;
378254721Semaste            }
379254721Semaste
380254721Semaste            sub_len = end - start;
381254721Semaste            if (start != 0)
382254721Semaste                strm.EOL();
383254721Semaste            strm.Indent();
384254721Semaste            assert (start < final_end);
385254721Semaste            assert (start + sub_len <= final_end);
386254721Semaste            strm.Write(text + start, sub_len);
387254721Semaste            start = end + 1;
388254721Semaste        }
389254721Semaste        strm.EOL();
390254721Semaste    }
391254721Semaste}
392254721Semaste
393254721Semastebool
394254721SemasteOptions::SupportsLongOption (const char *long_option)
395254721Semaste{
396254721Semaste    if (long_option && long_option[0])
397254721Semaste    {
398254721Semaste        const OptionDefinition *opt_defs = GetDefinitions ();
399254721Semaste        if (opt_defs)
400254721Semaste        {
401254721Semaste            const char *long_option_name = long_option;
402254721Semaste            if (long_option[0] == '-' && long_option[1] == '-')
403254721Semaste                long_option_name += 2;
404254721Semaste
405254721Semaste            for (uint32_t i = 0; opt_defs[i].long_option; ++i)
406254721Semaste            {
407254721Semaste                if (strcmp(opt_defs[i].long_option, long_option_name) == 0)
408254721Semaste                    return true;
409254721Semaste            }
410254721Semaste        }
411254721Semaste    }
412254721Semaste    return false;
413254721Semaste}
414254721Semaste
415254721Semasteenum OptionDisplayType
416254721Semaste{
417254721Semaste    eDisplayBestOption,
418254721Semaste    eDisplayShortOption,
419254721Semaste    eDisplayLongOption
420254721Semaste};
421254721Semaste
422254721Semastestatic bool
423254721SemastePrintOption (const OptionDefinition &opt_def,
424254721Semaste             OptionDisplayType display_type,
425254721Semaste             const char *header,
426254721Semaste             const char *footer,
427254721Semaste             bool show_optional,
428254721Semaste             Stream &strm)
429254721Semaste{
430254721Semaste    const bool has_short_option = isprint8(opt_def.short_option) != 0;
431254721Semaste
432254721Semaste    if (display_type == eDisplayShortOption && !has_short_option)
433254721Semaste        return false;
434254721Semaste
435254721Semaste    if (header && header[0])
436254721Semaste        strm.PutCString(header);
437254721Semaste
438254721Semaste    if (show_optional && !opt_def.required)
439254721Semaste    strm.PutChar('[');
440254721Semaste    const bool show_short_option = has_short_option && display_type != eDisplayLongOption;
441254721Semaste    if (show_short_option)
442254721Semaste        strm.Printf ("-%c", opt_def.short_option);
443254721Semaste    else
444254721Semaste        strm.Printf ("--%s", opt_def.long_option);
445254721Semaste    switch (opt_def.option_has_arg)
446254721Semaste    {
447263363Semaste        case OptionParser::eNoArgument:
448254721Semaste            break;
449263363Semaste        case OptionParser::eRequiredArgument:
450254721Semaste            strm.Printf (" <%s>", CommandObject::GetArgumentName (opt_def.argument_type));
451254721Semaste            break;
452254721Semaste
453263363Semaste        case OptionParser::eOptionalArgument:
454254721Semaste            strm.Printf ("%s[<%s>]",
455254721Semaste                         show_short_option ? "" : "=",
456254721Semaste                         CommandObject::GetArgumentName (opt_def.argument_type));
457254721Semaste            break;
458254721Semaste    }
459254721Semaste    if (show_optional && !opt_def.required)
460254721Semaste        strm.PutChar(']');
461254721Semaste    if (footer && footer[0])
462254721Semaste        strm.PutCString(footer);
463254721Semaste    return true;
464254721Semaste}
465254721Semaste
466254721Semastevoid
467254721SemasteOptions::GenerateOptionUsage
468254721Semaste(
469254721Semaste    Stream &strm,
470254721Semaste    CommandObject *cmd
471254721Semaste)
472254721Semaste{
473254721Semaste    const uint32_t screen_width = m_interpreter.GetDebugger().GetTerminalWidth();
474254721Semaste
475254721Semaste    const OptionDefinition *opt_defs = GetDefinitions();
476254721Semaste    const uint32_t save_indent_level = strm.GetIndentLevel();
477254721Semaste    const char *name;
478254721Semaste
479254721Semaste    StreamString arguments_str;
480254721Semaste
481254721Semaste    if (cmd)
482254721Semaste    {
483254721Semaste        name = cmd->GetCommandName();
484254721Semaste        cmd->GetFormattedCommandArguments (arguments_str);
485254721Semaste    }
486254721Semaste    else
487254721Semaste        name = "";
488254721Semaste
489254721Semaste    strm.PutCString ("\nCommand Options Usage:\n");
490254721Semaste
491254721Semaste    strm.IndentMore(2);
492254721Semaste
493254721Semaste    // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
494254721Semaste    //                                                   <cmd> [options-for-level-1]
495254721Semaste    //                                                   etc.
496254721Semaste
497254721Semaste    const uint32_t num_options = NumCommandOptions();
498254721Semaste    if (num_options == 0)
499254721Semaste        return;
500254721Semaste
501254721Semaste    uint32_t num_option_sets = GetRequiredOptions().size();
502254721Semaste
503254721Semaste    uint32_t i;
504254721Semaste
505254721Semaste    for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
506254721Semaste    {
507254721Semaste        uint32_t opt_set_mask;
508254721Semaste
509254721Semaste        opt_set_mask = 1 << opt_set;
510254721Semaste        if (opt_set > 0)
511254721Semaste            strm.Printf ("\n");
512254721Semaste        strm.Indent (name);
513254721Semaste
514254721Semaste        // Different option sets may require different args.
515254721Semaste        StreamString args_str;
516254721Semaste        if (cmd)
517254721Semaste            cmd->GetFormattedCommandArguments(args_str, opt_set_mask);
518254721Semaste
519254721Semaste        // First go through and print all options that take no arguments as
520254721Semaste        // a single string. If a command has "-a" "-b" and "-c", this will show
521254721Semaste        // up as [-abc]
522254721Semaste
523254721Semaste        std::set<int> options;
524254721Semaste        std::set<int>::const_iterator options_pos, options_end;
525254721Semaste        for (i = 0; i < num_options; ++i)
526254721Semaste        {
527254721Semaste            if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
528254721Semaste            {
529254721Semaste                // Add current option to the end of out_stream.
530254721Semaste
531254721Semaste                if (opt_defs[i].required == true &&
532263363Semaste                    opt_defs[i].option_has_arg == OptionParser::eNoArgument)
533254721Semaste                {
534254721Semaste                    options.insert (opt_defs[i].short_option);
535254721Semaste                }
536254721Semaste            }
537254721Semaste        }
538254721Semaste
539254721Semaste        if (options.empty() == false)
540254721Semaste        {
541254721Semaste            // We have some required options with no arguments
542254721Semaste            strm.PutCString(" -");
543254721Semaste            for (i=0; i<2; ++i)
544254721Semaste                for (options_pos = options.begin(), options_end = options.end();
545254721Semaste                     options_pos != options_end;
546254721Semaste                     ++options_pos)
547254721Semaste                {
548254721Semaste                    if (i==0 && ::islower (*options_pos))
549254721Semaste                        continue;
550254721Semaste                    if (i==1 && ::isupper (*options_pos))
551254721Semaste                        continue;
552254721Semaste                    strm << (char)*options_pos;
553254721Semaste                }
554254721Semaste        }
555254721Semaste
556254721Semaste        for (i = 0, options.clear(); i < num_options; ++i)
557254721Semaste        {
558254721Semaste            if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
559254721Semaste            {
560254721Semaste                // Add current option to the end of out_stream.
561254721Semaste
562254721Semaste                if (opt_defs[i].required == false &&
563263363Semaste                    opt_defs[i].option_has_arg == OptionParser::eNoArgument)
564254721Semaste                {
565254721Semaste                    options.insert (opt_defs[i].short_option);
566254721Semaste                }
567254721Semaste            }
568254721Semaste        }
569254721Semaste
570254721Semaste        if (options.empty() == false)
571254721Semaste        {
572254721Semaste            // We have some required options with no arguments
573254721Semaste            strm.PutCString(" [-");
574254721Semaste            for (i=0; i<2; ++i)
575254721Semaste                for (options_pos = options.begin(), options_end = options.end();
576254721Semaste                     options_pos != options_end;
577254721Semaste                     ++options_pos)
578254721Semaste                {
579254721Semaste                    if (i==0 && ::islower (*options_pos))
580254721Semaste                        continue;
581254721Semaste                    if (i==1 && ::isupper (*options_pos))
582254721Semaste                        continue;
583254721Semaste                    strm << (char)*options_pos;
584254721Semaste                }
585254721Semaste            strm.PutChar(']');
586254721Semaste        }
587254721Semaste
588254721Semaste        // First go through and print the required options (list them up front).
589254721Semaste
590254721Semaste        for (i = 0; i < num_options; ++i)
591254721Semaste        {
592254721Semaste            if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
593254721Semaste            {
594263363Semaste                if (opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
595254721Semaste                    PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
596254721Semaste            }
597254721Semaste        }
598254721Semaste
599254721Semaste        // Now go through again, and this time only print the optional options.
600254721Semaste
601254721Semaste        for (i = 0; i < num_options; ++i)
602254721Semaste        {
603254721Semaste            if (opt_defs[i].usage_mask & opt_set_mask)
604254721Semaste            {
605254721Semaste                // Add current option to the end of out_stream.
606254721Semaste
607263363Semaste                if (!opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
608254721Semaste                    PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
609254721Semaste            }
610254721Semaste        }
611254721Semaste
612254721Semaste        if (args_str.GetSize() > 0)
613254721Semaste        {
614254721Semaste            if (cmd->WantsRawCommandString())
615254721Semaste                strm.Printf(" --");
616254721Semaste
617254721Semaste            strm.Printf (" %s", args_str.GetData());
618254721Semaste        }
619254721Semaste    }
620254721Semaste
621254721Semaste    if (cmd &&
622254721Semaste        cmd->WantsRawCommandString() &&
623254721Semaste        arguments_str.GetSize() > 0)
624254721Semaste    {
625254721Semaste        strm.PutChar('\n');
626254721Semaste        strm.Indent(name);
627254721Semaste        strm.Printf(" %s", arguments_str.GetData());
628254721Semaste    }
629254721Semaste
630254721Semaste    strm.Printf ("\n\n");
631254721Semaste
632254721Semaste    // Now print out all the detailed information about the various options:  long form, short form and help text:
633254721Semaste    //   --long_name <argument>  ( -short <argument> )
634254721Semaste    //   help text
635254721Semaste
636254721Semaste    // This variable is used to keep track of which options' info we've printed out, because some options can be in
637254721Semaste    // more than one usage level, but we only want to print the long form of its information once.
638254721Semaste
639254721Semaste    std::multimap<int, uint32_t> options_seen;
640254721Semaste    strm.IndentMore (5);
641254721Semaste
642254721Semaste    // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option)
643254721Semaste    // when writing out detailed help for each option.
644254721Semaste
645254721Semaste    for (i = 0; i < num_options; ++i)
646254721Semaste        options_seen.insert(std::make_pair(opt_defs[i].short_option, i));
647254721Semaste
648254721Semaste    // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option
649254721Semaste    // and write out the detailed help information for that option.
650254721Semaste
651254721Semaste    bool first_option_printed = false;;
652254721Semaste
653254721Semaste    for (auto pos : options_seen)
654254721Semaste    {
655254721Semaste        i = pos.second;
656254721Semaste        //Print out the help information for this option.
657254721Semaste
658254721Semaste        // Put a newline separation between arguments
659254721Semaste        if (first_option_printed)
660254721Semaste            strm.EOL();
661254721Semaste        else
662254721Semaste            first_option_printed = true;
663254721Semaste
664254721Semaste        CommandArgumentType arg_type = opt_defs[i].argument_type;
665254721Semaste
666254721Semaste        StreamString arg_name_str;
667254721Semaste        arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type));
668254721Semaste
669254721Semaste        strm.Indent ();
670254721Semaste        if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option))
671254721Semaste        {
672254721Semaste            PrintOption (opt_defs[i], eDisplayShortOption, NULL, NULL, false, strm);
673254721Semaste            PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm);
674254721Semaste        }
675254721Semaste        else
676254721Semaste        {
677254721Semaste            // Short option is not printable, just print long option
678254721Semaste            PrintOption (opt_defs[i], eDisplayLongOption, NULL, NULL, false, strm);
679254721Semaste        }
680254721Semaste        strm.EOL();
681254721Semaste
682254721Semaste        strm.IndentMore (5);
683254721Semaste
684254721Semaste        if (opt_defs[i].usage_text)
685254721Semaste            OutputFormattedUsageText (strm,
686254721Semaste                                      opt_defs[i].usage_text,
687254721Semaste                                      screen_width);
688254721Semaste        if (opt_defs[i].enum_values != NULL)
689254721Semaste        {
690254721Semaste            strm.Indent ();
691254721Semaste            strm.Printf("Values: ");
692254721Semaste            for (int k = 0; opt_defs[i].enum_values[k].string_value != NULL; k++)
693254721Semaste            {
694254721Semaste                if (k == 0)
695254721Semaste                    strm.Printf("%s", opt_defs[i].enum_values[k].string_value);
696254721Semaste                else
697254721Semaste                    strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value);
698254721Semaste            }
699254721Semaste            strm.EOL();
700254721Semaste        }
701254721Semaste        strm.IndentLess (5);
702254721Semaste    }
703254721Semaste
704254721Semaste    // Restore the indent level
705254721Semaste    strm.SetIndentLevel (save_indent_level);
706254721Semaste}
707254721Semaste
708254721Semaste// This function is called when we have been given a potentially incomplete set of
709254721Semaste// options, such as when an alias has been defined (more options might be added at
710254721Semaste// at the time the alias is invoked).  We need to verify that the options in the set
711254721Semaste// m_seen_options are all part of a set that may be used together, but m_seen_options
712254721Semaste// may be missing some of the "required" options.
713254721Semaste
714254721Semastebool
715254721SemasteOptions::VerifyPartialOptions (CommandReturnObject &result)
716254721Semaste{
717254721Semaste    bool options_are_valid = false;
718254721Semaste
719254721Semaste    int num_levels = GetRequiredOptions().size();
720254721Semaste    if (num_levels)
721254721Semaste      {
722254721Semaste        for (int i = 0; i < num_levels && !options_are_valid; ++i)
723254721Semaste          {
724254721Semaste            // In this case we are treating all options as optional rather than required.
725254721Semaste            // Therefore a set of options is correct if m_seen_options is a subset of the
726254721Semaste            // union of m_required_options and m_optional_options.
727254721Semaste            OptionSet union_set;
728254721Semaste            OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
729254721Semaste            if (IsASubset (m_seen_options, union_set))
730254721Semaste                options_are_valid = true;
731254721Semaste          }
732254721Semaste      }
733254721Semaste
734254721Semaste    return options_are_valid;
735254721Semaste}
736254721Semaste
737254721Semastebool
738254721SemasteOptions::HandleOptionCompletion
739254721Semaste(
740254721Semaste    Args &input,
741254721Semaste    OptionElementVector &opt_element_vector,
742254721Semaste    int cursor_index,
743254721Semaste    int char_pos,
744254721Semaste    int match_start_point,
745254721Semaste    int max_return_elements,
746254721Semaste    bool &word_complete,
747254721Semaste    lldb_private::StringList &matches
748254721Semaste)
749254721Semaste{
750254721Semaste    word_complete = true;
751254721Semaste
752254721Semaste    // For now we just scan the completions to see if the cursor position is in
753254721Semaste    // an option or its argument.  Otherwise we'll call HandleArgumentCompletion.
754254721Semaste    // In the future we can use completion to validate options as well if we want.
755254721Semaste
756254721Semaste    const OptionDefinition *opt_defs = GetDefinitions();
757254721Semaste
758254721Semaste    std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
759254721Semaste    cur_opt_std_str.erase(char_pos);
760254721Semaste    const char *cur_opt_str = cur_opt_std_str.c_str();
761254721Semaste
762254721Semaste    for (size_t i = 0; i < opt_element_vector.size(); i++)
763254721Semaste    {
764254721Semaste        int opt_pos = opt_element_vector[i].opt_pos;
765254721Semaste        int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
766254721Semaste        int opt_defs_index = opt_element_vector[i].opt_defs_index;
767254721Semaste        if (opt_pos == cursor_index)
768254721Semaste        {
769254721Semaste            // We're completing the option itself.
770254721Semaste
771254721Semaste            if (opt_defs_index == OptionArgElement::eBareDash)
772254721Semaste            {
773254721Semaste                // We're completing a bare dash.  That means all options are open.
774254721Semaste                // FIXME: We should scan the other options provided and only complete options
775254721Semaste                // within the option group they belong to.
776254721Semaste                char opt_str[3] = {'-', 'a', '\0'};
777254721Semaste
778254721Semaste                for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
779254721Semaste                {
780254721Semaste                    opt_str[1] = opt_defs[j].short_option;
781254721Semaste                    matches.AppendString (opt_str);
782254721Semaste                }
783254721Semaste                return true;
784254721Semaste            }
785254721Semaste            else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
786254721Semaste            {
787254721Semaste                std::string full_name ("--");
788254721Semaste                for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
789254721Semaste                {
790254721Semaste                    full_name.erase(full_name.begin() + 2, full_name.end());
791254721Semaste                    full_name.append (opt_defs[j].long_option);
792254721Semaste                    matches.AppendString (full_name.c_str());
793254721Semaste                }
794254721Semaste                return true;
795254721Semaste            }
796254721Semaste            else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
797254721Semaste            {
798254721Semaste                // We recognized it, if it an incomplete long option, complete it anyway (getopt_long_only is
799254721Semaste                // happy with shortest unique string, but it's still a nice thing to do.)  Otherwise return
800254721Semaste                // The string so the upper level code will know this is a full match and add the " ".
801254721Semaste                if (cur_opt_str && strlen (cur_opt_str) > 2
802254721Semaste                    && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
803254721Semaste                    && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
804254721Semaste                {
805254721Semaste                        std::string full_name ("--");
806254721Semaste                        full_name.append (opt_defs[opt_defs_index].long_option);
807254721Semaste                        matches.AppendString(full_name.c_str());
808254721Semaste                        return true;
809254721Semaste                }
810254721Semaste                else
811254721Semaste                {
812254721Semaste                    matches.AppendString(input.GetArgumentAtIndex(cursor_index));
813254721Semaste                    return true;
814254721Semaste                }
815254721Semaste            }
816254721Semaste            else
817254721Semaste            {
818254721Semaste                // FIXME - not handling wrong options yet:
819254721Semaste                // Check to see if they are writing a long option & complete it.
820254721Semaste                // I think we will only get in here if the long option table has two elements
821254721Semaste                // that are not unique up to this point.  getopt_long_only does shortest unique match
822254721Semaste                // for long options already.
823254721Semaste
824254721Semaste                if (cur_opt_str && strlen (cur_opt_str) > 2
825254721Semaste                    && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
826254721Semaste                {
827254721Semaste                    for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
828254721Semaste                    {
829254721Semaste                        if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option)
830254721Semaste                        {
831254721Semaste                            std::string full_name ("--");
832254721Semaste                            full_name.append (opt_defs[j].long_option);
833254721Semaste                            // The options definitions table has duplicates because of the
834254721Semaste                            // way the grouping information is stored, so only add once.
835254721Semaste                            bool duplicate = false;
836254721Semaste                            for (size_t k = 0; k < matches.GetSize(); k++)
837254721Semaste                            {
838254721Semaste                                if (matches.GetStringAtIndex(k) == full_name)
839254721Semaste                                {
840254721Semaste                                    duplicate = true;
841254721Semaste                                    break;
842254721Semaste                                }
843254721Semaste                            }
844254721Semaste                            if (!duplicate)
845254721Semaste                                matches.AppendString(full_name.c_str());
846254721Semaste                        }
847254721Semaste                    }
848254721Semaste                }
849254721Semaste                return true;
850254721Semaste            }
851254721Semaste
852254721Semaste
853254721Semaste        }
854254721Semaste        else if (opt_arg_pos == cursor_index)
855254721Semaste        {
856254721Semaste            // Okay the cursor is on the completion of an argument.
857254721Semaste            // See if it has a completion, otherwise return no matches.
858254721Semaste
859254721Semaste            if (opt_defs_index != -1)
860254721Semaste            {
861254721Semaste                HandleOptionArgumentCompletion (input,
862254721Semaste                                                cursor_index,
863254721Semaste                                                strlen (input.GetArgumentAtIndex(cursor_index)),
864254721Semaste                                                opt_element_vector,
865254721Semaste                                                i,
866254721Semaste                                                match_start_point,
867254721Semaste                                                max_return_elements,
868254721Semaste                                                word_complete,
869254721Semaste                                                matches);
870254721Semaste                return true;
871254721Semaste            }
872254721Semaste            else
873254721Semaste            {
874254721Semaste                // No completion callback means no completions...
875254721Semaste                return true;
876254721Semaste            }
877254721Semaste
878254721Semaste        }
879254721Semaste        else
880254721Semaste        {
881254721Semaste            // Not the last element, keep going.
882254721Semaste            continue;
883254721Semaste        }
884254721Semaste    }
885254721Semaste    return false;
886254721Semaste}
887254721Semaste
888254721Semastebool
889254721SemasteOptions::HandleOptionArgumentCompletion
890254721Semaste(
891254721Semaste    Args &input,
892254721Semaste    int cursor_index,
893254721Semaste    int char_pos,
894254721Semaste    OptionElementVector &opt_element_vector,
895254721Semaste    int opt_element_index,
896254721Semaste    int match_start_point,
897254721Semaste    int max_return_elements,
898254721Semaste    bool &word_complete,
899254721Semaste    lldb_private::StringList &matches
900254721Semaste)
901254721Semaste{
902254721Semaste    const OptionDefinition *opt_defs = GetDefinitions();
903254721Semaste    std::unique_ptr<SearchFilter> filter_ap;
904254721Semaste
905254721Semaste    int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
906254721Semaste    int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
907254721Semaste
908254721Semaste    // See if this is an enumeration type option, and if so complete it here:
909254721Semaste
910254721Semaste    OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
911254721Semaste    if (enum_values != NULL)
912254721Semaste    {
913254721Semaste        bool return_value = false;
914254721Semaste        std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
915254721Semaste        for (int i = 0; enum_values[i].string_value != NULL; i++)
916254721Semaste        {
917254721Semaste            if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
918254721Semaste            {
919254721Semaste                matches.AppendString (enum_values[i].string_value);
920254721Semaste                return_value = true;
921254721Semaste            }
922254721Semaste        }
923254721Semaste        return return_value;
924254721Semaste    }
925254721Semaste
926254721Semaste    // If this is a source file or symbol type completion, and  there is a
927254721Semaste    // -shlib option somewhere in the supplied arguments, then make a search filter
928254721Semaste    // for that shared library.
929254721Semaste    // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
930254721Semaste
931254721Semaste    uint32_t completion_mask = opt_defs[opt_defs_index].completion_type;
932254721Semaste
933254721Semaste    if (completion_mask == 0)
934254721Semaste    {
935254721Semaste        lldb::CommandArgumentType option_arg_type = opt_defs[opt_defs_index].argument_type;
936254721Semaste        if (option_arg_type != eArgTypeNone)
937254721Semaste        {
938254721Semaste            CommandObject::ArgumentTableEntry *arg_entry = CommandObject::FindArgumentDataByType (opt_defs[opt_defs_index].argument_type);
939254721Semaste            if (arg_entry)
940254721Semaste                completion_mask = arg_entry->completion_type;
941254721Semaste        }
942254721Semaste    }
943254721Semaste
944254721Semaste    if (completion_mask & CommandCompletions::eSourceFileCompletion
945254721Semaste        || completion_mask & CommandCompletions::eSymbolCompletion)
946254721Semaste    {
947254721Semaste        for (size_t i = 0; i < opt_element_vector.size(); i++)
948254721Semaste        {
949254721Semaste            int cur_defs_index = opt_element_vector[i].opt_defs_index;
950254721Semaste            int cur_arg_pos    = opt_element_vector[i].opt_arg_pos;
951254721Semaste            const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
952254721Semaste
953254721Semaste            // If this is the "shlib" option and there was an argument provided,
954254721Semaste            // restrict it to that shared library.
955269024Semaste            if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
956254721Semaste            {
957254721Semaste                const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
958254721Semaste                if (module_name)
959254721Semaste                {
960254721Semaste                    FileSpec module_spec(module_name, false);
961254721Semaste                    lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
962254721Semaste                    // Search filters require a target...
963254721Semaste                    if (target_sp)
964254721Semaste                        filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
965254721Semaste                }
966254721Semaste                break;
967254721Semaste            }
968254721Semaste        }
969254721Semaste    }
970254721Semaste
971254721Semaste    return CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
972254721Semaste                                                                completion_mask,
973254721Semaste                                                                input.GetArgumentAtIndex (opt_arg_pos),
974254721Semaste                                                                match_start_point,
975254721Semaste                                                                max_return_elements,
976254721Semaste                                                                filter_ap.get(),
977254721Semaste                                                                word_complete,
978254721Semaste                                                                matches);
979254721Semaste
980254721Semaste}
981254721Semaste
982254721Semaste
983254721Semastevoid
984254721SemasteOptionGroupOptions::Append (OptionGroup* group)
985254721Semaste{
986254721Semaste    const OptionDefinition* group_option_defs = group->GetDefinitions ();
987254721Semaste    const uint32_t group_option_count = group->GetNumDefinitions();
988254721Semaste    for (uint32_t i=0; i<group_option_count; ++i)
989254721Semaste    {
990254721Semaste        m_option_infos.push_back (OptionInfo (group, i));
991254721Semaste        m_option_defs.push_back (group_option_defs[i]);
992254721Semaste    }
993254721Semaste}
994254721Semaste
995263363Semasteconst OptionGroup*
996263363SemasteOptionGroupOptions::GetGroupWithOption (char short_opt)
997263363Semaste{
998263363Semaste    for (uint32_t i = 0; i < m_option_defs.size(); i++)
999263363Semaste    {
1000263363Semaste        OptionDefinition opt_def = m_option_defs[i];
1001263363Semaste        if (opt_def.short_option == short_opt)
1002263363Semaste            return m_option_infos[i].option_group;
1003263363Semaste    }
1004263363Semaste    return NULL;
1005263363Semaste}
1006263363Semaste
1007254721Semastevoid
1008254721SemasteOptionGroupOptions::Append (OptionGroup* group,
1009254721Semaste                            uint32_t src_mask,
1010254721Semaste                            uint32_t dst_mask)
1011254721Semaste{
1012254721Semaste    const OptionDefinition* group_option_defs = group->GetDefinitions ();
1013254721Semaste    const uint32_t group_option_count = group->GetNumDefinitions();
1014254721Semaste    for (uint32_t i=0; i<group_option_count; ++i)
1015254721Semaste    {
1016254721Semaste        if (group_option_defs[i].usage_mask & src_mask)
1017254721Semaste        {
1018254721Semaste            m_option_infos.push_back (OptionInfo (group, i));
1019254721Semaste            m_option_defs.push_back (group_option_defs[i]);
1020254721Semaste            m_option_defs.back().usage_mask = dst_mask;
1021254721Semaste        }
1022254721Semaste    }
1023254721Semaste}
1024254721Semaste
1025254721Semastevoid
1026254721SemasteOptionGroupOptions::Finalize ()
1027254721Semaste{
1028254721Semaste    m_did_finalize = true;
1029254721Semaste    OptionDefinition empty_option_def = { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL };
1030254721Semaste    m_option_defs.push_back (empty_option_def);
1031254721Semaste}
1032254721Semaste
1033254721SemasteError
1034254721SemasteOptionGroupOptions::SetOptionValue (uint32_t option_idx,
1035254721Semaste                                    const char *option_value)
1036254721Semaste{
1037254721Semaste    // After calling OptionGroupOptions::Append(...), you must finalize the groups
1038254721Semaste    // by calling OptionGroupOptions::Finlize()
1039254721Semaste    assert (m_did_finalize);
1040254721Semaste    assert (m_option_infos.size() + 1 == m_option_defs.size());
1041254721Semaste    Error error;
1042254721Semaste    if (option_idx < m_option_infos.size())
1043254721Semaste    {
1044254721Semaste        error = m_option_infos[option_idx].option_group->SetOptionValue (m_interpreter,
1045254721Semaste                                                                         m_option_infos[option_idx].option_index,
1046254721Semaste                                                                         option_value);
1047254721Semaste
1048254721Semaste    }
1049254721Semaste    else
1050254721Semaste    {
1051254721Semaste        error.SetErrorString ("invalid option index"); // Shouldn't happen...
1052254721Semaste    }
1053254721Semaste    return error;
1054254721Semaste}
1055254721Semaste
1056254721Semastevoid
1057254721SemasteOptionGroupOptions::OptionParsingStarting ()
1058254721Semaste{
1059254721Semaste    std::set<OptionGroup*> group_set;
1060254721Semaste    OptionInfos::iterator pos, end = m_option_infos.end();
1061254721Semaste    for (pos = m_option_infos.begin(); pos != end; ++pos)
1062254721Semaste    {
1063254721Semaste        OptionGroup* group = pos->option_group;
1064254721Semaste        if (group_set.find(group) == group_set.end())
1065254721Semaste        {
1066254721Semaste            group->OptionParsingStarting (m_interpreter);
1067254721Semaste            group_set.insert(group);
1068254721Semaste        }
1069254721Semaste    }
1070254721Semaste}
1071254721SemasteError
1072254721SemasteOptionGroupOptions::OptionParsingFinished ()
1073254721Semaste{
1074254721Semaste    std::set<OptionGroup*> group_set;
1075254721Semaste    Error error;
1076254721Semaste    OptionInfos::iterator pos, end = m_option_infos.end();
1077254721Semaste    for (pos = m_option_infos.begin(); pos != end; ++pos)
1078254721Semaste    {
1079254721Semaste        OptionGroup* group = pos->option_group;
1080254721Semaste        if (group_set.find(group) == group_set.end())
1081254721Semaste        {
1082254721Semaste            error = group->OptionParsingFinished (m_interpreter);
1083254721Semaste            group_set.insert(group);
1084254721Semaste            if (error.Fail())
1085254721Semaste                return error;
1086254721Semaste        }
1087254721Semaste    }
1088254721Semaste    return error;
1089254721Semaste}
1090