]> cygwin.com Git - cygwin-apps/setup.git/blob - libgetopt++/src/OptionSet.cc
Access StringOption's value by reference
[cygwin-apps/setup.git] / libgetopt++ / src / OptionSet.cc
1 /*
2 * Copyright (c) 2002 Robert Collins.
3 * Copyright (c) 2003 Robert Collins.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * A copy of the GNU General Public License can be found at
11 * http://www.gnu.org/
12 *
13 * Written by Robert Collins <robertc@hotmail.com>
14 *
15 */
16
17 #if HAVE_CONFIG_H
18 #include "autoconf.h"
19 #endif
20 #include "getopt++/OptionSet.h"
21 #include "getopt++/Option.h"
22 #include "getopt++/DefaultFormatter.h"
23
24 #include <iostream>
25 #include <algorithm>
26
27 using namespace std;
28
29 bool
30 OptionSet::isOption(string::size_type pos) const
31 {
32 return pos == 1 || pos == 2;
33 }
34
35 void
36 OptionSet::processOne()
37 {
38 string &option (argv[0]);
39 string::size_type pos = option.find_first_not_of("-");
40
41 if (!isOption(pos)) {
42 /* Push the non option into storage */
43 if (nonOptionHandler) {
44 lastResult = nonOptionHandler->Process(option.c_str());
45 } else {
46 nonoptions.push_back(option);
47 lastResult = Option::Ok;
48 }
49 } else {
50 doOption(option, pos);
51 }
52 }
53
54 Option *
55 OptionSet::findOption(string &option, string::size_type const &pos) const
56 {
57 Option *theOption = NULL;
58
59 for (std::vector<Option *>::const_iterator i = options.begin(); i != options.end();
60 ++i) {
61 if (pos == 1) {
62 if (option[0] == (*i)->shortOption()[0]) {
63 theOption = (*i);
64 }
65 } else {
66 /* pos == 2 : todo - prefix matches */
67
68 if (option.find((*i)->longOption()) == 0) {
69 theOption = (*i);
70 }
71 }
72 }
73 return theOption;
74 }
75
76 bool
77 OptionSet::doNoArgumentOption(std::string &option, std::string::size_type const &pos)
78 {
79 if (pos == 1 && option.size() > 1) {
80 /* Parameter when none allowed */
81
82 if (option.find("=") == 1)
83 /* How best to provide failure state ? */
84 return false;
85
86 argv.insert(argv.begin() + 1,"-" + option.substr(1));
87 }
88
89 if (pos == 2) {
90 if (option.find("=") != string::npos)
91 /* How best to provide failure state ? */
92 return false;
93 }
94 return true;
95 }
96
97 /* TODO: factor this better */
98 void
99 OptionSet::doOption(string &option, string::size_type const &pos)
100 {
101 lastResult = Option::Failed;
102 option.erase(0, pos);
103 Option *theOption = findOption(option, pos);
104 char const *optionValue = NULL;
105 string value;
106
107 if (theOption == NULL)
108 return;
109
110 switch (theOption->argument()) {
111
112 case Option::None:
113 if (!doNoArgumentOption (option, pos))
114 return;
115 break;
116
117 case Option::Optional: {
118 if (pos == 1) {
119 if (option.size() == 1) {
120 /* Value in next argv */
121
122 if (argv.size() > 1) {
123 string::size_type maybepos = argv[1].find_first_not_of("-");
124
125 if (!isOption(maybepos))
126 /* not an option */
127 value = argv[1];
128 argv.erase(argv.begin() + 1);
129 }
130 } else {
131 /* value if present is in this argv */
132
133 if (option.find ("=") == 1) {
134 /* option present */
135 value = option.substr(2);
136 } else
137 /* no option present */
138 argv.insert(argv.begin() + 1,"-" + option.substr(1));
139 }
140 }
141
142 if (pos == 2) {
143 string::size_type vpos = option.find("=");
144
145 if (vpos != string::npos) {
146 /* How best to provide failure state ? */
147
148 if (vpos == option.size() - 1)
149 /* blank value */
150 return;
151
152 value = option.substr(vpos + 1);
153 } else {
154 /* Value in next argv */
155
156 if (argv.size() > 1) {
157 string::size_type maybepos = argv[1].find_first_not_of("-");
158
159 if (!isOption(maybepos))
160 value = argv[1];
161 argv.erase(argv.begin() + 1);
162 }
163 }
164 }
165
166 if (value.size()) {
167 optionValue = value.c_str();
168 }
169
170 }
171 break;
172
173 case Option::Required: {
174 if (pos == 1) {
175 if (option.size() == 1) {
176 /* Value in next argv */
177
178 if (argv.size() < 2)
179 /* but there aren't any */
180 return;
181
182 string::size_type maybepos = argv[1].find_first_not_of("-");
183
184 if (isOption(maybepos))
185 /* The next argv is an option */
186 return;
187
188 value = argv[1];
189 argv.erase(argv.begin() + 1);
190 } else {
191 if (option.find ("=") != 1 || option.size() < 3)
192 /* no option passed */
193 return;
194
195 value = option.substr(2);
196 }
197
198 argv.insert(argv.begin() + 1,"-" + option.substr(1));
199 }
200
201 if (pos == 2) {
202 string::size_type vpos = option.find("=");
203
204 if (vpos != string::npos) {
205 /* How best to provide failure state ? */
206
207 if (vpos == option.size() - 1)
208 return;
209
210 value = option.substr(vpos + 1);
211 } else {
212 /* Value in next argv */
213
214 if (argv.size() < 2)
215 /* but there aren't any */
216 return;
217
218 string::size_type maybepos = argv[1].find_first_not_of("-");
219
220 if (isOption(maybepos))
221 /* The next argv is an option */
222 return;
223
224 value = argv[1];
225 argv.erase(argv.begin() + 1);
226 }
227 }
228
229 optionValue = value.c_str();
230 }
231 break;
232 }
233 lastResult = theOption->Process(optionValue);
234 }
235
236 OptionSet::OptionSet () {}
237
238 OptionSet::~OptionSet ()
239 {}
240
241 void
242 OptionSet::Init()
243 {
244 options = std::vector<Option *> ();
245 argv = std::vector<string> ();
246 nonoptions = std::vector<string> ();
247 remainingargv = std::vector<string> ();
248 nonOptionHandler = NULL;
249 }
250
251 bool
252 OptionSet::process (Option *aNonOptionHandler)
253 {
254 nonOptionHandler = aNonOptionHandler;
255 if (options.size() == 0 && nonOptionHandler == NULL)
256 return false;
257
258 while (argv.size()) {
259 processOne();
260 switch (lastResult) {
261
262 case Option::Failed:
263 return false;
264
265 case Option::Ok:
266 argv.erase(argv.begin());
267 break;
268
269 case Option::Stop:
270 if (argv.size() > 1) {
271 // dies: copy(argv.begin() + 1, argv.end(), remainingargv.begin());
272 for (std::vector<string>::iterator i = argv.begin() + 1; i != argv.end(); ++i)
273 remainingargv.push_back(*i);
274 }
275 return true;
276 }
277 }
278
279 return true;
280 }
281
282 bool
283 OptionSet::Process (int argc, char **argV, Option *nonOptionHandler)
284 {
285 if (argc == 1) {
286 return true;
287 }
288
289 argv.clear();
290 nonoptions.clear();
291 remainingargv.clear();
292
293 for (int counter = 1; counter < argc; ++counter)
294 argv.push_back(string(argV[counter]));
295
296 return process(nonOptionHandler);
297 }
298
299 bool
300 OptionSet::Process (std::vector<std::string> const &parms, Option *nonOptionHandler)
301 {
302 if (parms.size() == 0)
303 return true;
304 argv = parms;
305 nonoptions.clear();
306 remainingargv.clear();
307 return process(nonOptionHandler);
308 }
309
310 //FIXME: check for conflicts.
311 void
312 OptionSet::Register (Option * anOption)
313 {
314 options.push_back(anOption);
315 }
316
317 static bool
318 comp_long_option(const Option *a, const Option *b)
319 {
320 return (a->longOption().compare(b->longOption()) < 0);
321 }
322
323 void
324 OptionSet::ParameterUsage (ostream &aStream)
325 {
326 std::sort(options.begin(), options.end(), comp_long_option);
327 for_each (options.begin(), options.end(), DefaultFormatter (aStream));
328 }
329
330 std::vector<Option *> const &
331 OptionSet::optionsInSet() const
332 {
333 return options;
334 }
335
336 std::vector<string> const &
337 OptionSet::nonOptions() const
338 {
339 return nonoptions;
340 }
341
342 std::vector<string> const &
343 OptionSet::remainingArgv() const
344 {
345 return remainingargv;
346 }
This page took 0.053908 seconds and 6 git commands to generate.