"Fossies" - the Fresh Open Source Software Archive 
Member "ansifilter-2.18/src/arg_parser.cpp" (30 Jan 2021, 6525 Bytes) of package /linux/privat/ansifilter-2.18.tar.bz2:
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.
For more information about "arg_parser.cpp" see the
Fossies "Dox" file reference documentation.
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 }