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