• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- Option.cpp - Abstract Driver Options -----------------------------===//
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/Option.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Option/Arg.h"
13 #include "llvm/Option/ArgList.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include <algorithm>
18 #include <cassert>
19 
20 using namespace llvm;
21 using namespace llvm::opt;
22 
Option(const OptTable::Info * info,const OptTable * owner)23 Option::Option(const OptTable::Info *info, const OptTable *owner)
24   : Info(info), Owner(owner) {
25 
26   // Multi-level aliases are not supported. This just simplifies option
27   // tracking, it is not an inherent limitation.
28   assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
29          "Multi-level aliases are not supported.");
30 
31   if (Info && getAliasArgs()) {
32     assert(getAlias().isValid() && "Only alias options can have alias args.");
33     assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
34     assert(getAlias().getKind() != FlagClass &&
35            "Cannot provide alias args to a flag option.");
36   }
37 }
38 
print(raw_ostream & O) const39 void Option::print(raw_ostream &O) const {
40   O << "<";
41   switch (getKind()) {
42 #define P(N) case N: O << #N; break
43     P(GroupClass);
44     P(InputClass);
45     P(UnknownClass);
46     P(FlagClass);
47     P(JoinedClass);
48     P(SeparateClass);
49     P(CommaJoinedClass);
50     P(MultiArgClass);
51     P(JoinedOrSeparateClass);
52     P(JoinedAndSeparateClass);
53     P(RemainingArgsClass);
54     P(RemainingArgsJoinedClass);
55 #undef P
56   }
57 
58   if (Info->Prefixes) {
59     O << " Prefixes:[";
60     for (const char *const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
61       O << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
62     }
63     O << ']';
64   }
65 
66   O << " Name:\"" << getName() << '"';
67 
68   const Option Group = getGroup();
69   if (Group.isValid()) {
70     O << " Group:";
71     Group.print(O);
72   }
73 
74   const Option Alias = getAlias();
75   if (Alias.isValid()) {
76     O << " Alias:";
77     Alias.print(O);
78   }
79 
80   if (getKind() == MultiArgClass)
81     O << " NumArgs:" << getNumArgs();
82 
83   O << ">\n";
84 }
85 
dump() const86 LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
87 
matches(OptSpecifier Opt) const88 bool Option::matches(OptSpecifier Opt) const {
89   // Aliases are never considered in matching, look through them.
90   const Option Alias = getAlias();
91   if (Alias.isValid())
92     return Alias.matches(Opt);
93 
94   // Check exact match.
95   if (getID() == Opt.getID())
96     return true;
97 
98   const Option Group = getGroup();
99   if (Group.isValid())
100     return Group.matches(Opt);
101   return false;
102 }
103 
accept(const ArgList & Args,unsigned & Index,unsigned ArgSize) const104 Arg *Option::accept(const ArgList &Args,
105                     unsigned &Index,
106                     unsigned ArgSize) const {
107   const Option &UnaliasedOption = getUnaliasedOption();
108   StringRef Spelling;
109   // If the option was an alias, get the spelling from the unaliased one.
110   if (getID() == UnaliasedOption.getID()) {
111     Spelling = StringRef(Args.getArgString(Index), ArgSize);
112   } else {
113     Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
114                                   Twine(UnaliasedOption.getName()));
115   }
116 
117   switch (getKind()) {
118   case FlagClass: {
119     if (ArgSize != strlen(Args.getArgString(Index)))
120       return nullptr;
121 
122     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
123     if (getAliasArgs()) {
124       const char *Val = getAliasArgs();
125       while (*Val != '\0') {
126         A->getValues().push_back(Val);
127 
128         // Move past the '\0' to the next argument.
129         Val += strlen(Val) + 1;
130       }
131     }
132 
133     if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
134       // A Flag alias for a Joined option must provide an argument.
135       A->getValues().push_back("");
136 
137     return A;
138   }
139   case JoinedClass: {
140     const char *Value = Args.getArgString(Index) + ArgSize;
141     return new Arg(UnaliasedOption, Spelling, Index++, Value);
142   }
143   case CommaJoinedClass: {
144     // Always matches.
145     const char *Str = Args.getArgString(Index) + ArgSize;
146     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
147 
148     // Parse out the comma separated values.
149     const char *Prev = Str;
150     for (;; ++Str) {
151       char c = *Str;
152 
153       if (!c || c == ',') {
154         if (Prev != Str) {
155           char *Value = new char[Str - Prev + 1];
156           memcpy(Value, Prev, Str - Prev);
157           Value[Str - Prev] = '\0';
158           A->getValues().push_back(Value);
159         }
160 
161         if (!c)
162           break;
163 
164         Prev = Str + 1;
165       }
166     }
167     A->setOwnsValues(true);
168 
169     return A;
170   }
171   case SeparateClass:
172     // Matches iff this is an exact match.
173     // FIXME: Avoid strlen.
174     if (ArgSize != strlen(Args.getArgString(Index)))
175       return nullptr;
176 
177     Index += 2;
178     if (Index > Args.getNumInputArgStrings() ||
179         Args.getArgString(Index - 1) == nullptr)
180       return nullptr;
181 
182     return new Arg(UnaliasedOption, Spelling,
183                    Index - 2, Args.getArgString(Index - 1));
184   case MultiArgClass: {
185     // Matches iff this is an exact match.
186     // FIXME: Avoid strlen.
187     if (ArgSize != strlen(Args.getArgString(Index)))
188       return nullptr;
189 
190     Index += 1 + getNumArgs();
191     if (Index > Args.getNumInputArgStrings())
192       return nullptr;
193 
194     Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
195                       Args.getArgString(Index - getNumArgs()));
196     for (unsigned i = 1; i != getNumArgs(); ++i)
197       A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
198     return A;
199   }
200   case JoinedOrSeparateClass: {
201     // If this is not an exact match, it is a joined arg.
202     // FIXME: Avoid strlen.
203     if (ArgSize != strlen(Args.getArgString(Index))) {
204       const char *Value = Args.getArgString(Index) + ArgSize;
205       return new Arg(*this, Spelling, Index++, Value);
206     }
207 
208     // Otherwise it must be separate.
209     Index += 2;
210     if (Index > Args.getNumInputArgStrings() ||
211         Args.getArgString(Index - 1) == nullptr)
212       return nullptr;
213 
214     return new Arg(UnaliasedOption, Spelling,
215                    Index - 2, Args.getArgString(Index - 1));
216   }
217   case JoinedAndSeparateClass:
218     // Always matches.
219     Index += 2;
220     if (Index > Args.getNumInputArgStrings() ||
221         Args.getArgString(Index - 1) == nullptr)
222       return nullptr;
223 
224     return new Arg(UnaliasedOption, Spelling, Index - 2,
225                    Args.getArgString(Index - 2) + ArgSize,
226                    Args.getArgString(Index - 1));
227   case RemainingArgsClass: {
228     // Matches iff this is an exact match.
229     // FIXME: Avoid strlen.
230     if (ArgSize != strlen(Args.getArgString(Index)))
231       return nullptr;
232     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
233     while (Index < Args.getNumInputArgStrings() &&
234            Args.getArgString(Index) != nullptr)
235       A->getValues().push_back(Args.getArgString(Index++));
236     return A;
237   }
238   case RemainingArgsJoinedClass: {
239     Arg *A = new Arg(UnaliasedOption, Spelling, Index);
240     if (ArgSize != strlen(Args.getArgString(Index))) {
241       // An inexact match means there is a joined arg.
242       A->getValues().push_back(Args.getArgString(Index) + ArgSize);
243     }
244     Index++;
245     while (Index < Args.getNumInputArgStrings() &&
246            Args.getArgString(Index) != nullptr)
247       A->getValues().push_back(Args.getArgString(Index++));
248     return A;
249   }
250 
251   default:
252     llvm_unreachable("Invalid option kind!");
253   }
254 }
255