]> cygwin.com Git - cygwin-apps/setup.git/blob - libgetopt++/src/OptionSet.cc
fff13934926d7b24e6688b4e03bfc98cf05e865e
[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
106 if (theOption == NULL)
107 return;
108
109 switch (theOption->argument()) {
110
111 case Option::None:
112 if (!doNoArgumentOption (option, pos))
113 return;
114 break;
115
116 case Option::Optional: {
117 string value;
118
119 if (pos == 1) {
120 if (option.size() == 1) {
121 /* Value in next argv */
122
123 if (argv.size() > 1) {
124 string::size_type maybepos = argv[1].find_first_not_of("-");
125
126 if (!isOption(maybepos))
127 /* not an option */
128 value = argv[1];
129 argv.erase(argv.begin() + 1);
130 }
131 } else {
132 /* value if present is in this argv */
133
134 if (option.find ("=") == 1) {
135 /* option present */
136 value = option.substr(2);
137 } else
138 /* no option present */
139 argv.insert(argv.begin() + 1,"-" + option.substr(1));
140 }
141 }
142
143 if (pos == 2) {
144 string::size_type vpos = option.find("=");
145
146 if (vpos != string::npos) {
147 /* How best to provide failure state ? */
148
149 if (vpos == option.size() - 1)
150 /* blank value */
151 return;
152
153 value = option.substr(vpos + 1);
154 } else {
155 /* Value in next argv */
156
157 if (argv.size() > 1) {
158 string::size_type maybepos = argv[1].find_first_not_of("-");
159
160 if (!isOption(maybepos))
161 value = argv[1];
162 argv.erase(argv.begin() + 1);
163 }
164 }
165 }
166
167 if (value.size()) {
168 optionValue = value.c_str();
169 }
170
171 }
172 break;
173
174 case Option::Required: {
175 string value;
176
177 if (pos == 1) {
178 if (option.size() == 1) {
179 /* Value in next argv */
180
181 if (argv.size() < 2)
182 /* but there aren't any */
183 return;
184
185 string::size_type maybepos = argv[1].find_first_not_of("-");
186
187 if (isOption(maybepos))
188 /* The next argv is an option */
189 return;
190
191 value = argv[1];
192 argv.erase(argv.begin() + 1);
193 } else {
194 if (option.find ("=") != 1 || option.size() < 3)
195 /* no option passed */
196 return;
197
198 value = option.substr(2);
199 }
200
201 argv.insert(argv.begin() + 1,"-" + option.substr(1));
202 }
203
204 if (pos == 2) {
205 string::size_type vpos = option.find("=");
206
207 if (vpos != string::npos) {
208 /* How best to provide failure state ? */
209
210 if (vpos == option.size() - 1)
211 return;
212
213 value = option.substr(vpos + 1);
214 } else {
215 /* Value in next argv */
216
217 if (argv.size() < 2)
218 /* but there aren't any */
219 return;
220
221 string::size_type maybepos = argv[1].find_first_not_of("-");
222
223 if (isOption(maybepos))
224 /* The next argv is an option */
225 return;
226
227 value = argv[1];
228 argv.erase(argv.begin() + 1);
229 }
230 }
231
232 optionValue = value.c_str();
233 }
234 break;
235 }
236 lastResult = theOption->Process(optionValue);
237 }
238
239 OptionSet::OptionSet () {}
240
241 OptionSet::~OptionSet ()
242 {}
243
244 void
245 OptionSet::Init()
246 {
247 options = std::vector<Option *> ();
248 argv = std::vector<string> ();
249 nonoptions = std::vector<string> ();
250 remainingargv = std::vector<string> ();
251 nonOptionHandler = NULL;
252 }
253
254 bool
255 OptionSet::process (Option *aNonOptionHandler)
256 {
257 nonOptionHandler = aNonOptionHandler;
258 if (options.size() == 0 && nonOptionHandler == NULL)
259 return false;
260
261 while (argv.size()) {
262 processOne();
263 switch (lastResult) {
264
265 case Option::Failed:
266 return false;
267
268 case Option::Ok:
269 argv.erase(argv.begin());
270 break;
271
272 case Option::Stop:
273 if (argv.size() > 1) {
274 // dies: copy(argv.begin() + 1, argv.end(), remainingargv.begin());
275 for (std::vector<string>::iterator i = argv.begin() + 1; i != argv.end(); ++i)
276 remainingargv.push_back(*i);
277 }
278 return true;
279 }
280 }
281
282 return true;
283 }
284
285 bool
286 OptionSet::Process (int argc, char **argV, Option *nonOptionHandler)
287 {
288 if (argc == 1) {
289 return true;
290 }
291
292 argv.clear();
293 nonoptions.clear();
294 remainingargv.clear();
295
296 for (int counter = 1; counter < argc; ++counter)
297 argv.push_back(string(argV[counter]));
298
299 return process(nonOptionHandler);
300 }
301
302 bool
303 OptionSet::Process (std::vector<std::string> const &parms, Option *nonOptionHandler)
304 {
305 if (parms.size() == 0)
306 return true;
307 argv = parms;
308 nonoptions.clear();
309 remainingargv.clear();
310 return process(nonOptionHandler);
311 }
312
313 //FIXME: check for conflicts.
314 void
315 OptionSet::Register (Option * anOption)
316 {
317 options.push_back(anOption);
318 }
319
320 void
321 OptionSet::ParameterUsage (ostream &aStream)
322 {
323 for_each (options.begin(), options.end(), DefaultFormatter (aStream));
324 }
325
326 std::vector<Option *> const &
327 OptionSet::optionsInSet() const
328 {
329 return options;
330 }
331
332 std::vector<string> const &
333 OptionSet::nonOptions() const
334 {
335 return nonoptions;
336 }
337
338 std::vector<string> const &
339 OptionSet::remainingArgv() const
340 {
341 return remainingargv;
342 }
This page took 0.050209 seconds and 5 git commands to generate.