1*9880d681SAndroid Build Coastguard Worker //===--- OptTable.cpp - Option Table Implementation -----------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "llvm/Option/OptTable.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/Option/Arg.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/Option/ArgList.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/Option/Option.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
16*9880d681SAndroid Build Coastguard Worker #include <algorithm>
17*9880d681SAndroid Build Coastguard Worker #include <cctype>
18*9880d681SAndroid Build Coastguard Worker #include <map>
19*9880d681SAndroid Build Coastguard Worker
20*9880d681SAndroid Build Coastguard Worker using namespace llvm;
21*9880d681SAndroid Build Coastguard Worker using namespace llvm::opt;
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker namespace llvm {
24*9880d681SAndroid Build Coastguard Worker namespace opt {
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker // Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
27*9880d681SAndroid Build Coastguard Worker // with an exceptions. '\0' comes at the end of the alphabet instead of the
28*9880d681SAndroid Build Coastguard Worker // beginning (thus options precede any other options which prefix them).
StrCmpOptionNameIgnoreCase(const char * A,const char * B)29*9880d681SAndroid Build Coastguard Worker static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) {
30*9880d681SAndroid Build Coastguard Worker const char *X = A, *Y = B;
31*9880d681SAndroid Build Coastguard Worker char a = tolower(*A), b = tolower(*B);
32*9880d681SAndroid Build Coastguard Worker while (a == b) {
33*9880d681SAndroid Build Coastguard Worker if (a == '\0')
34*9880d681SAndroid Build Coastguard Worker return 0;
35*9880d681SAndroid Build Coastguard Worker
36*9880d681SAndroid Build Coastguard Worker a = tolower(*++X);
37*9880d681SAndroid Build Coastguard Worker b = tolower(*++Y);
38*9880d681SAndroid Build Coastguard Worker }
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker if (a == '\0') // A is a prefix of B.
41*9880d681SAndroid Build Coastguard Worker return 1;
42*9880d681SAndroid Build Coastguard Worker if (b == '\0') // B is a prefix of A.
43*9880d681SAndroid Build Coastguard Worker return -1;
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker // Otherwise lexicographic.
46*9880d681SAndroid Build Coastguard Worker return (a < b) ? -1 : 1;
47*9880d681SAndroid Build Coastguard Worker }
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
StrCmpOptionName(const char * A,const char * B)50*9880d681SAndroid Build Coastguard Worker static int StrCmpOptionName(const char *A, const char *B) {
51*9880d681SAndroid Build Coastguard Worker if (int N = StrCmpOptionNameIgnoreCase(A, B))
52*9880d681SAndroid Build Coastguard Worker return N;
53*9880d681SAndroid Build Coastguard Worker return strcmp(A, B);
54*9880d681SAndroid Build Coastguard Worker }
55*9880d681SAndroid Build Coastguard Worker
operator <(const OptTable::Info & A,const OptTable::Info & B)56*9880d681SAndroid Build Coastguard Worker static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
57*9880d681SAndroid Build Coastguard Worker if (&A == &B)
58*9880d681SAndroid Build Coastguard Worker return false;
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker if (int N = StrCmpOptionName(A.Name, B.Name))
61*9880d681SAndroid Build Coastguard Worker return N < 0;
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker for (const char * const *APre = A.Prefixes,
64*9880d681SAndroid Build Coastguard Worker * const *BPre = B.Prefixes;
65*9880d681SAndroid Build Coastguard Worker *APre != nullptr && *BPre != nullptr; ++APre, ++BPre){
66*9880d681SAndroid Build Coastguard Worker if (int N = StrCmpOptionName(*APre, *BPre))
67*9880d681SAndroid Build Coastguard Worker return N < 0;
68*9880d681SAndroid Build Coastguard Worker }
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker // Names are the same, check that classes are in order; exactly one
71*9880d681SAndroid Build Coastguard Worker // should be joined, and it should succeed the other.
72*9880d681SAndroid Build Coastguard Worker assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
73*9880d681SAndroid Build Coastguard Worker "Unexpected classes for options with same name.");
74*9880d681SAndroid Build Coastguard Worker return B.Kind == Option::JoinedClass;
75*9880d681SAndroid Build Coastguard Worker }
76*9880d681SAndroid Build Coastguard Worker #endif
77*9880d681SAndroid Build Coastguard Worker
78*9880d681SAndroid Build Coastguard Worker // Support lower_bound between info and an option name.
operator <(const OptTable::Info & I,const char * Name)79*9880d681SAndroid Build Coastguard Worker static inline bool operator<(const OptTable::Info &I, const char *Name) {
80*9880d681SAndroid Build Coastguard Worker return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
81*9880d681SAndroid Build Coastguard Worker }
82*9880d681SAndroid Build Coastguard Worker }
83*9880d681SAndroid Build Coastguard Worker }
84*9880d681SAndroid Build Coastguard Worker
OptSpecifier(const Option * Opt)85*9880d681SAndroid Build Coastguard Worker OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
86*9880d681SAndroid Build Coastguard Worker
OptTable(ArrayRef<Info> OptionInfos,bool IgnoreCase)87*9880d681SAndroid Build Coastguard Worker OptTable::OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
88*9880d681SAndroid Build Coastguard Worker : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase), TheInputOptionID(0),
89*9880d681SAndroid Build Coastguard Worker TheUnknownOptionID(0), FirstSearchableIndex(0) {
90*9880d681SAndroid Build Coastguard Worker // Explicitly zero initialize the error to work around a bug in array
91*9880d681SAndroid Build Coastguard Worker // value-initialization on MinGW with gcc 4.3.5.
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker // Find start of normal options.
94*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
95*9880d681SAndroid Build Coastguard Worker unsigned Kind = getInfo(i + 1).Kind;
96*9880d681SAndroid Build Coastguard Worker if (Kind == Option::InputClass) {
97*9880d681SAndroid Build Coastguard Worker assert(!TheInputOptionID && "Cannot have multiple input options!");
98*9880d681SAndroid Build Coastguard Worker TheInputOptionID = getInfo(i + 1).ID;
99*9880d681SAndroid Build Coastguard Worker } else if (Kind == Option::UnknownClass) {
100*9880d681SAndroid Build Coastguard Worker assert(!TheUnknownOptionID && "Cannot have multiple unknown options!");
101*9880d681SAndroid Build Coastguard Worker TheUnknownOptionID = getInfo(i + 1).ID;
102*9880d681SAndroid Build Coastguard Worker } else if (Kind != Option::GroupClass) {
103*9880d681SAndroid Build Coastguard Worker FirstSearchableIndex = i;
104*9880d681SAndroid Build Coastguard Worker break;
105*9880d681SAndroid Build Coastguard Worker }
106*9880d681SAndroid Build Coastguard Worker }
107*9880d681SAndroid Build Coastguard Worker assert(FirstSearchableIndex != 0 && "No searchable options?");
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
110*9880d681SAndroid Build Coastguard Worker // Check that everything after the first searchable option is a
111*9880d681SAndroid Build Coastguard Worker // regular option class.
112*9880d681SAndroid Build Coastguard Worker for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
113*9880d681SAndroid Build Coastguard Worker Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
114*9880d681SAndroid Build Coastguard Worker assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
115*9880d681SAndroid Build Coastguard Worker Kind != Option::GroupClass) &&
116*9880d681SAndroid Build Coastguard Worker "Special options should be defined first!");
117*9880d681SAndroid Build Coastguard Worker }
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker // Check that options are in order.
120*9880d681SAndroid Build Coastguard Worker for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions(); i != e; ++i){
121*9880d681SAndroid Build Coastguard Worker if (!(getInfo(i) < getInfo(i + 1))) {
122*9880d681SAndroid Build Coastguard Worker getOption(i).dump();
123*9880d681SAndroid Build Coastguard Worker getOption(i + 1).dump();
124*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Options are not in order!");
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker }
127*9880d681SAndroid Build Coastguard Worker #endif
128*9880d681SAndroid Build Coastguard Worker
129*9880d681SAndroid Build Coastguard Worker // Build prefixes.
130*9880d681SAndroid Build Coastguard Worker for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
131*9880d681SAndroid Build Coastguard Worker i != e; ++i) {
132*9880d681SAndroid Build Coastguard Worker if (const char *const *P = getInfo(i).Prefixes) {
133*9880d681SAndroid Build Coastguard Worker for (; *P != nullptr; ++P) {
134*9880d681SAndroid Build Coastguard Worker PrefixesUnion.insert(*P);
135*9880d681SAndroid Build Coastguard Worker }
136*9880d681SAndroid Build Coastguard Worker }
137*9880d681SAndroid Build Coastguard Worker }
138*9880d681SAndroid Build Coastguard Worker
139*9880d681SAndroid Build Coastguard Worker // Build prefix chars.
140*9880d681SAndroid Build Coastguard Worker for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(),
141*9880d681SAndroid Build Coastguard Worker E = PrefixesUnion.end(); I != E; ++I) {
142*9880d681SAndroid Build Coastguard Worker StringRef Prefix = I->getKey();
143*9880d681SAndroid Build Coastguard Worker for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
144*9880d681SAndroid Build Coastguard Worker C != CE; ++C)
145*9880d681SAndroid Build Coastguard Worker if (std::find(PrefixChars.begin(), PrefixChars.end(), *C)
146*9880d681SAndroid Build Coastguard Worker == PrefixChars.end())
147*9880d681SAndroid Build Coastguard Worker PrefixChars.push_back(*C);
148*9880d681SAndroid Build Coastguard Worker }
149*9880d681SAndroid Build Coastguard Worker }
150*9880d681SAndroid Build Coastguard Worker
~OptTable()151*9880d681SAndroid Build Coastguard Worker OptTable::~OptTable() {
152*9880d681SAndroid Build Coastguard Worker }
153*9880d681SAndroid Build Coastguard Worker
getOption(OptSpecifier Opt) const154*9880d681SAndroid Build Coastguard Worker const Option OptTable::getOption(OptSpecifier Opt) const {
155*9880d681SAndroid Build Coastguard Worker unsigned id = Opt.getID();
156*9880d681SAndroid Build Coastguard Worker if (id == 0)
157*9880d681SAndroid Build Coastguard Worker return Option(nullptr, nullptr);
158*9880d681SAndroid Build Coastguard Worker assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
159*9880d681SAndroid Build Coastguard Worker return Option(&getInfo(id), this);
160*9880d681SAndroid Build Coastguard Worker }
161*9880d681SAndroid Build Coastguard Worker
isInput(const llvm::StringSet<> & Prefixes,StringRef Arg)162*9880d681SAndroid Build Coastguard Worker static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) {
163*9880d681SAndroid Build Coastguard Worker if (Arg == "-")
164*9880d681SAndroid Build Coastguard Worker return true;
165*9880d681SAndroid Build Coastguard Worker for (llvm::StringSet<>::const_iterator I = Prefixes.begin(),
166*9880d681SAndroid Build Coastguard Worker E = Prefixes.end(); I != E; ++I)
167*9880d681SAndroid Build Coastguard Worker if (Arg.startswith(I->getKey()))
168*9880d681SAndroid Build Coastguard Worker return false;
169*9880d681SAndroid Build Coastguard Worker return true;
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker /// \returns Matched size. 0 means no match.
matchOption(const OptTable::Info * I,StringRef Str,bool IgnoreCase)173*9880d681SAndroid Build Coastguard Worker static unsigned matchOption(const OptTable::Info *I, StringRef Str,
174*9880d681SAndroid Build Coastguard Worker bool IgnoreCase) {
175*9880d681SAndroid Build Coastguard Worker for (const char * const *Pre = I->Prefixes; *Pre != nullptr; ++Pre) {
176*9880d681SAndroid Build Coastguard Worker StringRef Prefix(*Pre);
177*9880d681SAndroid Build Coastguard Worker if (Str.startswith(Prefix)) {
178*9880d681SAndroid Build Coastguard Worker StringRef Rest = Str.substr(Prefix.size());
179*9880d681SAndroid Build Coastguard Worker bool Matched = IgnoreCase
180*9880d681SAndroid Build Coastguard Worker ? Rest.startswith_lower(I->Name)
181*9880d681SAndroid Build Coastguard Worker : Rest.startswith(I->Name);
182*9880d681SAndroid Build Coastguard Worker if (Matched)
183*9880d681SAndroid Build Coastguard Worker return Prefix.size() + StringRef(I->Name).size();
184*9880d681SAndroid Build Coastguard Worker }
185*9880d681SAndroid Build Coastguard Worker }
186*9880d681SAndroid Build Coastguard Worker return 0;
187*9880d681SAndroid Build Coastguard Worker }
188*9880d681SAndroid Build Coastguard Worker
ParseOneArg(const ArgList & Args,unsigned & Index,unsigned FlagsToInclude,unsigned FlagsToExclude) const189*9880d681SAndroid Build Coastguard Worker Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
190*9880d681SAndroid Build Coastguard Worker unsigned FlagsToInclude,
191*9880d681SAndroid Build Coastguard Worker unsigned FlagsToExclude) const {
192*9880d681SAndroid Build Coastguard Worker unsigned Prev = Index;
193*9880d681SAndroid Build Coastguard Worker const char *Str = Args.getArgString(Index);
194*9880d681SAndroid Build Coastguard Worker
195*9880d681SAndroid Build Coastguard Worker // Anything that doesn't start with PrefixesUnion is an input, as is '-'
196*9880d681SAndroid Build Coastguard Worker // itself.
197*9880d681SAndroid Build Coastguard Worker if (isInput(PrefixesUnion, Str))
198*9880d681SAndroid Build Coastguard Worker return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
199*9880d681SAndroid Build Coastguard Worker
200*9880d681SAndroid Build Coastguard Worker const Info *Start = OptionInfos.begin() + FirstSearchableIndex;
201*9880d681SAndroid Build Coastguard Worker const Info *End = OptionInfos.end();
202*9880d681SAndroid Build Coastguard Worker StringRef Name = StringRef(Str).ltrim(PrefixChars);
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker // Search for the first next option which could be a prefix.
205*9880d681SAndroid Build Coastguard Worker Start = std::lower_bound(Start, End, Name.data());
206*9880d681SAndroid Build Coastguard Worker
207*9880d681SAndroid Build Coastguard Worker // Options are stored in sorted order, with '\0' at the end of the
208*9880d681SAndroid Build Coastguard Worker // alphabet. Since the only options which can accept a string must
209*9880d681SAndroid Build Coastguard Worker // prefix it, we iteratively search for the next option which could
210*9880d681SAndroid Build Coastguard Worker // be a prefix.
211*9880d681SAndroid Build Coastguard Worker //
212*9880d681SAndroid Build Coastguard Worker // FIXME: This is searching much more than necessary, but I am
213*9880d681SAndroid Build Coastguard Worker // blanking on the simplest way to make it fast. We can solve this
214*9880d681SAndroid Build Coastguard Worker // problem when we move to TableGen.
215*9880d681SAndroid Build Coastguard Worker for (; Start != End; ++Start) {
216*9880d681SAndroid Build Coastguard Worker unsigned ArgSize = 0;
217*9880d681SAndroid Build Coastguard Worker // Scan for first option which is a proper prefix.
218*9880d681SAndroid Build Coastguard Worker for (; Start != End; ++Start)
219*9880d681SAndroid Build Coastguard Worker if ((ArgSize = matchOption(Start, Str, IgnoreCase)))
220*9880d681SAndroid Build Coastguard Worker break;
221*9880d681SAndroid Build Coastguard Worker if (Start == End)
222*9880d681SAndroid Build Coastguard Worker break;
223*9880d681SAndroid Build Coastguard Worker
224*9880d681SAndroid Build Coastguard Worker Option Opt(Start, this);
225*9880d681SAndroid Build Coastguard Worker
226*9880d681SAndroid Build Coastguard Worker if (FlagsToInclude && !Opt.hasFlag(FlagsToInclude))
227*9880d681SAndroid Build Coastguard Worker continue;
228*9880d681SAndroid Build Coastguard Worker if (Opt.hasFlag(FlagsToExclude))
229*9880d681SAndroid Build Coastguard Worker continue;
230*9880d681SAndroid Build Coastguard Worker
231*9880d681SAndroid Build Coastguard Worker // See if this option matches.
232*9880d681SAndroid Build Coastguard Worker if (Arg *A = Opt.accept(Args, Index, ArgSize))
233*9880d681SAndroid Build Coastguard Worker return A;
234*9880d681SAndroid Build Coastguard Worker
235*9880d681SAndroid Build Coastguard Worker // Otherwise, see if this argument was missing values.
236*9880d681SAndroid Build Coastguard Worker if (Prev != Index)
237*9880d681SAndroid Build Coastguard Worker return nullptr;
238*9880d681SAndroid Build Coastguard Worker }
239*9880d681SAndroid Build Coastguard Worker
240*9880d681SAndroid Build Coastguard Worker // If we failed to find an option and this arg started with /, then it's
241*9880d681SAndroid Build Coastguard Worker // probably an input path.
242*9880d681SAndroid Build Coastguard Worker if (Str[0] == '/')
243*9880d681SAndroid Build Coastguard Worker return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str);
246*9880d681SAndroid Build Coastguard Worker }
247*9880d681SAndroid Build Coastguard Worker
ParseArgs(ArrayRef<const char * > ArgArr,unsigned & MissingArgIndex,unsigned & MissingArgCount,unsigned FlagsToInclude,unsigned FlagsToExclude) const248*9880d681SAndroid Build Coastguard Worker InputArgList OptTable::ParseArgs(ArrayRef<const char *> ArgArr,
249*9880d681SAndroid Build Coastguard Worker unsigned &MissingArgIndex,
250*9880d681SAndroid Build Coastguard Worker unsigned &MissingArgCount,
251*9880d681SAndroid Build Coastguard Worker unsigned FlagsToInclude,
252*9880d681SAndroid Build Coastguard Worker unsigned FlagsToExclude) const {
253*9880d681SAndroid Build Coastguard Worker InputArgList Args(ArgArr.begin(), ArgArr.end());
254*9880d681SAndroid Build Coastguard Worker
255*9880d681SAndroid Build Coastguard Worker // FIXME: Handle '@' args (or at least error on them).
256*9880d681SAndroid Build Coastguard Worker
257*9880d681SAndroid Build Coastguard Worker MissingArgIndex = MissingArgCount = 0;
258*9880d681SAndroid Build Coastguard Worker unsigned Index = 0, End = ArgArr.size();
259*9880d681SAndroid Build Coastguard Worker while (Index < End) {
260*9880d681SAndroid Build Coastguard Worker // Ingore nullptrs, they are response file's EOL markers
261*9880d681SAndroid Build Coastguard Worker if (Args.getArgString(Index) == nullptr) {
262*9880d681SAndroid Build Coastguard Worker ++Index;
263*9880d681SAndroid Build Coastguard Worker continue;
264*9880d681SAndroid Build Coastguard Worker }
265*9880d681SAndroid Build Coastguard Worker // Ignore empty arguments (other things may still take them as arguments).
266*9880d681SAndroid Build Coastguard Worker StringRef Str = Args.getArgString(Index);
267*9880d681SAndroid Build Coastguard Worker if (Str == "") {
268*9880d681SAndroid Build Coastguard Worker ++Index;
269*9880d681SAndroid Build Coastguard Worker continue;
270*9880d681SAndroid Build Coastguard Worker }
271*9880d681SAndroid Build Coastguard Worker
272*9880d681SAndroid Build Coastguard Worker unsigned Prev = Index;
273*9880d681SAndroid Build Coastguard Worker Arg *A = ParseOneArg(Args, Index, FlagsToInclude, FlagsToExclude);
274*9880d681SAndroid Build Coastguard Worker assert(Index > Prev && "Parser failed to consume argument.");
275*9880d681SAndroid Build Coastguard Worker
276*9880d681SAndroid Build Coastguard Worker // Check for missing argument error.
277*9880d681SAndroid Build Coastguard Worker if (!A) {
278*9880d681SAndroid Build Coastguard Worker assert(Index >= End && "Unexpected parser error.");
279*9880d681SAndroid Build Coastguard Worker assert(Index - Prev - 1 && "No missing arguments!");
280*9880d681SAndroid Build Coastguard Worker MissingArgIndex = Prev;
281*9880d681SAndroid Build Coastguard Worker MissingArgCount = Index - Prev - 1;
282*9880d681SAndroid Build Coastguard Worker break;
283*9880d681SAndroid Build Coastguard Worker }
284*9880d681SAndroid Build Coastguard Worker
285*9880d681SAndroid Build Coastguard Worker Args.append(A);
286*9880d681SAndroid Build Coastguard Worker }
287*9880d681SAndroid Build Coastguard Worker
288*9880d681SAndroid Build Coastguard Worker return Args;
289*9880d681SAndroid Build Coastguard Worker }
290*9880d681SAndroid Build Coastguard Worker
getOptionHelpName(const OptTable & Opts,OptSpecifier Id)291*9880d681SAndroid Build Coastguard Worker static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
292*9880d681SAndroid Build Coastguard Worker const Option O = Opts.getOption(Id);
293*9880d681SAndroid Build Coastguard Worker std::string Name = O.getPrefixedName();
294*9880d681SAndroid Build Coastguard Worker
295*9880d681SAndroid Build Coastguard Worker // Add metavar, if used.
296*9880d681SAndroid Build Coastguard Worker switch (O.getKind()) {
297*9880d681SAndroid Build Coastguard Worker case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
298*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid option with help text.");
299*9880d681SAndroid Build Coastguard Worker
300*9880d681SAndroid Build Coastguard Worker case Option::MultiArgClass:
301*9880d681SAndroid Build Coastguard Worker if (const char *MetaVarName = Opts.getOptionMetaVar(Id)) {
302*9880d681SAndroid Build Coastguard Worker // For MultiArgs, metavar is full list of all argument names.
303*9880d681SAndroid Build Coastguard Worker Name += ' ';
304*9880d681SAndroid Build Coastguard Worker Name += MetaVarName;
305*9880d681SAndroid Build Coastguard Worker }
306*9880d681SAndroid Build Coastguard Worker else {
307*9880d681SAndroid Build Coastguard Worker // For MultiArgs<N>, if metavar not supplied, print <value> N times.
308*9880d681SAndroid Build Coastguard Worker for (unsigned i=0, e=O.getNumArgs(); i< e; ++i) {
309*9880d681SAndroid Build Coastguard Worker Name += " <value>";
310*9880d681SAndroid Build Coastguard Worker }
311*9880d681SAndroid Build Coastguard Worker }
312*9880d681SAndroid Build Coastguard Worker break;
313*9880d681SAndroid Build Coastguard Worker
314*9880d681SAndroid Build Coastguard Worker case Option::FlagClass:
315*9880d681SAndroid Build Coastguard Worker break;
316*9880d681SAndroid Build Coastguard Worker
317*9880d681SAndroid Build Coastguard Worker case Option::SeparateClass: case Option::JoinedOrSeparateClass:
318*9880d681SAndroid Build Coastguard Worker case Option::RemainingArgsClass: case Option::RemainingArgsJoinedClass:
319*9880d681SAndroid Build Coastguard Worker Name += ' ';
320*9880d681SAndroid Build Coastguard Worker // FALLTHROUGH
321*9880d681SAndroid Build Coastguard Worker case Option::JoinedClass: case Option::CommaJoinedClass:
322*9880d681SAndroid Build Coastguard Worker case Option::JoinedAndSeparateClass:
323*9880d681SAndroid Build Coastguard Worker if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
324*9880d681SAndroid Build Coastguard Worker Name += MetaVarName;
325*9880d681SAndroid Build Coastguard Worker else
326*9880d681SAndroid Build Coastguard Worker Name += "<value>";
327*9880d681SAndroid Build Coastguard Worker break;
328*9880d681SAndroid Build Coastguard Worker }
329*9880d681SAndroid Build Coastguard Worker
330*9880d681SAndroid Build Coastguard Worker return Name;
331*9880d681SAndroid Build Coastguard Worker }
332*9880d681SAndroid Build Coastguard Worker
PrintHelpOptionList(raw_ostream & OS,StringRef Title,std::vector<std::pair<std::string,const char * >> & OptionHelp)333*9880d681SAndroid Build Coastguard Worker static void PrintHelpOptionList(raw_ostream &OS, StringRef Title,
334*9880d681SAndroid Build Coastguard Worker std::vector<std::pair<std::string,
335*9880d681SAndroid Build Coastguard Worker const char*> > &OptionHelp) {
336*9880d681SAndroid Build Coastguard Worker OS << Title << ":\n";
337*9880d681SAndroid Build Coastguard Worker
338*9880d681SAndroid Build Coastguard Worker // Find the maximum option length.
339*9880d681SAndroid Build Coastguard Worker unsigned OptionFieldWidth = 0;
340*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
341*9880d681SAndroid Build Coastguard Worker // Skip titles.
342*9880d681SAndroid Build Coastguard Worker if (!OptionHelp[i].second)
343*9880d681SAndroid Build Coastguard Worker continue;
344*9880d681SAndroid Build Coastguard Worker
345*9880d681SAndroid Build Coastguard Worker // Limit the amount of padding we are willing to give up for alignment.
346*9880d681SAndroid Build Coastguard Worker unsigned Length = OptionHelp[i].first.size();
347*9880d681SAndroid Build Coastguard Worker if (Length <= 23)
348*9880d681SAndroid Build Coastguard Worker OptionFieldWidth = std::max(OptionFieldWidth, Length);
349*9880d681SAndroid Build Coastguard Worker }
350*9880d681SAndroid Build Coastguard Worker
351*9880d681SAndroid Build Coastguard Worker const unsigned InitialPad = 2;
352*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
353*9880d681SAndroid Build Coastguard Worker const std::string &Option = OptionHelp[i].first;
354*9880d681SAndroid Build Coastguard Worker int Pad = OptionFieldWidth - int(Option.size());
355*9880d681SAndroid Build Coastguard Worker OS.indent(InitialPad) << Option;
356*9880d681SAndroid Build Coastguard Worker
357*9880d681SAndroid Build Coastguard Worker // Break on long option names.
358*9880d681SAndroid Build Coastguard Worker if (Pad < 0) {
359*9880d681SAndroid Build Coastguard Worker OS << "\n";
360*9880d681SAndroid Build Coastguard Worker Pad = OptionFieldWidth + InitialPad;
361*9880d681SAndroid Build Coastguard Worker }
362*9880d681SAndroid Build Coastguard Worker OS.indent(Pad + 1) << OptionHelp[i].second << '\n';
363*9880d681SAndroid Build Coastguard Worker }
364*9880d681SAndroid Build Coastguard Worker }
365*9880d681SAndroid Build Coastguard Worker
getOptionHelpGroup(const OptTable & Opts,OptSpecifier Id)366*9880d681SAndroid Build Coastguard Worker static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
367*9880d681SAndroid Build Coastguard Worker unsigned GroupID = Opts.getOptionGroupID(Id);
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker // If not in a group, return the default help group.
370*9880d681SAndroid Build Coastguard Worker if (!GroupID)
371*9880d681SAndroid Build Coastguard Worker return "OPTIONS";
372*9880d681SAndroid Build Coastguard Worker
373*9880d681SAndroid Build Coastguard Worker // Abuse the help text of the option groups to store the "help group"
374*9880d681SAndroid Build Coastguard Worker // name.
375*9880d681SAndroid Build Coastguard Worker //
376*9880d681SAndroid Build Coastguard Worker // FIXME: Split out option groups.
377*9880d681SAndroid Build Coastguard Worker if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
378*9880d681SAndroid Build Coastguard Worker return GroupHelp;
379*9880d681SAndroid Build Coastguard Worker
380*9880d681SAndroid Build Coastguard Worker // Otherwise keep looking.
381*9880d681SAndroid Build Coastguard Worker return getOptionHelpGroup(Opts, GroupID);
382*9880d681SAndroid Build Coastguard Worker }
383*9880d681SAndroid Build Coastguard Worker
PrintHelp(raw_ostream & OS,const char * Name,const char * Title,bool ShowHidden) const384*9880d681SAndroid Build Coastguard Worker void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title,
385*9880d681SAndroid Build Coastguard Worker bool ShowHidden) const {
386*9880d681SAndroid Build Coastguard Worker PrintHelp(OS, Name, Title, /*Include*/ 0, /*Exclude*/
387*9880d681SAndroid Build Coastguard Worker (ShowHidden ? 0 : HelpHidden));
388*9880d681SAndroid Build Coastguard Worker }
389*9880d681SAndroid Build Coastguard Worker
390*9880d681SAndroid Build Coastguard Worker
PrintHelp(raw_ostream & OS,const char * Name,const char * Title,unsigned FlagsToInclude,unsigned FlagsToExclude) const391*9880d681SAndroid Build Coastguard Worker void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title,
392*9880d681SAndroid Build Coastguard Worker unsigned FlagsToInclude,
393*9880d681SAndroid Build Coastguard Worker unsigned FlagsToExclude) const {
394*9880d681SAndroid Build Coastguard Worker OS << "OVERVIEW: " << Title << "\n";
395*9880d681SAndroid Build Coastguard Worker OS << '\n';
396*9880d681SAndroid Build Coastguard Worker OS << "USAGE: " << Name << " [options] <inputs>\n";
397*9880d681SAndroid Build Coastguard Worker OS << '\n';
398*9880d681SAndroid Build Coastguard Worker
399*9880d681SAndroid Build Coastguard Worker // Render help text into a map of group-name to a list of (option, help)
400*9880d681SAndroid Build Coastguard Worker // pairs.
401*9880d681SAndroid Build Coastguard Worker typedef std::map<std::string,
402*9880d681SAndroid Build Coastguard Worker std::vector<std::pair<std::string, const char*> > > helpmap_ty;
403*9880d681SAndroid Build Coastguard Worker helpmap_ty GroupedOptionHelp;
404*9880d681SAndroid Build Coastguard Worker
405*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
406*9880d681SAndroid Build Coastguard Worker unsigned Id = i + 1;
407*9880d681SAndroid Build Coastguard Worker
408*9880d681SAndroid Build Coastguard Worker // FIXME: Split out option groups.
409*9880d681SAndroid Build Coastguard Worker if (getOptionKind(Id) == Option::GroupClass)
410*9880d681SAndroid Build Coastguard Worker continue;
411*9880d681SAndroid Build Coastguard Worker
412*9880d681SAndroid Build Coastguard Worker unsigned Flags = getInfo(Id).Flags;
413*9880d681SAndroid Build Coastguard Worker if (FlagsToInclude && !(Flags & FlagsToInclude))
414*9880d681SAndroid Build Coastguard Worker continue;
415*9880d681SAndroid Build Coastguard Worker if (Flags & FlagsToExclude)
416*9880d681SAndroid Build Coastguard Worker continue;
417*9880d681SAndroid Build Coastguard Worker
418*9880d681SAndroid Build Coastguard Worker if (const char *Text = getOptionHelpText(Id)) {
419*9880d681SAndroid Build Coastguard Worker const char *HelpGroup = getOptionHelpGroup(*this, Id);
420*9880d681SAndroid Build Coastguard Worker const std::string &OptName = getOptionHelpName(*this, Id);
421*9880d681SAndroid Build Coastguard Worker GroupedOptionHelp[HelpGroup].push_back(std::make_pair(OptName, Text));
422*9880d681SAndroid Build Coastguard Worker }
423*9880d681SAndroid Build Coastguard Worker }
424*9880d681SAndroid Build Coastguard Worker
425*9880d681SAndroid Build Coastguard Worker for (helpmap_ty::iterator it = GroupedOptionHelp .begin(),
426*9880d681SAndroid Build Coastguard Worker ie = GroupedOptionHelp.end(); it != ie; ++it) {
427*9880d681SAndroid Build Coastguard Worker if (it != GroupedOptionHelp .begin())
428*9880d681SAndroid Build Coastguard Worker OS << "\n";
429*9880d681SAndroid Build Coastguard Worker PrintHelpOptionList(OS, it->first, it->second);
430*9880d681SAndroid Build Coastguard Worker }
431*9880d681SAndroid Build Coastguard Worker
432*9880d681SAndroid Build Coastguard Worker OS.flush();
433*9880d681SAndroid Build Coastguard Worker }
434