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
20namespace llvm {
21
22class raw_ostream;
23
24namespace opt {
25
26class Arg;
27class ArgList;
28
29/// ArgStringList - Type used for constructing argv lists for subprocesses.
30using ArgStringList = SmallVector<const char *, 16>;
31
32/// Base flags for all options. Custom flags may be added after.
33enum 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.
51class Option {
52public:
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
76protected:
77  const OptTable::Info *Info;
78  const OptTable *Owner;
79
80public:
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    const char *Prefix = *Info->Prefixes;
128    return Prefix ? Prefix : StringRef();
129  }
130
131  /// Get the name of this option with the default prefix.
132  std::string getPrefixedName() const {
133    std::string Ret = getPrefix();
134    Ret += getName();
135    return Ret;
136  }
137
138  unsigned getNumArgs() const { return Info->Param; }
139
140  bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;}
141
142  RenderStyleKind getRenderStyle() const {
143    if (Info->Flags & RenderJoined)
144      return RenderJoinedStyle;
145    if (Info->Flags & RenderSeparate)
146      return RenderSeparateStyle;
147    switch (getKind()) {
148    case GroupClass:
149    case InputClass:
150    case UnknownClass:
151      return RenderValuesStyle;
152    case JoinedClass:
153    case JoinedAndSeparateClass:
154      return RenderJoinedStyle;
155    case CommaJoinedClass:
156      return RenderCommaJoinedStyle;
157    case FlagClass:
158    case ValuesClass:
159    case SeparateClass:
160    case MultiArgClass:
161    case JoinedOrSeparateClass:
162    case RemainingArgsClass:
163    case RemainingArgsJoinedClass:
164      return RenderSeparateStyle;
165    }
166    llvm_unreachable("Unexpected kind!");
167  }
168
169  /// Test if this option has the flag \a Val.
170  bool hasFlag(unsigned Val) const {
171    return Info->Flags & Val;
172  }
173
174  /// getUnaliasedOption - Return the final option this option
175  /// aliases (itself, if the option has no alias).
176  const Option getUnaliasedOption() const {
177    const Option Alias = getAlias();
178    if (Alias.isValid()) return Alias.getUnaliasedOption();
179    return *this;
180  }
181
182  /// getRenderName - Return the name to use when rendering this
183  /// option.
184  StringRef getRenderName() const {
185    return getUnaliasedOption().getName();
186  }
187
188  /// matches - Predicate for whether this option is part of the
189  /// given option (which may be a group).
190  ///
191  /// Note that matches against options which are an alias should never be
192  /// done -- aliases do not participate in matching and so such a query will
193  /// always be false.
194  bool matches(OptSpecifier ID) const;
195
196  /// accept - Potentially accept the current argument, returning a
197  /// new Arg instance, or 0 if the option does not accept this
198  /// argument (or the argument is missing values).
199  ///
200  /// If the option accepts the current argument, accept() sets
201  /// Index to the position where argument parsing should resume
202  /// (even if the argument is missing values).
203  ///
204  /// \param ArgSize The number of bytes taken up by the matched Option prefix
205  ///                and name. This is used to determine where joined values
206  ///                start.
207  Arg *accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const;
208
209private:
210  Arg *acceptInternal(const ArgList &Args, unsigned &Index,
211                      unsigned ArgSize) const;
212
213public:
214  void print(raw_ostream &O) const;
215  void dump() const;
216};
217
218} // end namespace opt
219
220} // end namespace llvm
221
222#endif // LLVM_OPTION_OPTION_H
223