1 //===- Option.h - Abstract Driver Options -----------------------*- C++ -*-===//
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 #ifndef LLVM_OPTION_OPTION_H
11 #define LLVM_OPTION_OPTION_H
12 
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Option/OptSpecifier.h"
16 #include "llvm/Option/OptTable.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include <cassert>
19 #include <string>
20 
21 namespace llvm {
22 
23 class raw_ostream;
24 
25 namespace opt {
26 
27 class Arg;
28 class ArgList;
29 
30 /// ArgStringList - Type used for constructing argv lists for subprocesses.
31 using ArgStringList = SmallVector<const char *, 16>;
32 
33 /// Base flags for all options. Custom flags may be added after.
34 enum DriverFlag {
35   HelpHidden       = (1 << 0),
36   RenderAsInput    = (1 << 1),
37   RenderJoined     = (1 << 2),
38   RenderSeparate   = (1 << 3)
39 };
40 
41 /// Option - Abstract representation for a single form of driver
42 /// argument.
43 ///
44 /// An Option class represents a form of option that the driver
45 /// takes, for example how many arguments the option has and how
46 /// they can be provided. Individual option instances store
47 /// additional information about what group the option is a member
48 /// of (if any), if the option is an alias, and a number of
49 /// flags. At runtime the driver parses the command line into
50 /// concrete Arg instances, each of which corresponds to a
51 /// particular Option instance.
52 class Option {
53 public:
54   enum OptionClass {
55     GroupClass = 0,
56     InputClass,
57     UnknownClass,
58     FlagClass,
59     JoinedClass,
60     ValuesClass,
61     SeparateClass,
62     RemainingArgsClass,
63     RemainingArgsJoinedClass,
64     CommaJoinedClass,
65     MultiArgClass,
66     JoinedOrSeparateClass,
67     JoinedAndSeparateClass
68   };
69 
70   enum RenderStyleKind {
71     RenderCommaJoinedStyle,
72     RenderJoinedStyle,
73     RenderSeparateStyle,
74     RenderValuesStyle
75   };
76 
77 protected:
78   const OptTable::Info *Info;
79   const OptTable *Owner;
80 
81 public:
82   Option(const OptTable::Info *Info, const OptTable *Owner);
83 
isValid()84   bool isValid() const {
85     return Info != nullptr;
86   }
87 
getID()88   unsigned getID() const {
89     assert(Info && "Must have a valid info!");
90     return Info->ID;
91   }
92 
getKind()93   OptionClass getKind() const {
94     assert(Info && "Must have a valid info!");
95     return OptionClass(Info->Kind);
96   }
97 
98   /// Get the name of this option without any prefix.
getName()99   StringRef getName() const {
100     assert(Info && "Must have a valid info!");
101     return Info->Name;
102   }
103 
getGroup()104   const Option getGroup() const {
105     assert(Info && "Must have a valid info!");
106     assert(Owner && "Must have a valid owner!");
107     return Owner->getOption(Info->GroupID);
108   }
109 
getAlias()110   const Option getAlias() const {
111     assert(Info && "Must have a valid info!");
112     assert(Owner && "Must have a valid owner!");
113     return Owner->getOption(Info->AliasID);
114   }
115 
116   /// Get the alias arguments as a \0 separated list.
117   /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0".
getAliasArgs()118   const char *getAliasArgs() const {
119     assert(Info && "Must have a valid info!");
120     assert((!Info->AliasArgs || Info->AliasArgs[0] != 0) &&
121            "AliasArgs should be either 0 or non-empty.");
122 
123     return Info->AliasArgs;
124   }
125 
126   /// Get the default prefix for this option.
getPrefix()127   StringRef getPrefix() const {
128     const char *Prefix = *Info->Prefixes;
129     return Prefix ? Prefix : StringRef();
130   }
131 
132   /// Get the name of this option with the default prefix.
getPrefixedName()133   std::string getPrefixedName() const {
134     std::string Ret = getPrefix();
135     Ret += getName();
136     return Ret;
137   }
138 
getNumArgs()139   unsigned getNumArgs() const { return Info->Param; }
140 
hasNoOptAsInput()141   bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;}
142 
getRenderStyle()143   RenderStyleKind getRenderStyle() const {
144     if (Info->Flags & RenderJoined)
145       return RenderJoinedStyle;
146     if (Info->Flags & RenderSeparate)
147       return RenderSeparateStyle;
148     switch (getKind()) {
149     case GroupClass:
150     case InputClass:
151     case UnknownClass:
152       return RenderValuesStyle;
153     case JoinedClass:
154     case JoinedAndSeparateClass:
155       return RenderJoinedStyle;
156     case CommaJoinedClass:
157       return RenderCommaJoinedStyle;
158     case FlagClass:
159     case ValuesClass:
160     case SeparateClass:
161     case MultiArgClass:
162     case JoinedOrSeparateClass:
163     case RemainingArgsClass:
164     case RemainingArgsJoinedClass:
165       return RenderSeparateStyle;
166     }
167     llvm_unreachable("Unexpected kind!");
168   }
169 
170   /// Test if this option has the flag \a Val.
hasFlag(unsigned Val)171   bool hasFlag(unsigned Val) const {
172     return Info->Flags & Val;
173   }
174 
175   /// getUnaliasedOption - Return the final option this option
176   /// aliases (itself, if the option has no alias).
getUnaliasedOption()177   const Option getUnaliasedOption() const {
178     const Option Alias = getAlias();
179     if (Alias.isValid()) return Alias.getUnaliasedOption();
180     return *this;
181   }
182 
183   /// getRenderName - Return the name to use when rendering this
184   /// option.
getRenderName()185   StringRef getRenderName() const {
186     return getUnaliasedOption().getName();
187   }
188 
189   /// matches - Predicate for whether this option is part of the
190   /// given option (which may be a group).
191   ///
192   /// Note that matches against options which are an alias should never be
193   /// done -- aliases do not participate in matching and so such a query will
194   /// always be false.
195   bool matches(OptSpecifier ID) const;
196 
197   /// accept - Potentially accept the current argument, returning a
198   /// new Arg instance, or 0 if the option does not accept this
199   /// argument (or the argument is missing values).
200   ///
201   /// If the option accepts the current argument, accept() sets
202   /// Index to the position where argument parsing should resume
203   /// (even if the argument is missing values).
204   ///
205   /// \param ArgSize The number of bytes taken up by the matched Option prefix
206   ///                and name. This is used to determine where joined values
207   ///                start.
208   Arg *accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const;
209 
210   void print(raw_ostream &O) const;
211   void dump() const;
212 };
213 
214 } // end namespace opt
215 
216 } // end namespace llvm
217 
218 #endif // LLVM_OPTION_OPTION_H
219