Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef shell_jsoptparse_h
8 #define shell_jsoptparse_h
10 #include <stdio.h>
12 #include "jsalloc.h"
13 #include "jsutil.h"
15 #include "js/Vector.h"
17 namespace js {
18 namespace cli {
20 namespace detail {
22 struct BoolOption;
23 struct MultiStringOption;
24 struct ValuedOption;
25 struct StringOption;
26 struct IntOption;
28 enum OptionKind
29 {
30 OptionKindBool,
31 OptionKindString,
32 OptionKindInt,
33 OptionKindMultiString,
34 OptionKindInvalid
35 };
37 struct Option
38 {
39 const char *longflag;
40 const char *help;
41 OptionKind kind;
42 char shortflag;
43 bool terminatesOptions;
45 Option(OptionKind kind, char shortflag, const char *longflag, const char *help)
46 : longflag(longflag), help(help), kind(kind), shortflag(shortflag), terminatesOptions(false)
47 {}
49 virtual ~Option() = 0;
51 void setTerminatesOptions(bool enabled) { terminatesOptions = enabled; }
52 bool getTerminatesOptions() const { return terminatesOptions; }
54 virtual bool isValued() const { return false; }
56 /* Only some valued options are variadic (like MultiStringOptions). */
57 virtual bool isVariadic() const { return false; }
59 /*
60 * For arguments, the shortflag field is used to indicate whether the
61 * argument is optional.
62 */
63 bool isOptional() { return shortflag; }
65 void setFlagInfo(char shortflag, const char *longflag, const char *help) {
66 this->shortflag = shortflag;
67 this->longflag = longflag;
68 this->help = help;
69 }
71 ValuedOption *asValued();
72 const ValuedOption *asValued() const;
74 #define OPTION_CONVERT_DECL(__cls) \
75 bool is##__cls##Option() const; \
76 __cls##Option *as##__cls##Option(); \
77 const __cls##Option *as##__cls##Option() const;
79 OPTION_CONVERT_DECL(Bool)
80 OPTION_CONVERT_DECL(String)
81 OPTION_CONVERT_DECL(Int)
82 OPTION_CONVERT_DECL(MultiString)
83 };
85 inline Option::~Option() {}
87 struct BoolOption : public Option
88 {
89 size_t argno;
90 bool value;
92 BoolOption(char shortflag, const char *longflag, const char *help)
93 : Option(OptionKindBool, shortflag, longflag, help), value(false)
94 {}
96 virtual ~BoolOption() {}
97 };
99 struct ValuedOption : public Option
100 {
101 const char *metavar;
103 ValuedOption(OptionKind kind, char shortflag, const char *longflag, const char *help,
104 const char *metavar)
105 : Option(kind, shortflag, longflag, help), metavar(metavar)
106 {}
108 virtual ~ValuedOption() = 0;
109 virtual bool isValued() const { return true; }
110 };
112 inline ValuedOption::~ValuedOption() {}
114 struct StringOption : public ValuedOption
115 {
116 const char *value;
118 StringOption(char shortflag, const char *longflag, const char *help, const char *metavar)
119 : ValuedOption(OptionKindString, shortflag, longflag, help, metavar), value(nullptr)
120 {}
122 virtual ~StringOption() {}
123 };
125 struct IntOption : public ValuedOption
126 {
127 int value;
129 IntOption(char shortflag, const char *longflag, const char *help, const char *metavar,
130 int defaultValue)
131 : ValuedOption(OptionKindInt, shortflag, longflag, help, metavar), value(defaultValue)
132 {}
134 virtual ~IntOption() {}
135 };
137 struct StringArg
138 {
139 char *value;
140 size_t argno;
142 StringArg(char *value, size_t argno) : value(value), argno(argno) {}
143 };
145 struct MultiStringOption : public ValuedOption
146 {
147 Vector<StringArg, 0, SystemAllocPolicy> strings;
149 MultiStringOption(char shortflag, const char *longflag, const char *help, const char *metavar)
150 : ValuedOption(OptionKindMultiString, shortflag, longflag, help, metavar)
151 {}
153 virtual ~MultiStringOption() {}
155 virtual bool isVariadic() const { return true; }
156 };
158 } /* namespace detail */
160 class MultiStringRange
161 {
162 typedef detail::StringArg StringArg;
163 const StringArg *cur;
164 const StringArg *end;
166 public:
167 explicit MultiStringRange(const StringArg *cur, const StringArg *end)
168 : cur(cur), end(end) {
169 JS_ASSERT(end - cur >= 0);
170 }
172 bool empty() const { return cur == end; }
173 void popFront() { JS_ASSERT(!empty()); ++cur; }
174 char *front() const { JS_ASSERT(!empty()); return cur->value; }
175 size_t argno() const { JS_ASSERT(!empty()); return cur->argno; }
176 };
178 /*
179 * Builder for describing a command line interface and parsing the resulting
180 * specification.
181 *
182 * - A multi-option is an option that can appear multiple times and still
183 * parse as valid command line arguments.
184 * - An "optional argument" is supported for backwards compatibility with prior
185 * command line interface usage. Once one optional argument has been added,
186 * *only* optional arguments may be added.
187 */
188 class OptionParser
189 {
190 public:
191 enum Result
192 {
193 Okay = 0,
194 Fail, /* As in, allocation fail. */
195 ParseError, /* Successfully parsed but with an error. */
196 ParseHelp /* Aborted on help flag. */
197 };
199 private:
200 typedef Vector<detail::Option *, 0, SystemAllocPolicy> Options;
201 typedef detail::Option Option;
202 typedef detail::BoolOption BoolOption;
204 Options options;
205 Options arguments;
206 BoolOption helpOption;
207 const char *usage;
208 const char *ver;
209 const char *descr;
210 size_t descrWidth;
211 size_t helpWidth;
212 size_t nextArgument;
214 // If '--' is passed, all remaining arguments should be interpreted as the
215 // argument at index 'restArgument'. Defaults to the next unassigned
216 // argument.
217 int restArgument;
219 static const char prognameMeta[];
221 Option *findOption(char shortflag);
222 const Option *findOption(char shortflag) const;
223 Option *findOption(const char *longflag);
224 const Option *findOption(const char *longflag) const;
225 int findArgumentIndex(const char *name) const;
226 Option *findArgument(const char *name);
227 const Option *findArgument(const char *name) const;
229 Result error(const char *fmt, ...);
230 Result extractValue(size_t argc, char **argv, size_t *i, char **value);
231 Result handleArg(size_t argc, char **argv, size_t *i, bool *optsAllowed);
232 Result handleOption(Option *opt, size_t argc, char **argv, size_t *i, bool *optsAllowed);
234 public:
235 explicit OptionParser(const char *usage)
236 : helpOption('h', "help", "Display help information"),
237 usage(usage), ver(nullptr), descr(nullptr), descrWidth(80), helpWidth(80),
238 nextArgument(0), restArgument(-1)
239 {}
241 ~OptionParser();
243 Result parseArgs(int argc, char **argv);
244 Result printHelp(const char *progname);
246 /* Metadata */
248 void setVersion(const char *version) { ver = version; }
249 void setHelpWidth(size_t width) { helpWidth = width; }
250 void setDescriptionWidth(size_t width) { descrWidth = width; }
251 void setDescription(const char *description) { descr = description; }
252 void setHelpOption(char shortflag, const char *longflag, const char *help);
253 void setArgTerminatesOptions(const char *name, bool enabled);
254 void setArgCapturesRest(const char *name);
256 /* Arguments: no further arguments may be added after a variadic argument. */
258 bool addOptionalStringArg(const char *name, const char *help);
259 bool addOptionalMultiStringArg(const char *name, const char *help);
261 const char *getStringArg(const char *name) const;
262 MultiStringRange getMultiStringArg(const char *name) const;
264 /* Options */
266 bool addBoolOption(char shortflag, const char *longflag, const char *help);
267 bool addStringOption(char shortflag, const char *longflag, const char *help,
268 const char *metavar);
269 bool addIntOption(char shortflag, const char *longflag, const char *help,
270 const char *metavar, int defaultValue);
271 bool addMultiStringOption(char shortflag, const char *longflag, const char *help,
272 const char *metavar);
273 bool addOptionalVariadicArg(const char *name);
275 int getIntOption(char shortflag) const;
276 int getIntOption(const char *longflag) const;
277 const char *getStringOption(char shortflag) const;
278 const char *getStringOption(const char *longflag) const;
279 bool getBoolOption(char shortflag) const;
280 bool getBoolOption(const char *longflag) const;
281 MultiStringRange getMultiStringOption(char shortflag) const;
282 MultiStringRange getMultiStringOption(const char *longflag) const;
284 /*
285 * Return whether the help option was present (and thus help was already
286 * displayed during parse_args).
287 */
288 bool getHelpOption() const;
289 };
291 } /* namespace cli */
292 } /* namespace js */
294 #endif /* shell_jsoptparse_h */