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