]> cygwin.com Git - cygwin-apps/setup.git/blame - libgetopt++/src/OptionSet.cc
Access StringOption's value by reference
[cygwin-apps/setup.git] / libgetopt++ / src / OptionSet.cc
CommitLineData
7419f059
RC
1/*
2 * Copyright (c) 2002 Robert Collins.
6f1abe45 3 * Copyright (c) 2003 Robert Collins.
7419f059
RC
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"
20e315e1 22#include "getopt++/DefaultFormatter.h"
7419f059 23
1ae8e28d 24#include <iostream>
2e0aaec9 25#include <algorithm>
1ae8e28d 26
e930272e
RC
27using namespace std;
28
1d644c06
RC
29bool
30OptionSet::isOption(string::size_type pos) const
7419f059 31{
1d644c06 32 return pos == 1 || pos == 2;
7419f059
RC
33}
34
35void
1d644c06 36OptionSet::processOne()
7419f059 37{
1d644c06
RC
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 }
7419f059
RC
52}
53
1d644c06
RC
54Option *
55OptionSet::findOption(string &option, string::size_type const &pos) const
7419f059 56{
1d644c06
RC
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 }
7419f059 72 }
1d644c06
RC
73 return theOption;
74}
75
76bool
77OptionSet::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));
7419f059 87 }
1d644c06
RC
88
89 if (pos == 2) {
90 if (option.find("=") != string::npos)
91 /* How best to provide failure state ? */
92 return false;
7419f059 93 }
1d644c06
RC
94 return true;
95}
96
97/* TODO: factor this better */
98void
99OptionSet::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;
dbfe3c19 105 string value;
1d644c06
RC
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: {
1d644c06
RC
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();
7419f059 168 }
1d644c06
RC
169
170 }
171 break;
172
173 case Option::Required: {
1d644c06
RC
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
236OptionSet::OptionSet () {}
237
238OptionSet::~OptionSet ()
239{}
240
241void
242OptionSet::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
251bool
252OptionSet::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);
7419f059 274 }
1d644c06
RC
275 return true;
276 }
7419f059 277 }
1d644c06
RC
278
279 return true;
280}
281
282bool
283OptionSet::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
299bool
300OptionSet::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);
7419f059
RC
308}
309
310//FIXME: check for conflicts.
311void
312OptionSet::Register (Option * anOption)
313{
6f1abe45 314 options.push_back(anOption);
7419f059 315}
1ae8e28d 316
efe6ef67
JT
317static bool
318comp_long_option(const Option *a, const Option *b)
319{
320 return (a->longOption().compare(b->longOption()) < 0);
321}
322
1ae8e28d
RC
323void
324OptionSet::ParameterUsage (ostream &aStream)
325{
efe6ef67 326 std::sort(options.begin(), options.end(), comp_long_option);
1d644c06 327 for_each (options.begin(), options.end(), DefaultFormatter (aStream));
1ae8e28d 328}
6f1abe45
RC
329
330std::vector<Option *> const &
331OptionSet::optionsInSet() const
332{
333 return options;
334}
1d644c06
RC
335
336std::vector<string> const &
337OptionSet::nonOptions() const
338{
339 return nonoptions;
340}
341
342std::vector<string> const &
343OptionSet::remainingArgv() const
344{
345 return remainingargv;
346}
This page took 0.102108 seconds and 5 git commands to generate.