"Fossies" - the Fresh Open Source Software Archive

Member "highlight-3.57-x64/src/cli/arg_parser.cc" (12 May 2020, 5841 Bytes) of package /windows/www/highlight-3.57-x64.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*  Arg_parser - A POSIX/GNU command line argument parser.
    2     Copyright (C) 2006, 2007, 2008 Antonio Diaz Diaz.
    3 
    4     This program is free software: you can redistribute it and/or modify
    5     it under the terms of the GNU General Public License as published by
    6     the Free Software Foundation, either version 3 of the License, or
    7     (at your option) any later version.
    8 
    9     This program is distributed in the hope that it will be useful,
   10     but WITHOUT ANY WARRANTY; without even the implied warranty of
   11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12     GNU General Public License for more details.
   13 
   14     You should have received a copy of the GNU General Public License
   15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
   16 */
   17 
   18 #include <cstring>
   19 #include <string>
   20 #include <vector>
   21 
   22 #include "arg_parser.h"
   23 
   24 
   25 bool Arg_parser::parse_long_option( const char * const opt, const char * const arg,
   26                                     const Option options[], int & argind ) throw()
   27   {
   28   unsigned int len;
   29   int index = -1;
   30   bool exact = false, ambig = false;
   31 
   32   for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ;
   33 
   34   // Test all long options for either exact match or abbreviated matches.
   35   for( int i = 0; options[i].code != 0; ++i )
   36     if( options[i].name && !std::strncmp( options[i].name, &opt[2], len ) )
   37       {
   38       if( std::strlen( options[i].name ) == len )   // Exact match found
   39         { index = i; exact = true; break; }
   40       else if( index < 0 ) index = i;       // First nonexact match found
   41       else if( options[index].code != options[i].code ||
   42                options[index].has_arg != options[i].has_arg )
   43         ambig = true;           // Second or later nonexact match found
   44       }
   45 
   46   if( ambig && !exact )
   47     {
   48     _error = "option `"; _error += opt; _error += "' is ambiguous";
   49     return false;
   50     }
   51 
   52   if( index < 0 )       // nothing found
   53     {
   54     _error = "unrecognized option `"; _error += opt; _error += '\'';
   55     return false;
   56     }
   57 
   58   ++argind;
   59   data.push_back( Record( options[index].code ) );
   60 
   61   if( opt[len+2] )      // `--<long_option>=<argument>' syntax
   62     {
   63     if( options[index].has_arg == no )
   64       {
   65       _error = "option `--"; _error += options[index].name;
   66       _error += "' doesn't allow an argument";
   67       return false;
   68       }
   69     if( options[index].has_arg == yes && !opt[len+3] )
   70       {
   71       _error = "option `--"; _error += options[index].name;
   72       _error += "' requires an argument";
   73       return false;
   74       }
   75     data.back().argument = &opt[len+3];
   76     return true;
   77     }
   78 
   79   if( options[index].has_arg == yes )
   80     {
   81     if( !arg )
   82       {
   83       _error = "option `--"; _error += options[index].name;
   84       _error += "' requires an argument";
   85       return false;
   86       }
   87     ++argind; data.back().argument = arg;
   88     return true;
   89     }
   90 
   91   return true;
   92   }
   93 
   94 
   95 bool Arg_parser::parse_short_option( const char * const opt, const char * const arg,
   96                                      const Option options[], int & argind ) throw()
   97   {
   98   int cind = 1;         // character index in opt
   99 
  100   while( cind > 0 )
  101     {
  102     int index = -1;
  103     const unsigned char code = opt[cind];
  104 
  105     if( code != 0 )
  106       for( int i = 0; options[i].code; ++i )
  107         if( code == options[i].code )
  108           { index = i; break; }
  109 
  110     if( index < 0 )
  111       {
  112       _error = "invalid option -- "; _error += code;
  113       return false;
  114       }
  115 
  116     data.push_back( Record( code ) );
  117     if( opt[++cind] == 0 ) { ++argind; cind = 0; }  // opt finished
  118 
  119     if( options[index].has_arg != no && cind > 0 && opt[cind] )
  120       {
  121       data.back().argument = &opt[cind]; ++argind; cind = 0;
  122       }
  123     else if( options[index].has_arg == yes )
  124       {
  125       if( !arg || !arg[0] )
  126         {
  127         _error = "option requires an argument -- "; _error += code;
  128         return false;
  129         }
  130       data.back().argument = arg; ++argind; cind = 0;
  131       }
  132     }
  133   return true;
  134   }
  135 
  136 
  137 Arg_parser::Arg_parser( const int argc, const char * const argv[],
  138                         const Option options[], const bool in_order ) throw()
  139   {
  140   if( argc < 2 || !argv || !options ) return;
  141 
  142   std::vector< std::string > non_options;   // skipped non-options
  143   int argind = 1;               // index in argv
  144 
  145   while( argind < argc )
  146     {
  147     const unsigned char ch1 = argv[argind][0];
  148     const unsigned char ch2 = ( ch1 ? argv[argind][1] : 0 );
  149 
  150     if( ch1 == '-' && ch2 )     // we found an option
  151       {
  152       const char * const opt = argv[argind];
  153       const char * const arg = (argind + 1 < argc) ? argv[argind+1] : 0;
  154       if( ch2 == '-' )
  155         {
  156         if( !argv[argind][2] ) { ++argind; break; } // we found "--"
  157         else if( !parse_long_option( opt, arg, options, argind ) ) break;
  158         }
  159       else if( !parse_short_option( opt, arg, options, argind ) ) break;
  160       }
  161     else
  162       {
  163       if( !in_order ) non_options.push_back( argv[argind++] );
  164       else { data.push_back( Record() ); data.back().argument = argv[argind++]; }
  165       }
  166     }
  167   if( _error.size() ) data.clear();
  168   else
  169     {
  170     for( unsigned int i = 0; i < non_options.size(); ++i )
  171       { data.push_back( Record() ); data.back().argument.swap( non_options[i] ); }
  172     while( argind < argc )
  173       { data.push_back( Record() ); data.back().argument = argv[argind++]; }
  174     }
  175   }
  176 
  177 
  178 Arg_parser::Arg_parser( const char * const opt, const char * const arg,
  179                         const Option options[] ) throw()
  180   {
  181   if( !opt || !opt[0] || !options ) return;
  182 
  183   if( opt[0] == '-' && opt[1] )     // we found an option
  184     {
  185     int argind = 1;         // dummy
  186     if( opt[1] == '-' )
  187       { if( opt[2] ) parse_long_option( opt, arg, options, argind ); }
  188     else
  189       parse_short_option( opt, arg, options, argind );
  190     if( _error.size() ) data.clear();
  191     }
  192   else { data.push_back( Record() ); data.back().argument = opt; }
  193   }