]> cygwin.com Git - cygwin-apps/setup.git/blame - libgetopt++/src/OptionSet.cc
Add command-line option help-text localization
[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
1d644c06 27bool
155eacb6 28OptionSet::isOption(std::string::size_type pos) const
7419f059 29{
1d644c06 30 return pos == 1 || pos == 2;
7419f059
RC
31}
32
33void
1d644c06 34OptionSet::processOne()
7419f059 35{
155eacb6
AG
36 std::string &option (argv[0]);
37 std::string::size_type pos = option.find_first_not_of("-");
1d644c06
RC
38
39 if (!isOption(pos)) {
40 /* Push the non option into storage */
8effde7a
JT
41 if (nonOptionHandler) {
42 lastResult = nonOptionHandler->Process(option.c_str(), 0);
43 } else {
44 nonoptions.push_back(option);
45 lastResult = Option::Ok;
46 }
1d644c06 47 } else {
8effde7a 48 doOption(option, pos);
1d644c06 49 }
7419f059
RC
50}
51
8effde7a
JT
52void
53OptionSet::findOption(std::string &option, std::string::size_type const &pos,
54 Option *&theOption, int & prefixIndex) const
7419f059 55{
8effde7a
JT
56 theOption = NULL;
57 prefixIndex = 0;
1d644c06
RC
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);
8effde7a 64 return;
1d644c06
RC
65 }
66 } else {
8effde7a
JT
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) {
1d644c06 75 theOption = (*i);
8effde7a
JT
76 prefixIndex = j - prefixes.begin();
77 return;
78 }
1d644c06
RC
79 }
80 }
7419f059 81 }
1d644c06
RC
82}
83
84bool
85OptionSet::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));
7419f059 95 }
1d644c06
RC
96
97 if (pos == 2) {
155eacb6 98 if (option.find("=") != std::string::npos)
1d644c06
RC
99 /* How best to provide failure state ? */
100 return false;
7419f059 101 }
1d644c06
RC
102 return true;
103}
104
105/* TODO: factor this better */
106void
155eacb6 107OptionSet::doOption(std::string &option, std::string::size_type const &pos)
1d644c06
RC
108{
109 lastResult = Option::Failed;
110 option.erase(0, pos);
8effde7a
JT
111 Option *theOption = NULL;
112 int prefixIndex = 0;
113 findOption(option, pos, theOption, prefixIndex);
1d644c06 114 char const *optionValue = NULL;
155eacb6 115 std::string value;
1d644c06
RC
116
117 if (theOption == NULL)
118 return;
119
120 switch (theOption->argument()) {
121
122 case Option::None:
8effde7a
JT
123 if (!doNoArgumentOption (option, pos))
124 return;
125 break;
1d644c06
RC
126
127 case Option::Optional: {
1d644c06
RC
128 if (pos == 1) {
129 if (option.size() == 1) {
130 /* Value in next argv */
131
132 if (argv.size() > 1) {
155eacb6 133 std::string::size_type maybepos = argv[1].find_first_not_of("-");
1d644c06 134
f003c558 135 if (!isOption(maybepos)) {
1d644c06
RC
136 /* not an option */
137 value = argv[1];
138 argv.erase(argv.begin() + 1);
f003c558 139 }
1d644c06
RC
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) {
155eacb6 154 std::string::size_type vpos = option.find("=");
1d644c06 155
155eacb6 156 if (vpos != std::string::npos) {
1d644c06
RC
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) {
155eacb6 168 std::string::size_type maybepos = argv[1].find_first_not_of("-");
1d644c06 169
f003c558 170 if (!isOption(maybepos)) {
1d644c06
RC
171 value = argv[1];
172 argv.erase(argv.begin() + 1);
f003c558 173 }
1d644c06
RC
174 }
175 }
176 }
177
178 if (value.size()) {
179 optionValue = value.c_str();
7419f059 180 }
1d644c06
RC
181
182 }
183 break;
184
185 case Option::Required: {
1d644c06
RC
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
155eacb6 194 std::string::size_type maybepos = argv[1].find_first_not_of("-");
1d644c06
RC
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) {
155eacb6 214 std::string::size_type vpos = option.find("=");
1d644c06 215
155eacb6 216 if (vpos != std::string::npos) {
1d644c06
RC
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
155eacb6 230 std::string::size_type maybepos = argv[1].find_first_not_of("-");
1d644c06
RC
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;
b1b204c8
JT
244 }
245 theOption->setPresent(true);
8effde7a 246 lastResult = theOption->Process(optionValue, prefixIndex);
1d644c06
RC
247}
248
249OptionSet::OptionSet () {}
250
251OptionSet::~OptionSet ()
252{}
253
254void
255OptionSet::Init()
256{
257 options = std::vector<Option *> ();
155eacb6
AG
258 argv = std::vector<std::string> ();
259 nonoptions = std::vector<std::string> ();
260 remainingargv = std::vector<std::string> ();
1d644c06
RC
261 nonOptionHandler = NULL;
262}
263
264bool
265OptionSet::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());
155eacb6 285 for (std::vector<std::string>::iterator i = argv.begin() + 1; i != argv.end(); ++i)
1d644c06 286 remainingargv.push_back(*i);
7419f059 287 }
1d644c06
RC
288 return true;
289 }
7419f059 290 }
1d644c06
RC
291
292 return true;
293}
294
295bool
296OptionSet::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)
155eacb6 307 argv.push_back(std::string(argV[counter]));
1d644c06
RC
308
309 return process(nonOptionHandler);
310}
311
312bool
313OptionSet::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);
7419f059
RC
321}
322
323//FIXME: check for conflicts.
324void
325OptionSet::Register (Option * anOption)
326{
6f1abe45 327 options.push_back(anOption);
7419f059 328}
1ae8e28d 329
efe6ef67
JT
330static bool
331comp_long_option(const Option *a, const Option *b)
332{
333 return (a->longOption().compare(b->longOption()) < 0);
334}
335
1ae8e28d 336void
20f237b4 337OptionSet::ParameterUsage (std::ostream &aStream, StrLookup strLookup)
1ae8e28d 338{
efe6ef67 339 std::sort(options.begin(), options.end(), comp_long_option);
20f237b4 340 for_each (options.begin(), options.end(), DefaultFormatter (aStream, strLookup));
1ae8e28d 341}
6f1abe45
RC
342
343std::vector<Option *> const &
344OptionSet::optionsInSet() const
345{
346 return options;
347}
1d644c06 348
155eacb6 349std::vector<std::string> const &
1d644c06
RC
350OptionSet::nonOptions() const
351{
352 return nonoptions;
353}
354
155eacb6 355std::vector<std::string> const &
1d644c06
RC
356OptionSet::remainingArgv() const
357{
358 return remainingargv;
359}
This page took 0.16349 seconds and 5 git commands to generate.