• 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 "clang/Driver/Option.h"
11 
12 #include "clang/Driver/Arg.h"
13 #include "clang/Driver/ArgList.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include <cassert>
17 #include <algorithm>
18 using namespace clang::driver;
19 
Option(const OptTable::Info * info,OptSpecifier _ID,const Option * _Group,const Option * _Alias)20 Option::Option(const OptTable::Info *info, OptSpecifier _ID,
21                const Option *_Group, const Option *_Alias)
22   : Info(info), ID(_ID.getID()), Group(_Group), Alias(_Alias) {
23 
24   // Multi-level aliases are not supported, and alias options cannot
25   // have groups. This just simplifies option tracking, it is not an
26   // inherent limitation.
27   assert((!Alias || (!Alias->Alias && !Group)) &&
28          "Multi-level aliases and aliases with groups are unsupported.");
29 }
30 
~Option()31 Option::~Option() {
32 }
33 
dump() const34 void Option::dump() const {
35   llvm::errs() << "<";
36   switch (getKind()) {
37 #define P(N) case N: llvm::errs() << #N; break
38     P(GroupClass);
39     P(InputClass);
40     P(UnknownClass);
41     P(FlagClass);
42     P(JoinedClass);
43     P(SeparateClass);
44     P(CommaJoinedClass);
45     P(MultiArgClass);
46     P(JoinedOrSeparateClass);
47     P(JoinedAndSeparateClass);
48 #undef P
49   }
50 
51   llvm::errs() << " Name:\"" << getName() << '"';
52 
53   if (Group) {
54     llvm::errs() << " Group:";
55     Group->dump();
56   }
57 
58   if (Alias) {
59     llvm::errs() << " Alias:";
60     Alias->dump();
61   }
62 
63   if (getKind() == MultiArgClass)
64     llvm::errs() << " NumArgs:" << getNumArgs();
65 
66   llvm::errs() << ">\n";
67 }
68 
matches(OptSpecifier Opt) const69 bool Option::matches(OptSpecifier Opt) const {
70   // Aliases are never considered in matching, look through them.
71   if (Alias)
72     return Alias->matches(Opt);
73 
74   // Check exact match.
75   if (ID == Opt)
76     return true;
77 
78   if (Group)
79     return Group->matches(Opt);
80   return false;
81 }
82 
accept(const ArgList & Args,unsigned & Index) const83 Arg *Option::accept(const ArgList &Args, unsigned &Index) const {
84   switch (getKind()) {
85   case FlagClass:
86     if (getName().size() != strlen(Args.getArgString(Index)))
87       return 0;
88 
89     return new Arg(getUnaliasedOption(), Index++);
90   case JoinedClass: {
91     const char *Value = Args.getArgString(Index) + getName().size();
92     return new Arg(getUnaliasedOption(), Index++, Value);
93   }
94   case CommaJoinedClass: {
95     // Always matches.
96     const char *Str = Args.getArgString(Index) + getName().size();
97     Arg *A = new Arg(getUnaliasedOption(), Index++);
98 
99     // Parse out the comma separated values.
100     const char *Prev = Str;
101     for (;; ++Str) {
102       char c = *Str;
103 
104       if (!c || c == ',') {
105         if (Prev != Str) {
106           char *Value = new char[Str - Prev + 1];
107           memcpy(Value, Prev, Str - Prev);
108           Value[Str - Prev] = '\0';
109           A->getValues().push_back(Value);
110         }
111 
112         if (!c)
113           break;
114 
115         Prev = Str + 1;
116       }
117     }
118     A->setOwnsValues(true);
119 
120     return A;
121   }
122   case SeparateClass:
123     // Matches iff this is an exact match.
124     // FIXME: Avoid strlen.
125     if (getName().size() != strlen(Args.getArgString(Index)))
126       return 0;
127 
128     Index += 2;
129     if (Index > Args.getNumInputArgStrings())
130       return 0;
131 
132     return new Arg(getUnaliasedOption(),
133                    Index - 2, Args.getArgString(Index - 1));
134   case MultiArgClass: {
135     // Matches iff this is an exact match.
136     // FIXME: Avoid strlen.
137     if (getName().size() != strlen(Args.getArgString(Index)))
138       return 0;
139 
140     Index += 1 + getNumArgs();
141     if (Index > Args.getNumInputArgStrings())
142       return 0;
143 
144     Arg *A = new Arg(getUnaliasedOption(), Index - 1 - getNumArgs(),
145                       Args.getArgString(Index - getNumArgs()));
146     for (unsigned i = 1; i != getNumArgs(); ++i)
147       A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
148     return A;
149   }
150   case JoinedOrSeparateClass: {
151     // If this is not an exact match, it is a joined arg.
152     // FIXME: Avoid strlen.
153     if (getName().size() != strlen(Args.getArgString(Index))) {
154       const char *Value = Args.getArgString(Index) + getName().size();
155       return new Arg(this, Index++, Value);
156     }
157 
158     // Otherwise it must be separate.
159     Index += 2;
160     if (Index > Args.getNumInputArgStrings())
161       return 0;
162 
163     return new Arg(getUnaliasedOption(),
164                    Index - 2, Args.getArgString(Index - 1));
165   }
166   case JoinedAndSeparateClass:
167     // Always matches.
168     Index += 2;
169     if (Index > Args.getNumInputArgStrings())
170       return 0;
171 
172     return new Arg(getUnaliasedOption(), Index - 2,
173                    Args.getArgString(Index-2)+getName().size(),
174                    Args.getArgString(Index-1));
175   default:
176     llvm_unreachable("Invalid option kind!");
177   }
178 }
179