"Fossies" - the Fresh Open Source Software Archive

Member "ansifilter-2.18-x64/src/arg_parser.cpp" (30 Jan 2021, 6525 Bytes) of package /windows/misc/ansifilter-2.18-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             if( std::strlen( options[i].name ) == len ) {   // Exact match found
   38                 index = i;
   39                 exact = true;
   40                 break;
   41             } else if( index < 0 ) index = i;       // First nonexact match found
   42             else if( options[index].code != options[i].code ||
   43                      options[index].has_arg != options[i].has_arg )
   44                 ambig = true;           // Second or later nonexact match found
   45         }
   46 
   47     if( ambig && !exact ) {
   48         _error = "option `";
   49         _error += opt;
   50         _error += "' is ambiguous";
   51         return false;
   52     }
   53 
   54     if( index < 0 ) {   // nothing found
   55         _error = "unrecognized option `";
   56         _error += opt;
   57         _error += '\'';
   58         return false;
   59     }
   60 
   61     ++argind;
   62     data.push_back( Record( options[index].code ) );
   63 
   64     if( opt[len+2] ) {  // `--<long_option>=<argument>' syntax
   65         if( options[index].has_arg == no ) {
   66             _error = "option `--";
   67             _error += options[index].name;
   68             _error += "' doesn't allow an argument";
   69             return false;
   70         }
   71         if( options[index].has_arg == yes && !opt[len+3] ) {
   72             _error = "option `--";
   73             _error += options[index].name;
   74             _error += "' requires an argument";
   75             return false;
   76         }
   77         data.back().argument = &opt[len+3];
   78         return true;
   79     }
   80 
   81     if( options[index].has_arg == yes ) {
   82         if( !arg ) {
   83             _error = "option `--";
   84             _error += options[index].name;
   85             _error += "' requires an argument";
   86             return false;
   87         }
   88         ++argind;
   89         data.back().argument = arg;
   90         return true;
   91     }
   92 
   93     return true;
   94 }
   95 
   96 
   97 bool Arg_parser::parse_short_option( const char * const opt, const char * const arg,
   98                                      const Option options[], int & argind ) throw()
   99 {
  100     int cind = 1;           // character index in opt
  101 
  102     while( cind > 0 ) {
  103         int index = -1;
  104         const unsigned char code = opt[cind];
  105 
  106         if( code != 0 )
  107             for( int i = 0; options[i].code; ++i )
  108                 if( code == options[i].code ) {
  109                     index = i;
  110                     break;
  111                 }
  112 
  113         if( index < 0 ) {
  114             _error = "invalid option -- ";
  115             _error += code;
  116             return false;
  117         }
  118 
  119         data.push_back( Record( code ) );
  120         if( opt[++cind] == 0 ) {
  121             ++argind;    // opt finished
  122             cind = 0;
  123         }
  124 
  125         if( options[index].has_arg != no && cind > 0 && opt[cind] ) {
  126             data.back().argument = &opt[cind];
  127             ++argind;
  128             cind = 0;
  129         } else if( options[index].has_arg == yes ) {
  130             if( !arg || !arg[0] ) {
  131                 _error = "option requires an argument -- ";
  132                 _error += code;
  133                 return false;
  134             }
  135             data.back().argument = arg;
  136             ++argind;
  137             cind = 0;
  138         }
  139     }
  140     return true;
  141 }
  142 
  143 
  144 Arg_parser::Arg_parser( const int argc, const char * const argv[],
  145                         const Option options[], const bool in_order ) throw()
  146 {
  147     if( argc < 2 || !argv || !options ) return;
  148 
  149     std::vector< std::string > non_options; // skipped non-options
  150     int argind = 1;             // index in argv
  151 
  152     while( argind < argc ) {
  153         const unsigned char ch1 = argv[argind][0];
  154         const unsigned char ch2 = ( ch1 ? argv[argind][1] : 0 );
  155 
  156         if( ch1 == '-' && ch2 ) {   // we found an option
  157             const char * const opt = argv[argind];
  158             const char * const arg = (argind + 1 < argc) ? argv[argind+1] : 0;
  159             if( ch2 == '-' ) {
  160                 if( !argv[argind][2] ) {
  161                     ++argind;    // we found "--"
  162                     break;
  163                 } else if( !parse_long_option( opt, arg, options, argind ) ) break;
  164             } else if( !parse_short_option( opt, arg, options, argind ) ) break;
  165         } else {
  166             if( !in_order ) non_options.push_back( argv[argind++] );
  167             else {
  168                 data.push_back( Record() );
  169                 data.back().argument = argv[argind++];
  170             }
  171         }
  172     }
  173     if( _error.size() ) data.clear();
  174     else {
  175         for( unsigned int i = 0; i < non_options.size(); ++i ) {
  176             data.push_back( Record() );
  177             data.back().argument.swap( non_options[i] );
  178         }
  179         while( argind < argc ) {
  180             data.push_back( Record() );
  181             data.back().argument = argv[argind++];
  182         }
  183     }
  184 }
  185 
  186 
  187 Arg_parser::Arg_parser( const char * const opt, const char * const arg,
  188                         const Option options[] ) throw()
  189 {
  190     if( !opt || !opt[0] || !options ) return;
  191 
  192     if( opt[0] == '-' && opt[1] ) { // we found an option
  193         int argind = 1;         // dummy
  194         if( opt[1] == '-' ) {
  195             if( opt[2] ) parse_long_option( opt, arg, options, argind );
  196         } else
  197             parse_short_option( opt, arg, options, argind );
  198         if( _error.size() ) data.clear();
  199     } else {
  200         data.push_back( Record() );
  201         data.back().argument = opt;
  202     }
  203 }