Home | History | Annotate | Download | only in Interpreter
      1 //===-- Args.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 // C Includes
     13 #include <getopt.h>
     14 #include <cstdlib>
     15 // C++ Includes
     16 // Other libraries and framework includes
     17 // Project includes
     18 #include "lldb/Interpreter/Args.h"
     19 #include "lldb/Core/Stream.h"
     20 #include "lldb/Core/StreamFile.h"
     21 #include "lldb/Core/StreamString.h"
     22 #include "lldb/DataFormatters/FormatManager.h"
     23 #include "lldb/Interpreter/Options.h"
     24 #include "lldb/Interpreter/CommandReturnObject.h"
     25 #include "lldb/Target/Process.h"
     26 //#include "lldb/Target/RegisterContext.h"
     27 #include "lldb/Target/StackFrame.h"
     28 #include "lldb/Target/Target.h"
     29 //#include "lldb/Target/Thread.h"
     30 
     31 using namespace lldb;
     32 using namespace lldb_private;
     33 
     34 //----------------------------------------------------------------------
     35 // Args constructor
     36 //----------------------------------------------------------------------
     37 Args::Args (const char *command) :
     38     m_args(),
     39     m_argv(),
     40     m_args_quote_char()
     41 {
     42     if (command)
     43         SetCommandString (command);
     44 }
     45 
     46 
     47 Args::Args (const char *command, size_t len) :
     48     m_args(),
     49     m_argv(),
     50     m_args_quote_char()
     51 {
     52     if (command && len)
     53         SetCommandString (command, len);
     54 }
     55 
     56 //----------------------------------------------------------------------
     57 // We have to be very careful on the copy constructor of this class
     58 // to make sure we copy all of the string values, but we can't copy the
     59 // rhs.m_argv into m_argv since it will point to the "const char *" c
     60 // strings in rhs.m_args. We need to copy the string list and update our
     61 // own m_argv appropriately.
     62 //----------------------------------------------------------------------
     63 Args::Args (const Args &rhs) :
     64     m_args (rhs.m_args),
     65     m_argv (),
     66     m_args_quote_char(rhs.m_args_quote_char)
     67 {
     68     UpdateArgvFromArgs();
     69 }
     70 
     71 //----------------------------------------------------------------------
     72 // We have to be very careful on the copy constructor of this class
     73 // to make sure we copy all of the string values, but we can't copy the
     74 // rhs.m_argv into m_argv since it will point to the "const char *" c
     75 // strings in rhs.m_args. We need to copy the string list and update our
     76 // own m_argv appropriately.
     77 //----------------------------------------------------------------------
     78 const Args &
     79 Args::operator= (const Args &rhs)
     80 {
     81     // Make sure we aren't assigning to self
     82     if (this != &rhs)
     83     {
     84         m_args = rhs.m_args;
     85         m_args_quote_char = rhs.m_args_quote_char;
     86         UpdateArgvFromArgs();
     87     }
     88     return *this;
     89 }
     90 
     91 //----------------------------------------------------------------------
     92 // Destructor
     93 //----------------------------------------------------------------------
     94 Args::~Args ()
     95 {
     96 }
     97 
     98 void
     99 Args::Dump (Stream *s)
    100 {
    101     const size_t argc = m_argv.size();
    102     for (size_t i=0; i<argc; ++i)
    103     {
    104         s->Indent();
    105         const char *arg_cstr = m_argv[i];
    106         if (arg_cstr)
    107             s->Printf("argv[%zi]=\"%s\"\n", i, arg_cstr);
    108         else
    109             s->Printf("argv[%zi]=NULL\n", i);
    110     }
    111     s->EOL();
    112 }
    113 
    114 bool
    115 Args::GetCommandString (std::string &command) const
    116 {
    117     command.clear();
    118     const size_t argc = GetArgumentCount();
    119     for (size_t i=0; i<argc; ++i)
    120     {
    121         if (i > 0)
    122             command += ' ';
    123         command += m_argv[i];
    124     }
    125     return argc > 0;
    126 }
    127 
    128 bool
    129 Args::GetQuotedCommandString (std::string &command) const
    130 {
    131     command.clear ();
    132     const size_t argc = GetArgumentCount();
    133     for (size_t i = 0; i < argc; ++i)
    134     {
    135         if (i > 0)
    136             command.append (1, ' ');
    137         char quote_char = GetArgumentQuoteCharAtIndex(i);
    138         if (quote_char)
    139         {
    140             command.append (1, quote_char);
    141             command.append (m_argv[i]);
    142             command.append (1, quote_char);
    143         }
    144         else
    145             command.append (m_argv[i]);
    146     }
    147     return argc > 0;
    148 }
    149 
    150 void
    151 Args::SetCommandString (const char *command, size_t len)
    152 {
    153     // Use std::string to make sure we get a NULL terminated string we can use
    154     // as "command" could point to a string within a large string....
    155     std::string null_terminated_command(command, len);
    156     SetCommandString(null_terminated_command.c_str());
    157 }
    158 
    159 void
    160 Args::SetCommandString (const char *command)
    161 {
    162     m_args.clear();
    163     m_argv.clear();
    164     m_args_quote_char.clear();
    165 
    166     if (command && command[0])
    167     {
    168         static const char *k_space_separators = " \t";
    169         static const char *k_space_separators_with_slash_and_quotes = " \t \\'\"";
    170         const char *arg_end = NULL;
    171         const char *arg_pos;
    172         for (arg_pos = command;
    173              arg_pos && arg_pos[0];
    174              arg_pos = arg_end)
    175         {
    176             // Skip any leading space separators
    177             const char *arg_start = ::strspn (arg_pos, k_space_separators) + arg_pos;
    178 
    179             // If there were only space separators to the end of the line, then
    180             // we're done.
    181             if (*arg_start == '\0')
    182                 break;
    183 
    184             // Arguments can be split into multiple discontiguous pieces,
    185             // for example:
    186             //  "Hello ""World"
    187             // this would result in a single argument "Hello World" (without/
    188             // the quotes) since the quotes would be removed and there is
    189             // not space between the strings. So we need to keep track of the
    190             // current start of each argument piece in "arg_piece_start"
    191             const char *arg_piece_start = arg_start;
    192             arg_pos = arg_piece_start;
    193 
    194             std::string arg;
    195             // Since we can have multiple quotes that form a single command
    196             // in a command like: "Hello "world'!' (which will make a single
    197             // argument "Hello world!") we remember the first quote character
    198             // we encounter and use that for the quote character.
    199             char first_quote_char = '\0';
    200             char quote_char = '\0';
    201             bool arg_complete = false;
    202 
    203             do
    204             {
    205                 arg_end = ::strcspn (arg_pos, k_space_separators_with_slash_and_quotes) + arg_pos;
    206 
    207                 switch (arg_end[0])
    208                 {
    209                 default:
    210                     assert (!"Unhandled case statement, we must handle this...");
    211                     break;
    212 
    213                 case '\0':
    214                     // End of C string
    215                     if (arg_piece_start && arg_piece_start[0])
    216                         arg.append (arg_piece_start);
    217                     arg_complete = true;
    218                     break;
    219 
    220                 case '\\':
    221                     // Backslash character
    222                     switch (arg_end[1])
    223                     {
    224                         case '\0':
    225                             arg.append (arg_piece_start);
    226                             ++arg_end;
    227                             arg_complete = true;
    228                             break;
    229 
    230                         default:
    231                             if (quote_char == '\0')
    232                             {
    233                                 arg.append (arg_piece_start, arg_end - arg_piece_start);
    234                                 if (arg_end[1] != '\0')
    235                                 {
    236                                     arg.append (arg_end + 1, 1);
    237                                     arg_pos = arg_end + 2;
    238                                     arg_piece_start = arg_pos;
    239                                 }
    240                             }
    241                             else
    242                                 arg_pos = arg_end + 2;
    243                             break;
    244                     }
    245                     break;
    246 
    247                 case '"':
    248                 case '\'':
    249                 case '`':
    250                     // Quote characters
    251                     if (quote_char)
    252                     {
    253                         // We found a quote character while inside a quoted
    254                         // character argument. If it matches our current quote
    255                         // character, this ends the effect of the quotes. If it
    256                         // doesn't we ignore it.
    257                         if (quote_char == arg_end[0])
    258                         {
    259                             arg.append (arg_piece_start, arg_end - arg_piece_start);
    260                             // Clear the quote character and let parsing
    261                             // continue (we need to watch for things like:
    262                             // "Hello ""World"
    263                             // "Hello "World
    264                             // "Hello "'World'
    265                             // All of which will result in a single argument "Hello World"
    266                             quote_char = '\0'; // Note that we are no longer inside quotes
    267                             arg_pos = arg_end + 1; // Skip the quote character
    268                             arg_piece_start = arg_pos; // Note we are starting from later in the string
    269                         }
    270                         else
    271                         {
    272                             // different quote, skip it and keep going
    273                             arg_pos = arg_end + 1;
    274                         }
    275                     }
    276                     else
    277                     {
    278                         // We found the start of a quote scope.
    279                         // Make sure there isn't a string that precedes
    280                         // the start of a quote scope like:
    281                         // Hello" World"
    282                         // If so, then add the "Hello" to the arg
    283                         if (arg_end > arg_piece_start)
    284                             arg.append (arg_piece_start, arg_end - arg_piece_start);
    285 
    286                         // Enter into a quote scope
    287                         quote_char = arg_end[0];
    288 
    289                         if (first_quote_char == '\0')
    290                             first_quote_char = quote_char;
    291 
    292                         arg_pos = arg_end;
    293                         ++arg_pos;                 // Skip the quote character
    294                         arg_piece_start = arg_pos; // Note we are starting from later in the string
    295 
    296                         // Skip till the next quote character
    297                         const char *end_quote = ::strchr (arg_piece_start, quote_char);
    298                         while (end_quote && end_quote[-1] == '\\')
    299                         {
    300                             // Don't skip the quote character if it is
    301                             // preceded by a '\' character
    302                             end_quote = ::strchr (end_quote + 1, quote_char);
    303                         }
    304 
    305                         if (end_quote)
    306                         {
    307                             if (end_quote > arg_piece_start)
    308                                 arg.append (arg_piece_start, end_quote - arg_piece_start);
    309 
    310                             // If the next character is a space or the end of
    311                             // string, this argument is complete...
    312                             if (end_quote[1] == ' ' || end_quote[1] == '\t' || end_quote[1] == '\0')
    313                             {
    314                                 arg_complete = true;
    315                                 arg_end = end_quote + 1;
    316                             }
    317                             else
    318                             {
    319                                 arg_pos = end_quote + 1;
    320                                 arg_piece_start = arg_pos;
    321                             }
    322                             quote_char = '\0';
    323                         }
    324                         else
    325                         {
    326                             // Consume the rest of the string as there was no terminating quote
    327                             arg.append(arg_piece_start);
    328                             arg_end = arg_piece_start + strlen(arg_piece_start);
    329                             arg_complete = true;
    330                         }
    331                     }
    332                     break;
    333 
    334                 case ' ':
    335                 case '\t':
    336                     if (quote_char)
    337                     {
    338                         // We are currently processing a quoted character and found
    339                         // a space character, skip any spaces and keep trying to find
    340                         // the end of the argument.
    341                         arg_pos = ::strspn (arg_end, k_space_separators) + arg_end;
    342                     }
    343                     else
    344                     {
    345                         // We are not inside any quotes, we just found a space after an
    346                         // argument
    347                         if (arg_end > arg_piece_start)
    348                             arg.append (arg_piece_start, arg_end - arg_piece_start);
    349                         arg_complete = true;
    350                     }
    351                     break;
    352                 }
    353             } while (!arg_complete);
    354 
    355             m_args.push_back(arg);
    356             m_args_quote_char.push_back (first_quote_char);
    357         }
    358         UpdateArgvFromArgs();
    359     }
    360 }
    361 
    362 void
    363 Args::UpdateArgsAfterOptionParsing()
    364 {
    365     // Now m_argv might be out of date with m_args, so we need to fix that
    366     arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
    367     arg_sstr_collection::iterator args_pos;
    368     arg_quote_char_collection::iterator quotes_pos;
    369 
    370     for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin();
    371          argv_pos != argv_end && args_pos != m_args.end();
    372          ++argv_pos)
    373     {
    374         const char *argv_cstr = *argv_pos;
    375         if (argv_cstr == NULL)
    376             break;
    377 
    378         while (args_pos != m_args.end())
    379         {
    380             const char *args_cstr = args_pos->c_str();
    381             if (args_cstr == argv_cstr)
    382             {
    383                 // We found the argument that matches the C string in the
    384                 // vector, so we can now look for the next one
    385                 ++args_pos;
    386                 ++quotes_pos;
    387                 break;
    388             }
    389             else
    390             {
    391                 quotes_pos = m_args_quote_char.erase (quotes_pos);
    392                 args_pos = m_args.erase (args_pos);
    393             }
    394         }
    395     }
    396 
    397     if (args_pos != m_args.end())
    398         m_args.erase (args_pos, m_args.end());
    399 
    400     if (quotes_pos != m_args_quote_char.end())
    401         m_args_quote_char.erase (quotes_pos, m_args_quote_char.end());
    402 }
    403 
    404 void
    405 Args::UpdateArgvFromArgs()
    406 {
    407     m_argv.clear();
    408     arg_sstr_collection::const_iterator pos, end = m_args.end();
    409     for (pos = m_args.begin(); pos != end; ++pos)
    410         m_argv.push_back(pos->c_str());
    411     m_argv.push_back(NULL);
    412     // Make sure we have enough arg quote chars in the array
    413     if (m_args_quote_char.size() < m_args.size())
    414         m_args_quote_char.resize (m_argv.size());
    415 }
    416 
    417 size_t
    418 Args::GetArgumentCount() const
    419 {
    420     if (m_argv.empty())
    421         return 0;
    422     return m_argv.size() - 1;
    423 }
    424 
    425 const char *
    426 Args::GetArgumentAtIndex (size_t idx) const
    427 {
    428     if (idx < m_argv.size())
    429         return m_argv[idx];
    430     return NULL;
    431 }
    432 
    433 char
    434 Args::GetArgumentQuoteCharAtIndex (size_t idx) const
    435 {
    436     if (idx < m_args_quote_char.size())
    437         return m_args_quote_char[idx];
    438     return '\0';
    439 }
    440 
    441 char **
    442 Args::GetArgumentVector()
    443 {
    444     if (!m_argv.empty())
    445         return (char **)&m_argv[0];
    446     return NULL;
    447 }
    448 
    449 const char **
    450 Args::GetConstArgumentVector() const
    451 {
    452     if (!m_argv.empty())
    453         return (const char **)&m_argv[0];
    454     return NULL;
    455 }
    456 
    457 void
    458 Args::Shift ()
    459 {
    460     // Don't pop the last NULL terminator from the argv array
    461     if (m_argv.size() > 1)
    462     {
    463         m_argv.erase(m_argv.begin());
    464         m_args.pop_front();
    465         if (!m_args_quote_char.empty())
    466             m_args_quote_char.erase(m_args_quote_char.begin());
    467     }
    468 }
    469 
    470 const char *
    471 Args::Unshift (const char *arg_cstr, char quote_char)
    472 {
    473     m_args.push_front(arg_cstr);
    474     m_argv.insert(m_argv.begin(), m_args.front().c_str());
    475     m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
    476     return GetArgumentAtIndex (0);
    477 }
    478 
    479 void
    480 Args::AppendArguments (const Args &rhs)
    481 {
    482     const size_t rhs_argc = rhs.GetArgumentCount();
    483     for (size_t i=0; i<rhs_argc; ++i)
    484         AppendArgument(rhs.GetArgumentAtIndex(i));
    485 }
    486 
    487 void
    488 Args::AppendArguments (const char **argv)
    489 {
    490     if (argv)
    491     {
    492         for (uint32_t i=0; argv[i]; ++i)
    493             AppendArgument(argv[i]);
    494     }
    495 }
    496 
    497 const char *
    498 Args::AppendArgument (const char *arg_cstr, char quote_char)
    499 {
    500     return InsertArgumentAtIndex (GetArgumentCount(), arg_cstr, quote_char);
    501 }
    502 
    503 const char *
    504 Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
    505 {
    506     // Since we are using a std::list to hold onto the copied C string and
    507     // we don't have direct access to the elements, we have to iterate to
    508     // find the value.
    509     arg_sstr_collection::iterator pos, end = m_args.end();
    510     size_t i = idx;
    511     for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
    512         --i;
    513 
    514     pos = m_args.insert(pos, arg_cstr);
    515 
    516     if (idx >= m_args_quote_char.size())
    517     {
    518         m_args_quote_char.resize(idx + 1);
    519         m_args_quote_char[idx] = quote_char;
    520     }
    521     else
    522         m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
    523 
    524     UpdateArgvFromArgs();
    525     return GetArgumentAtIndex(idx);
    526 }
    527 
    528 const char *
    529 Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
    530 {
    531     // Since we are using a std::list to hold onto the copied C string and
    532     // we don't have direct access to the elements, we have to iterate to
    533     // find the value.
    534     arg_sstr_collection::iterator pos, end = m_args.end();
    535     size_t i = idx;
    536     for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
    537         --i;
    538 
    539     if (pos != end)
    540     {
    541         pos->assign(arg_cstr);
    542         assert(idx < m_argv.size() - 1);
    543         m_argv[idx] = pos->c_str();
    544         if (idx >= m_args_quote_char.size())
    545             m_args_quote_char.resize(idx + 1);
    546         m_args_quote_char[idx] = quote_char;
    547         return GetArgumentAtIndex(idx);
    548     }
    549     return NULL;
    550 }
    551 
    552 void
    553 Args::DeleteArgumentAtIndex (size_t idx)
    554 {
    555     // Since we are using a std::list to hold onto the copied C string and
    556     // we don't have direct access to the elements, we have to iterate to
    557     // find the value.
    558     arg_sstr_collection::iterator pos, end = m_args.end();
    559     size_t i = idx;
    560     for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
    561         --i;
    562 
    563     if (pos != end)
    564     {
    565         m_args.erase (pos);
    566         assert(idx < m_argv.size() - 1);
    567         m_argv.erase(m_argv.begin() + idx);
    568         if (idx < m_args_quote_char.size())
    569             m_args_quote_char.erase(m_args_quote_char.begin() + idx);
    570     }
    571 }
    572 
    573 void
    574 Args::SetArguments (size_t argc, const char **argv)
    575 {
    576     // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
    577     // no need to clear it here.
    578     m_args.clear();
    579     m_args_quote_char.clear();
    580 
    581     // First copy each string
    582     for (size_t i=0; i<argc; ++i)
    583     {
    584         m_args.push_back (argv[i]);
    585         if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
    586             m_args_quote_char.push_back (argv[i][0]);
    587         else
    588             m_args_quote_char.push_back ('\0');
    589     }
    590 
    591     UpdateArgvFromArgs();
    592 }
    593 
    594 void
    595 Args::SetArguments (const char **argv)
    596 {
    597     // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
    598     // no need to clear it here.
    599     m_args.clear();
    600     m_args_quote_char.clear();
    601 
    602     if (argv)
    603     {
    604         // First copy each string
    605         for (size_t i=0; argv[i]; ++i)
    606         {
    607             m_args.push_back (argv[i]);
    608             if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
    609                 m_args_quote_char.push_back (argv[i][0]);
    610             else
    611                 m_args_quote_char.push_back ('\0');
    612         }
    613     }
    614 
    615     UpdateArgvFromArgs();
    616 }
    617 
    618 
    619 Error
    620 Args::ParseOptions (Options &options)
    621 {
    622     StreamString sstr;
    623     Error error;
    624     struct option *long_options = options.GetLongOptions();
    625     if (long_options == NULL)
    626     {
    627         error.SetErrorStringWithFormat("invalid long options");
    628         return error;
    629     }
    630 
    631     for (int i=0; long_options[i].name != NULL; ++i)
    632     {
    633         if (long_options[i].flag == NULL)
    634         {
    635             if (isprint8(long_options[i].val))
    636             {
    637                 sstr << (char)long_options[i].val;
    638                 switch (long_options[i].has_arg)
    639                 {
    640                 default:
    641                 case no_argument:                       break;
    642                 case required_argument: sstr << ':';    break;
    643                 case optional_argument: sstr << "::";   break;
    644                 }
    645             }
    646         }
    647     }
    648 #ifdef __GLIBC__
    649     optind = 0;
    650 #else
    651     optreset = 1;
    652     optind = 1;
    653 #endif
    654     int val;
    655     while (1)
    656     {
    657         int long_options_index = -1;
    658         val = ::getopt_long_only(GetArgumentCount(),
    659                                  GetArgumentVector(),
    660                                  sstr.GetData(),
    661                                  long_options,
    662                                  &long_options_index);
    663         if (val == -1)
    664             break;
    665 
    666         // Did we get an error?
    667         if (val == '?')
    668         {
    669             error.SetErrorStringWithFormat("unknown or ambiguous option");
    670             break;
    671         }
    672         // The option auto-set itself
    673         if (val == 0)
    674             continue;
    675 
    676         ((Options *) &options)->OptionSeen (val);
    677 
    678         // Lookup the long option index
    679         if (long_options_index == -1)
    680         {
    681             for (int i=0;
    682                  long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
    683                  ++i)
    684             {
    685                 if (long_options[i].val == val)
    686                 {
    687                     long_options_index = i;
    688                     break;
    689                 }
    690             }
    691         }
    692         // Call the callback with the option
    693         if (long_options_index >= 0)
    694         {
    695             error = options.SetOptionValue(long_options_index,
    696                                            long_options[long_options_index].has_arg == no_argument ? NULL : optarg);
    697         }
    698         else
    699         {
    700             error.SetErrorStringWithFormat("invalid option with value '%i'", val);
    701         }
    702         if (error.Fail())
    703             break;
    704     }
    705 
    706     // Update our ARGV now that get options has consumed all the options
    707     m_argv.erase(m_argv.begin(), m_argv.begin() + optind);
    708     UpdateArgsAfterOptionParsing ();
    709     return error;
    710 }
    711 
    712 void
    713 Args::Clear ()
    714 {
    715     m_args.clear ();
    716     m_argv.clear ();
    717     m_args_quote_char.clear();
    718 }
    719 
    720 int32_t
    721 Args::StringToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
    722 {
    723     if (s && s[0])
    724     {
    725         char *end = NULL;
    726         const long sval = ::strtol (s, &end, base);
    727         if (*end == '\0')
    728         {
    729             if (success_ptr)
    730                 *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN));
    731             return (int32_t)sval; // All characters were used, return the result
    732         }
    733     }
    734     if (success_ptr) *success_ptr = false;
    735     return fail_value;
    736 }
    737 
    738 uint32_t
    739 Args::StringToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
    740 {
    741     if (s && s[0])
    742     {
    743         char *end = NULL;
    744         const unsigned long uval = ::strtoul (s, &end, base);
    745         if (*end == '\0')
    746         {
    747             if (success_ptr)
    748                 *success_ptr = (uval <= UINT32_MAX);
    749             return (uint32_t)uval; // All characters were used, return the result
    750         }
    751     }
    752     if (success_ptr) *success_ptr = false;
    753     return fail_value;
    754 }
    755 
    756 
    757 int64_t
    758 Args::StringToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
    759 {
    760     if (s && s[0])
    761     {
    762         char *end = NULL;
    763         int64_t uval = ::strtoll (s, &end, base);
    764         if (*end == '\0')
    765         {
    766             if (success_ptr) *success_ptr = true;
    767             return uval; // All characters were used, return the result
    768         }
    769     }
    770     if (success_ptr) *success_ptr = false;
    771     return fail_value;
    772 }
    773 
    774 uint64_t
    775 Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
    776 {
    777     if (s && s[0])
    778     {
    779         char *end = NULL;
    780         uint64_t uval = ::strtoull (s, &end, base);
    781         if (*end == '\0')
    782         {
    783             if (success_ptr) *success_ptr = true;
    784             return uval; // All characters were used, return the result
    785         }
    786     }
    787     if (success_ptr) *success_ptr = false;
    788     return fail_value;
    789 }
    790 
    791 lldb::addr_t
    792 Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr)
    793 {
    794     bool error_set = false;
    795     if (s && s[0])
    796     {
    797         char *end = NULL;
    798         lldb::addr_t addr = ::strtoull (s, &end, 0);
    799         if (*end == '\0')
    800         {
    801             if (error_ptr)
    802                 error_ptr->Clear();
    803             return addr; // All characters were used, return the result
    804         }
    805         // Try base 16 with no prefix...
    806         addr = ::strtoull (s, &end, 16);
    807         if (*end == '\0')
    808         {
    809             if (error_ptr)
    810                 error_ptr->Clear();
    811             return addr; // All characters were used, return the result
    812         }
    813 
    814         if (exe_ctx)
    815         {
    816             Target *target = exe_ctx->GetTargetPtr();
    817             if (target)
    818             {
    819                 lldb::ValueObjectSP valobj_sp;
    820                 EvaluateExpressionOptions options;
    821                 options.SetCoerceToId(false);
    822                 options.SetUnwindOnError(true);
    823                 options.SetKeepInMemory(false);
    824                 options.SetRunOthers(true);
    825 
    826                 ExecutionResults expr_result = target->EvaluateExpression(s,
    827                                                                           exe_ctx->GetFramePtr(),
    828                                                                           valobj_sp,
    829                                                                           options);
    830 
    831                 bool success = false;
    832                 if (expr_result == eExecutionCompleted)
    833                 {
    834                     // Get the address to watch.
    835                     addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
    836                     if (success)
    837                     {
    838                         if (error_ptr)
    839                             error_ptr->Clear();
    840                         return addr;
    841                     }
    842                     else
    843                     {
    844                         if (error_ptr)
    845                         {
    846                             error_set = true;
    847                             error_ptr->SetErrorStringWithFormat("address expression \"%s\" resulted in a value whose type can't be converted to an address: %s", s, valobj_sp->GetTypeName().GetCString());
    848                         }
    849                     }
    850 
    851                 }
    852                 else
    853                 {
    854                     // Since the compiler can't handle things like "main + 12" we should
    855                     // try to do this for now. The compliler doesn't like adding offsets
    856                     // to function pointer types.
    857                     static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
    858                     RegularExpression::Match regex_match(3);
    859                     if (g_symbol_plus_offset_regex.Execute(s, &regex_match))
    860                     {
    861                         uint64_t offset = 0;
    862                         bool add = true;
    863                         std::string name;
    864                         std::string str;
    865                         if (regex_match.GetMatchAtIndex(s, 1, name))
    866                         {
    867                             if (regex_match.GetMatchAtIndex(s, 2, str))
    868                             {
    869                                 add = str[0] == '+';
    870 
    871                                 if (regex_match.GetMatchAtIndex(s, 3, str))
    872                                 {
    873                                     offset = Args::StringToUInt64(str.c_str(), 0, 0, &success);
    874 
    875                                     if (success)
    876                                     {
    877                                         Error error;
    878                                         addr = StringToAddress (exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error);
    879                                         if (addr != LLDB_INVALID_ADDRESS)
    880                                         {
    881                                             if (add)
    882                                                 return addr + offset;
    883                                             else
    884                                                 return addr - offset;
    885                                         }
    886                                     }
    887                                 }
    888                             }
    889                         }
    890                     }
    891 
    892                     if (error_ptr)
    893                     {
    894                         error_set = true;
    895                         error_ptr->SetErrorStringWithFormat("address expression \"%s\" evaluation failed", s);
    896                     }
    897                 }
    898             }
    899         }
    900     }
    901     if (error_ptr)
    902     {
    903         if (!error_set)
    904             error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", s);
    905     }
    906     return fail_value;
    907 }
    908 
    909 const char *
    910 Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null_if_empty)
    911 {
    912     static const char *k_white_space = " \t\v";
    913     if (!s.empty())
    914     {
    915         if (leading)
    916         {
    917             size_t pos = s.find_first_not_of (k_white_space);
    918             if (pos == std::string::npos)
    919                 s.clear();
    920             else if (pos > 0)
    921                 s.erase(0, pos);
    922         }
    923 
    924         if (trailing)
    925         {
    926             size_t rpos = s.find_last_not_of(k_white_space);
    927             if (rpos != std::string::npos && rpos + 1 < s.size())
    928                 s.erase(rpos + 1);
    929         }
    930     }
    931     if (return_null_if_empty && s.empty())
    932         return NULL;
    933     return s.c_str();
    934 }
    935 
    936 bool
    937 Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
    938 {
    939     if (s && s[0])
    940     {
    941         if (::strcasecmp (s, "false") == 0 ||
    942             ::strcasecmp (s, "off") == 0 ||
    943             ::strcasecmp (s, "no") == 0 ||
    944                 ::strcmp (s, "0") == 0)
    945         {
    946             if (success_ptr)
    947                 *success_ptr = true;
    948             return false;
    949         }
    950         else
    951         if (::strcasecmp (s, "true") == 0 ||
    952             ::strcasecmp (s, "on") == 0 ||
    953             ::strcasecmp (s, "yes") == 0 ||
    954                 ::strcmp (s, "1") == 0)
    955         {
    956             if (success_ptr) *success_ptr = true;
    957             return true;
    958         }
    959     }
    960     if (success_ptr) *success_ptr = false;
    961     return fail_value;
    962 }
    963 
    964 const char *
    965 Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update)
    966 {
    967     major = UINT32_MAX;
    968     minor = UINT32_MAX;
    969     update = UINT32_MAX;
    970 
    971     if (s && s[0])
    972     {
    973         char *pos = NULL;
    974         unsigned long uval32 = ::strtoul (s, &pos, 0);
    975         if (pos == s)
    976             return s;
    977         major = uval32;
    978         if (*pos == '\0')
    979         {
    980             return pos;   // Decoded major and got end of string
    981         }
    982         else if (*pos == '.')
    983         {
    984             const char *minor_cstr = pos + 1;
    985             uval32 = ::strtoul (minor_cstr, &pos, 0);
    986             if (pos == minor_cstr)
    987                 return pos; // Didn't get any digits for the minor version...
    988             minor = uval32;
    989             if (*pos == '.')
    990             {
    991                 const char *update_cstr = pos + 1;
    992                 uval32 = ::strtoul (update_cstr, &pos, 0);
    993                 if (pos == update_cstr)
    994                     return pos;
    995                 update = uval32;
    996             }
    997             return pos;
    998         }
    999     }
   1000     return 0;
   1001 }
   1002 
   1003 const char *
   1004 Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
   1005 {
   1006     safe_arg.assign (unsafe_arg);
   1007     size_t prev_pos = 0;
   1008     while (prev_pos < safe_arg.size())
   1009     {
   1010         // Escape spaces and quotes
   1011         size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
   1012         if (pos != std::string::npos)
   1013         {
   1014             safe_arg.insert (pos, 1, '\\');
   1015             prev_pos = pos + 2;
   1016         }
   1017         else
   1018             break;
   1019     }
   1020     return safe_arg.c_str();
   1021 }
   1022 
   1023 
   1024 int64_t
   1025 Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
   1026 {
   1027     if (enum_values)
   1028     {
   1029         if (s && s[0])
   1030         {
   1031             for (int i = 0; enum_values[i].string_value != NULL ; i++)
   1032             {
   1033                 if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
   1034                 {
   1035                     error.Clear();
   1036                     return enum_values[i].value;
   1037                 }
   1038             }
   1039         }
   1040 
   1041         StreamString strm;
   1042         strm.PutCString ("invalid enumeration value, valid values are: ");
   1043         for (int i = 0; enum_values[i].string_value != NULL; i++)
   1044         {
   1045             strm.Printf ("%s\"%s\"",
   1046                          i > 0 ? ", " : "",
   1047                          enum_values[i].string_value);
   1048         }
   1049         error.SetErrorString(strm.GetData());
   1050     }
   1051     else
   1052     {
   1053         error.SetErrorString ("invalid enumeration argument");
   1054     }
   1055     return fail_value;
   1056 }
   1057 
   1058 ScriptLanguage
   1059 Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
   1060 {
   1061     if (s && s[0])
   1062     {
   1063         if ((::strcasecmp (s, "python") == 0) ||
   1064             (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
   1065         {
   1066             if (success_ptr) *success_ptr = true;
   1067             return eScriptLanguagePython;
   1068         }
   1069         if (::strcasecmp (s, "none"))
   1070         {
   1071             if (success_ptr) *success_ptr = true;
   1072             return eScriptLanguageNone;
   1073         }
   1074     }
   1075     if (success_ptr) *success_ptr = false;
   1076     return fail_value;
   1077 }
   1078 
   1079 Error
   1080 Args::StringToFormat
   1081 (
   1082     const char *s,
   1083     lldb::Format &format,
   1084     size_t *byte_size_ptr
   1085 )
   1086 {
   1087     format = eFormatInvalid;
   1088     Error error;
   1089 
   1090     if (s && s[0])
   1091     {
   1092         if (byte_size_ptr)
   1093         {
   1094             if (isdigit (s[0]))
   1095             {
   1096                 char *format_char = NULL;
   1097                 unsigned long byte_size = ::strtoul (s, &format_char, 0);
   1098                 if (byte_size != ULONG_MAX)
   1099                     *byte_size_ptr = byte_size;
   1100                 s = format_char;
   1101             }
   1102             else
   1103                 *byte_size_ptr = 0;
   1104         }
   1105 
   1106         const bool partial_match_ok = true;
   1107         if (!FormatManager::GetFormatFromCString (s, partial_match_ok, format))
   1108         {
   1109             StreamString error_strm;
   1110             error_strm.Printf ("Invalid format character or name '%s'. Valid values are:\n", s);
   1111             for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
   1112             {
   1113                 char format_char = FormatManager::GetFormatAsFormatChar(f);
   1114                 if (format_char)
   1115                     error_strm.Printf ("'%c' or ", format_char);
   1116 
   1117                 error_strm.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
   1118                 error_strm.EOL();
   1119             }
   1120 
   1121             if (byte_size_ptr)
   1122                 error_strm.PutCString ("An optional byte size can precede the format character.\n");
   1123             error.SetErrorString(error_strm.GetString().c_str());
   1124         }
   1125 
   1126         if (error.Fail())
   1127             return error;
   1128     }
   1129     else
   1130     {
   1131         error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
   1132     }
   1133     return error;
   1134 }
   1135 
   1136 lldb::Encoding
   1137 Args::StringToEncoding (const char *s, lldb::Encoding fail_value)
   1138 {
   1139     if (s && s[0])
   1140     {
   1141         if (strcmp(s, "uint") == 0)
   1142             return eEncodingUint;
   1143         else if (strcmp(s, "sint") == 0)
   1144             return eEncodingSint;
   1145         else if (strcmp(s, "ieee754") == 0)
   1146             return eEncodingIEEE754;
   1147         else if (strcmp(s, "vector") == 0)
   1148             return eEncodingVector;
   1149     }
   1150     return fail_value;
   1151 }
   1152 
   1153 uint32_t
   1154 Args::StringToGenericRegister (const char *s)
   1155 {
   1156     if (s && s[0])
   1157     {
   1158         if (strcmp(s, "pc") == 0)
   1159             return LLDB_REGNUM_GENERIC_PC;
   1160         else if (strcmp(s, "sp") == 0)
   1161             return LLDB_REGNUM_GENERIC_SP;
   1162         else if (strcmp(s, "fp") == 0)
   1163             return LLDB_REGNUM_GENERIC_FP;
   1164         else if (strcmp(s, "ra") == 0)
   1165             return LLDB_REGNUM_GENERIC_RA;
   1166         else if (strcmp(s, "flags") == 0)
   1167             return LLDB_REGNUM_GENERIC_FLAGS;
   1168         else if (strncmp(s, "arg", 3) == 0)
   1169         {
   1170             if (s[3] && s[4] == '\0')
   1171             {
   1172                 switch (s[3])
   1173                 {
   1174                     case '1': return LLDB_REGNUM_GENERIC_ARG1;
   1175                     case '2': return LLDB_REGNUM_GENERIC_ARG2;
   1176                     case '3': return LLDB_REGNUM_GENERIC_ARG3;
   1177                     case '4': return LLDB_REGNUM_GENERIC_ARG4;
   1178                     case '5': return LLDB_REGNUM_GENERIC_ARG5;
   1179                     case '6': return LLDB_REGNUM_GENERIC_ARG6;
   1180                     case '7': return LLDB_REGNUM_GENERIC_ARG7;
   1181                     case '8': return LLDB_REGNUM_GENERIC_ARG8;
   1182                 }
   1183             }
   1184         }
   1185     }
   1186     return LLDB_INVALID_REGNUM;
   1187 }
   1188 
   1189 
   1190 void
   1191 Args::LongestCommonPrefix (std::string &common_prefix)
   1192 {
   1193     arg_sstr_collection::iterator pos, end = m_args.end();
   1194     pos = m_args.begin();
   1195     if (pos == end)
   1196         common_prefix.clear();
   1197     else
   1198         common_prefix = (*pos);
   1199 
   1200     for (++pos; pos != end; ++pos)
   1201     {
   1202         size_t new_size = (*pos).size();
   1203 
   1204         // First trim common_prefix if it is longer than the current element:
   1205         if (common_prefix.size() > new_size)
   1206             common_prefix.erase (new_size);
   1207 
   1208         // Then trim it at the first disparity:
   1209 
   1210         for (size_t i = 0; i < common_prefix.size(); i++)
   1211         {
   1212             if ((*pos)[i]  != common_prefix[i])
   1213             {
   1214                 common_prefix.erase(i);
   1215                 break;
   1216             }
   1217         }
   1218 
   1219         // If we've emptied the common prefix, we're done.
   1220         if (common_prefix.empty())
   1221             break;
   1222     }
   1223 }
   1224 
   1225 size_t
   1226 Args::FindArgumentIndexForOption (struct option *long_options, int long_options_index)
   1227 {
   1228     char short_buffer[3];
   1229     char long_buffer[255];
   1230     ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
   1231     ::snprintf (long_buffer, sizeof (long_buffer),  "--%s", long_options[long_options_index].name);
   1232     size_t end = GetArgumentCount ();
   1233     size_t idx = 0;
   1234     while (idx < end)
   1235     {
   1236         if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0)
   1237             || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0))
   1238             {
   1239                 return idx;
   1240             }
   1241         ++idx;
   1242     }
   1243 
   1244     return end;
   1245 }
   1246 
   1247 bool
   1248 Args::IsPositionalArgument (const char *arg)
   1249 {
   1250     if (arg == NULL)
   1251         return false;
   1252 
   1253     bool is_positional = true;
   1254     char *cptr = (char *) arg;
   1255 
   1256     if (cptr[0] == '%')
   1257     {
   1258         ++cptr;
   1259         while (isdigit (cptr[0]))
   1260             ++cptr;
   1261         if (cptr[0] != '\0')
   1262             is_positional = false;
   1263     }
   1264     else
   1265         is_positional = false;
   1266 
   1267     return is_positional;
   1268 }
   1269 
   1270 void
   1271 Args::ParseAliasOptions (Options &options,
   1272                          CommandReturnObject &result,
   1273                          OptionArgVector *option_arg_vector,
   1274                          std::string &raw_input_string)
   1275 {
   1276     StreamString sstr;
   1277     int i;
   1278     struct option *long_options = options.GetLongOptions();
   1279 
   1280     if (long_options == NULL)
   1281     {
   1282         result.AppendError ("invalid long options");
   1283         result.SetStatus (eReturnStatusFailed);
   1284         return;
   1285     }
   1286 
   1287     for (i = 0; long_options[i].name != NULL; ++i)
   1288     {
   1289         if (long_options[i].flag == NULL)
   1290         {
   1291             sstr << (char) long_options[i].val;
   1292             switch (long_options[i].has_arg)
   1293             {
   1294                 default:
   1295                 case no_argument:
   1296                     break;
   1297                 case required_argument:
   1298                     sstr << ":";
   1299                     break;
   1300                 case optional_argument:
   1301                     sstr << "::";
   1302                     break;
   1303             }
   1304         }
   1305     }
   1306 
   1307 #ifdef __GLIBC__
   1308     optind = 0;
   1309 #else
   1310     optreset = 1;
   1311     optind = 1;
   1312 #endif
   1313     int val;
   1314     while (1)
   1315     {
   1316         int long_options_index = -1;
   1317         val = ::getopt_long_only (GetArgumentCount(),
   1318                                   GetArgumentVector(),
   1319                                   sstr.GetData(),
   1320                                   long_options,
   1321                                   &long_options_index);
   1322 
   1323         if (val == -1)
   1324             break;
   1325 
   1326         if (val == '?')
   1327         {
   1328             result.AppendError ("unknown or ambiguous option");
   1329             result.SetStatus (eReturnStatusFailed);
   1330             break;
   1331         }
   1332 
   1333         if (val == 0)
   1334             continue;
   1335 
   1336         ((Options *) &options)->OptionSeen (val);
   1337 
   1338         // Look up the long option index
   1339         if (long_options_index == -1)
   1340         {
   1341             for (int j = 0;
   1342                  long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
   1343                  ++j)
   1344             {
   1345                 if (long_options[j].val == val)
   1346                 {
   1347                     long_options_index = j;
   1348                     break;
   1349                 }
   1350             }
   1351         }
   1352 
   1353         // See if the option takes an argument, and see if one was supplied.
   1354         if (long_options_index >= 0)
   1355         {
   1356             StreamString option_str;
   1357             option_str.Printf ("-%c", val);
   1358 
   1359             switch (long_options[long_options_index].has_arg)
   1360             {
   1361             case no_argument:
   1362                 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
   1363                                                              OptionArgValue (no_argument, "<no-argument>")));
   1364                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
   1365                 break;
   1366             case required_argument:
   1367                 if (optarg != NULL)
   1368                 {
   1369                     option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
   1370                                                                  OptionArgValue (required_argument,
   1371                                                                                  std::string (optarg))));
   1372                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
   1373                 }
   1374                 else
   1375                 {
   1376                     result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
   1377                                                  option_str.GetData());
   1378                     result.SetStatus (eReturnStatusFailed);
   1379                 }
   1380                 break;
   1381             case optional_argument:
   1382                 if (optarg != NULL)
   1383                 {
   1384                     option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
   1385                                                                  OptionArgValue (optional_argument,
   1386                                                                                  std::string (optarg))));
   1387                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
   1388                 }
   1389                 else
   1390                 {
   1391                     option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
   1392                                                                  OptionArgValue (optional_argument, "<no-argument>")));
   1393                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
   1394                 }
   1395                 break;
   1396             default:
   1397                 result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", val);
   1398                 result.SetStatus (eReturnStatusFailed);
   1399                 break;
   1400             }
   1401         }
   1402         else
   1403         {
   1404             result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", val);
   1405             result.SetStatus (eReturnStatusFailed);
   1406         }
   1407 
   1408         if (long_options_index >= 0)
   1409         {
   1410             // Find option in the argument list; also see if it was supposed to take an argument and if one was
   1411             // supplied.  Remove option (and argument, if given) from the argument list.  Also remove them from
   1412             // the raw_input_string, if one was passed in.
   1413             size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
   1414             if (idx < GetArgumentCount())
   1415             {
   1416                 if (raw_input_string.size() > 0)
   1417                 {
   1418                     const char *tmp_arg = GetArgumentAtIndex (idx);
   1419                     size_t pos = raw_input_string.find (tmp_arg);
   1420                     if (pos != std::string::npos)
   1421                         raw_input_string.erase (pos, strlen (tmp_arg));
   1422                 }
   1423                 ReplaceArgumentAtIndex (idx, "");
   1424                 if ((long_options[long_options_index].has_arg != no_argument)
   1425                     && (optarg != NULL)
   1426                     && (idx+1 < GetArgumentCount())
   1427                     && (strcmp (optarg, GetArgumentAtIndex(idx+1)) == 0))
   1428                 {
   1429                     if (raw_input_string.size() > 0)
   1430                     {
   1431                         const char *tmp_arg = GetArgumentAtIndex (idx+1);
   1432                         size_t pos = raw_input_string.find (tmp_arg);
   1433                         if (pos != std::string::npos)
   1434                             raw_input_string.erase (pos, strlen (tmp_arg));
   1435                     }
   1436                     ReplaceArgumentAtIndex (idx+1, "");
   1437                 }
   1438             }
   1439         }
   1440 
   1441         if (!result.Succeeded())
   1442             break;
   1443     }
   1444 }
   1445 
   1446 void
   1447 Args::ParseArgsForCompletion
   1448 (
   1449     Options &options,
   1450     OptionElementVector &option_element_vector,
   1451     uint32_t cursor_index
   1452 )
   1453 {
   1454     StreamString sstr;
   1455     struct option *long_options = options.GetLongOptions();
   1456     option_element_vector.clear();
   1457 
   1458     if (long_options == NULL)
   1459     {
   1460         return;
   1461     }
   1462 
   1463     // Leading : tells getopt to return a : for a missing option argument AND
   1464     // to suppress error messages.
   1465 
   1466     sstr << ":";
   1467     for (int i = 0; long_options[i].name != NULL; ++i)
   1468     {
   1469         if (long_options[i].flag == NULL)
   1470         {
   1471             sstr << (char) long_options[i].val;
   1472             switch (long_options[i].has_arg)
   1473             {
   1474                 default:
   1475                 case no_argument:
   1476                     break;
   1477                 case required_argument:
   1478                     sstr << ":";
   1479                     break;
   1480                 case optional_argument:
   1481                     sstr << "::";
   1482                     break;
   1483             }
   1484         }
   1485     }
   1486 
   1487 #ifdef __GLIBC__
   1488     optind = 0;
   1489 #else
   1490     optreset = 1;
   1491     optind = 1;
   1492 #endif
   1493     opterr = 0;
   1494 
   1495     int val;
   1496     const OptionDefinition *opt_defs = options.GetDefinitions();
   1497 
   1498     // Fooey... getopt_long_only permutes the GetArgumentVector to move the options to the front.
   1499     // So we have to build another Arg and pass that to getopt_long_only so it doesn't
   1500     // change the one we have.
   1501 
   1502     std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
   1503 
   1504     bool failed_once = false;
   1505     uint32_t dash_dash_pos = -1;
   1506 
   1507     while (1)
   1508     {
   1509         bool missing_argument = false;
   1510         int long_options_index = -1;
   1511 
   1512         val = ::getopt_long_only (dummy_vec.size() - 1,
   1513                                   (char *const *) &dummy_vec.front(),
   1514                                   sstr.GetData(),
   1515                                   long_options,
   1516                                   &long_options_index);
   1517 
   1518         if (val == -1)
   1519         {
   1520             // When we're completing a "--" which is the last option on line,
   1521             if (failed_once)
   1522                 break;
   1523 
   1524             failed_once = true;
   1525 
   1526             // If this is a bare  "--" we mark it as such so we can complete it successfully later.
   1527             // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
   1528             // user might want to complete options by long name.  I make this work by checking whether the
   1529             // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
   1530             // I let it pass to getopt_long_only which will terminate the option parsing.
   1531             // Note, in either case we continue parsing the line so we can figure out what other options
   1532             // were passed.  This will be useful when we come to restricting completions based on what other
   1533             // options we've seen on the line.
   1534 
   1535             if (optind < dummy_vec.size() - 1
   1536                 && (strcmp (dummy_vec[optind-1], "--") == 0))
   1537             {
   1538                 dash_dash_pos = optind - 1;
   1539                 if (optind - 1 == cursor_index)
   1540                 {
   1541                     option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, optind - 1,
   1542                                                                    OptionArgElement::eBareDoubleDash));
   1543                     continue;
   1544                 }
   1545                 else
   1546                     break;
   1547             }
   1548             else
   1549                 break;
   1550         }
   1551         else if (val == '?')
   1552         {
   1553             option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
   1554                                                                OptionArgElement::eUnrecognizedArg));
   1555             continue;
   1556         }
   1557         else if (val == 0)
   1558         {
   1559             continue;
   1560         }
   1561         else if (val == ':')
   1562         {
   1563             // This is a missing argument.
   1564             val = optopt;
   1565             missing_argument = true;
   1566         }
   1567 
   1568         ((Options *) &options)->OptionSeen (val);
   1569 
   1570         // Look up the long option index
   1571         if (long_options_index == -1)
   1572         {
   1573             for (int j = 0;
   1574                  long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
   1575                  ++j)
   1576             {
   1577                 if (long_options[j].val == val)
   1578                 {
   1579                     long_options_index = j;
   1580                     break;
   1581                 }
   1582             }
   1583         }
   1584 
   1585         // See if the option takes an argument, and see if one was supplied.
   1586         if (long_options_index >= 0)
   1587         {
   1588             int opt_defs_index = -1;
   1589             for (int i = 0; ; i++)
   1590             {
   1591                 if (opt_defs[i].short_option == 0)
   1592                     break;
   1593                 else if (opt_defs[i].short_option == val)
   1594                 {
   1595                     opt_defs_index = i;
   1596                     break;
   1597                 }
   1598             }
   1599 
   1600             switch (long_options[long_options_index].has_arg)
   1601             {
   1602             case no_argument:
   1603                 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, 0));
   1604                 break;
   1605             case required_argument:
   1606                 if (optarg != NULL)
   1607                 {
   1608                     int arg_index;
   1609                     if (missing_argument)
   1610                         arg_index = -1;
   1611                     else
   1612                         arg_index = optind - 1;
   1613 
   1614                     option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, arg_index));
   1615                 }
   1616                 else
   1617                 {
   1618                     option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, -1));
   1619                 }
   1620                 break;
   1621             case optional_argument:
   1622                 if (optarg != NULL)
   1623                 {
   1624                     option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
   1625                 }
   1626                 else
   1627                 {
   1628                     option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
   1629                 }
   1630                 break;
   1631             default:
   1632                 // The options table is messed up.  Here we'll just continue
   1633                 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
   1634                                                                    OptionArgElement::eUnrecognizedArg));
   1635                 break;
   1636             }
   1637         }
   1638         else
   1639         {
   1640             option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
   1641                                                                OptionArgElement::eUnrecognizedArg));
   1642         }
   1643     }
   1644 
   1645     // Finally we have to handle the case where the cursor index points at a single "-".  We want to mark that in
   1646     // the option_element_vector, but only if it is not after the "--".  But it turns out that getopt_long_only just ignores
   1647     // an isolated "-".  So we have to look it up by hand here.  We only care if it is AT the cursor position.
   1648 
   1649     if ((dash_dash_pos == -1 || cursor_index < dash_dash_pos)
   1650          && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
   1651     {
   1652         option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index,
   1653                                                            OptionArgElement::eBareDash));
   1654 
   1655     }
   1656 }
   1657 
   1658 void
   1659 Args::EncodeEscapeSequences (const char *src, std::string &dst)
   1660 {
   1661     dst.clear();
   1662     if (src)
   1663     {
   1664         for (const char *p = src; *p != '\0'; ++p)
   1665         {
   1666             size_t non_special_chars = ::strcspn (p, "\\");
   1667             if (non_special_chars > 0)
   1668             {
   1669                 dst.append(p, non_special_chars);
   1670                 p += non_special_chars;
   1671                 if (*p == '\0')
   1672                     break;
   1673             }
   1674 
   1675             if (*p == '\\')
   1676             {
   1677                 ++p; // skip the slash
   1678                 switch (*p)
   1679                 {
   1680                     case 'a' : dst.append(1, '\a'); break;
   1681                     case 'b' : dst.append(1, '\b'); break;
   1682                     case 'f' : dst.append(1, '\f'); break;
   1683                     case 'n' : dst.append(1, '\n'); break;
   1684                     case 'r' : dst.append(1, '\r'); break;
   1685                     case 't' : dst.append(1, '\t'); break;
   1686                     case 'v' : dst.append(1, '\v'); break;
   1687                     case '\\': dst.append(1, '\\'); break;
   1688                     case '\'': dst.append(1, '\''); break;
   1689                     case '"' : dst.append(1, '"'); break;
   1690                     case '0' :
   1691                         // 1 to 3 octal chars
   1692                     {
   1693                         // Make a string that can hold onto the initial zero char,
   1694                         // up to 3 octal digits, and a terminating NULL.
   1695                         char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' };
   1696 
   1697                         int i;
   1698                         for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
   1699                             oct_str[i] = p[i];
   1700 
   1701                         // We don't want to consume the last octal character since
   1702                         // the main for loop will do this for us, so we advance p by
   1703                         // one less than i (even if i is zero)
   1704                         p += i - 1;
   1705                         unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
   1706                         if (octal_value <= UINT8_MAX)
   1707                         {
   1708                             dst.append(1, (char)octal_value);
   1709                         }
   1710                     }
   1711                         break;
   1712 
   1713                     case 'x':
   1714                         // hex number in the format
   1715                         if (isxdigit(p[1]))
   1716                         {
   1717                             ++p;    // Skip the 'x'
   1718 
   1719                             // Make a string that can hold onto two hex chars plus a
   1720                             // NULL terminator
   1721                             char hex_str[3] = { *p, '\0', '\0' };
   1722                             if (isxdigit(p[1]))
   1723                             {
   1724                                 ++p; // Skip the first of the two hex chars
   1725                                 hex_str[1] = *p;
   1726                             }
   1727 
   1728                             unsigned long hex_value = strtoul (hex_str, NULL, 16);
   1729                             if (hex_value <= UINT8_MAX)
   1730                                 dst.append (1, (char)hex_value);
   1731                         }
   1732                         else
   1733                         {
   1734                             dst.append(1, 'x');
   1735                         }
   1736                         break;
   1737 
   1738                     default:
   1739                         // Just desensitize any other character by just printing what
   1740                         // came after the '\'
   1741                         dst.append(1, *p);
   1742                         break;
   1743 
   1744                 }
   1745             }
   1746         }
   1747     }
   1748 }
   1749 
   1750 
   1751 void
   1752 Args::ExpandEscapedCharacters (const char *src, std::string &dst)
   1753 {
   1754     dst.clear();
   1755     if (src)
   1756     {
   1757         for (const char *p = src; *p != '\0'; ++p)
   1758         {
   1759             if (isprint8(*p))
   1760                 dst.append(1, *p);
   1761             else
   1762             {
   1763                 switch (*p)
   1764                 {
   1765                     case '\a': dst.append("\\a"); break;
   1766                     case '\b': dst.append("\\b"); break;
   1767                     case '\f': dst.append("\\f"); break;
   1768                     case '\n': dst.append("\\n"); break;
   1769                     case '\r': dst.append("\\r"); break;
   1770                     case '\t': dst.append("\\t"); break;
   1771                     case '\v': dst.append("\\v"); break;
   1772                     case '\'': dst.append("\\'"); break;
   1773                     case '"': dst.append("\\\""); break;
   1774                     case '\\': dst.append("\\\\"); break;
   1775                     default:
   1776                         {
   1777                             // Just encode as octal
   1778                             dst.append("\\0");
   1779                             char octal_str[32];
   1780                             snprintf(octal_str, sizeof(octal_str), "%o", *p);
   1781                             dst.append(octal_str);
   1782                         }
   1783                         break;
   1784                 }
   1785             }
   1786         }
   1787     }
   1788 }
   1789 
   1790