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