]> cygwin.com Git - cygwin-apps/setup.git/blob - libgetopt++/src/OptionSet.cc
Suggest URLs for updated setup based on build architecture
[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 bool
28 OptionSet::isOption(std::string::size_type pos) const
29 {
30 return pos == 1 || pos == 2;
31 }
32
33 void
34 OptionSet::processOne()
35 {
36 std::string &option (argv[0]);
37 std::string::size_type pos = option.find_first_not_of("-");
38
39 if (!isOption(pos)) {
40 /* Push the non option into storage */
41 if (nonOptionHandler) {
42 lastResult = nonOptionHandler->Process(option.c_str(), 0);
43 } else {
44 nonoptions.push_back(option);
45 lastResult = Option::Ok;
46 }
47 } else {
48 doOption(option, pos);
49 }
50 }
51
52 void
53 OptionSet::findOption(std::string &option, std::string::size_type const &pos,
54 Option *&theOption, int & prefixIndex) const
55 {
56 theOption = NULL;
57 prefixIndex = 0;
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 return;
65 }
66 } else {
67 /* pos == 2 */
68 std::vector<std::string> prefixes = (*i)->longOptionPrefixes();
69 for (std::vector<std::string>::const_iterator j = prefixes.begin();
70 j != prefixes.end();
71 j++)
72 {
73 std::string prefixedOption = *j + (*i)->longOption();
74 if (option.find(prefixedOption) == 0) {
75 theOption = (*i);
76 prefixIndex = j - prefixes.begin();
77 return;
78 }
79 }
80 }
81 }
82 }
83
84 bool
85 OptionSet::doNoArgumentOption(std::string &option, std::string::size_type const &pos)
86 {
87 if (pos == 1 && option.size() > 1) {
88 /* Parameter when none allowed */
89
90 if (option.find("=") == 1)
91 /* How best to provide failure state ? */
92 return false;
93
94 argv.insert(argv.begin() + 1,"-" + option.substr(1));
95 }
96
97 if (pos == 2) {
98 if (option.find("=") != std::string::npos)
99 /* How best to provide failure state ? */
100 return false;
101 }
102 return true;
103 }
104
105 /* TODO: factor this better */
106 void
107 OptionSet::doOption(std::string &option, std::string::size_type const &pos)
108 {
109 lastResult = Option::Failed;
110 option.erase(0, pos);
111 Option *theOption = NULL;
112 int prefixIndex = 0;
113 findOption(option, pos, theOption, prefixIndex);
114 char const *optionValue = NULL;
115 std::string value;
116
117 if (theOption == NULL)
118 return;
119
120 switch (theOption->argument()) {
121
122 case Option::None:
123 if (!doNoArgumentOption (option, pos))
124 return;
125 break;
126
127 case Option::Optional: {
128 if (pos == 1) {
129 if (option.size() == 1) {
130 /* Value in next argv */
131
132 if (argv.size() > 1) {
133 std::string::size_type maybepos = argv[1].find_first_not_of("-");
134
135 if (!isOption(maybepos)) {
136 /* not an option */
137 value = argv[1];
138 argv.erase(argv.begin() + 1);
139 }
140 }
141 } else {
142 /* value if present is in this argv */
143
144 if (option.find ("=") == 1) {
145 /* option present */
146 value = option.substr(2);
147 } else
148 /* no option present */
149 argv.insert(argv.begin() + 1,"-" + option.substr(1));
150 }
151 }
152
153 if (pos == 2) {
154 std::string::size_type vpos = option.find("=");
155
156 if (vpos != std::string::npos) {
157 /* How best to provide failure state ? */
158
159 if (vpos == option.size() - 1)
160 /* blank value */
161 return;
162
163 value = option.substr(vpos + 1);
164 } else {
165 /* Value in next argv */
166
167 if (argv.size() > 1) {
168 std::string::size_type maybepos = argv[1].find_first_not_of("-");
169
170 if (!isOption(maybepos)) {
171 value = argv[1];
172 argv.erase(argv.begin() + 1);
173 }
174 }
175 }
176 }
177
178 if (value.size()) {
179 optionValue = value.c_str();
180 }
181
182 }
183 break;
184
185 case Option::Required: {
186 if (pos == 1) {
187 if (option.size() == 1) {
188 /* Value in next argv */
189
190 if (argv.size() < 2)
191 /* but there aren't any */
192 return;
193
194 std::string::size_type maybepos = argv[1].find_first_not_of("-");
195
196 if (isOption(maybepos))
197 /* The next argv is an option */
198 return;
199
200 value = argv[1];
201 argv.erase(argv.begin() + 1);
202 } else {
203 if (option.find ("=") != 1 || option.size() < 3)
204 /* no option passed */
205 return;
206
207 value = option.substr(2);
208 }
209
210 argv.insert(argv.begin() + 1,"-" + option.substr(1));
211 }
212
213 if (pos == 2) {
214 std::string::size_type vpos = option.find("=");
215
216 if (vpos != std::string::npos) {
217 /* How best to provide failure state ? */
218
219 if (vpos == option.size() - 1)
220 return;
221
222 value = option.substr(vpos + 1);
223 } else {
224 /* Value in next argv */
225
226 if (argv.size() < 2)
227 /* but there aren't any */
228 return;
229
230 std::string::size_type maybepos = argv[1].find_first_not_of("-");
231
232 if (isOption(maybepos))
233 /* The next argv is an option */
234 return;
235
236 value = argv[1];
237 argv.erase(argv.begin() + 1);
238 }
239 }
240
241 optionValue = value.c_str();
242 }
243 break;
244 }
245 theOption->setPresent(true);
246 lastResult = theOption->Process(optionValue, prefixIndex);
247 }
248
249 OptionSet::OptionSet () {}
250
251 OptionSet::~OptionSet ()
252 {}
253
254 void
255 OptionSet::Init()
256 {
257 options = std::vector<Option *> ();
258 argv = std::vector<std::string> ();
259 nonoptions = std::vector<std::string> ();
260 remainingargv = std::vector<std::string> ();
261 nonOptionHandler = NULL;
262 }
263
264 bool
265 OptionSet::process (Option *aNonOptionHandler)
266 {
267 nonOptionHandler = aNonOptionHandler;
268 if (options.size() == 0 && nonOptionHandler == NULL)
269 return false;
270
271 while (argv.size()) {
272 processOne();
273 switch (lastResult) {
274
275 case Option::Failed:
276 return false;
277
278 case Option::Ok:
279 argv.erase(argv.begin());
280 break;
281
282 case Option::Stop:
283 if (argv.size() > 1) {
284 // dies: copy(argv.begin() + 1, argv.end(), remainingargv.begin());
285 for (std::vector<std::string>::iterator i = argv.begin() + 1; i != argv.end(); ++i)
286 remainingargv.push_back(*i);
287 }
288 return true;
289 }
290 }
291
292 return true;
293 }
294
295 bool
296 OptionSet::Process (int argc, char **argV, Option *nonOptionHandler)
297 {
298 if (argc == 1) {
299 return true;
300 }
301
302 argv.clear();
303 nonoptions.clear();
304 remainingargv.clear();
305
306 for (int counter = 1; counter < argc; ++counter)
307 argv.push_back(std::string(argV[counter]));
308
309 return process(nonOptionHandler);
310 }
311
312 bool
313 OptionSet::Process (std::vector<std::string> const &parms, Option *nonOptionHandler)
314 {
315 if (parms.size() == 0)
316 return true;
317 argv = parms;
318 nonoptions.clear();
319 remainingargv.clear();
320 return process(nonOptionHandler);
321 }
322
323 //FIXME: check for conflicts.
324 void
325 OptionSet::Register (Option * anOption)
326 {
327 options.push_back(anOption);
328 }
329
330 static bool
331 comp_long_option(const Option *a, const Option *b)
332 {
333 return (a->longOption().compare(b->longOption()) < 0);
334 }
335
336 void
337 OptionSet::ParameterUsage (std::ostream &aStream, StrLookup strLookup)
338 {
339 std::sort(options.begin(), options.end(), comp_long_option);
340 for_each (options.begin(), options.end(), DefaultFormatter (aStream, strLookup));
341 }
342
343 std::vector<Option *> const &
344 OptionSet::optionsInSet() const
345 {
346 return options;
347 }
348
349 std::vector<std::string> const &
350 OptionSet::nonOptions() const
351 {
352 return nonoptions;
353 }
354
355 std::vector<std::string> const &
356 OptionSet::remainingArgv() const
357 {
358 return remainingargv;
359 }
This page took 0.052559 seconds and 6 git commands to generate.