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
21namespace llvm {
22
23class raw_ostream;
24
25namespace opt {
26
27class Arg;
28class ArgList;
29
30/// ArgStringList - Type used for constructing argv lists for subprocesses.
31using ArgStringList = SmallVector<const char *, 16>;
32
33/// Base flags for all options. Custom flags may be added after.
34enum 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.
52class Option {
53public:
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
77protected:
78  const OptTable::Info *Info;
79  const OptTable *Owner;
80
81public:
82  Option(const OptTable::Info *Info, const OptTable *Owner);
83
84  bool isValid() const {
85    return Info != nullptr;
86  }
87
88  unsigned getID() const {
89    assert(Info && "Must have a valid info!");
90    return Info->ID;
91  }
92
93  OptionClass getKind() const {
94    assert(Info && "Must have a valid info!");
95    return OptionClass(Info->Kind);
96  }
97
98  /// \brief Get the name of this option without any prefix.
99  StringRef getName() const {
100    assert(Info && "Must have a valid info!");
101    return Info->Name;
102  }
103
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
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  /// \brief Get the alias arguments as a \0 separated list.
117  /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0".
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  /// \brief Get the default prefix for this option.
127  StringRef getPrefix() const {
128    const char *Prefix = *Info->Prefixes;
129    return Prefix ? Prefix : StringRef();
130  }
131
132  /// \brief 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  unsigned getNumArgs() const { return Info->Param; }
140
141  bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;}
142
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.
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).
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.
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