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