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