1//===--- OptTable.h - Option Table ------------------------------*- 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_OPTTABLE_H
11#define CLANG_DRIVER_OPTTABLE_H
12
13#include "clang/Basic/LLVM.h"
14#include "clang/Driver/OptSpecifier.h"
15
16namespace clang {
17namespace driver {
18  class Arg;
19  class ArgList;
20  class InputArgList;
21  class Option;
22
23  /// \brief Provide access to the Option info table.
24  ///
25  /// The OptTable class provides a layer of indirection which allows Option
26  /// instance to be created lazily. In the common case, only a few options will
27  /// be needed at runtime; the OptTable class maintains enough information to
28  /// parse command lines without instantiating Options, while letting other
29  /// parts of the driver still use Option instances where convenient.
30  class OptTable {
31  public:
32    /// \brief Entry for a single option instance in the option data table.
33    struct Info {
34      const char *Name;
35      const char *HelpText;
36      const char *MetaVar;
37      unsigned char Kind;
38      unsigned char Param;
39      unsigned short Flags;
40      unsigned short GroupID;
41      unsigned short AliasID;
42    };
43
44  private:
45    /// \brief The static option information table.
46    const Info *OptionInfos;
47    unsigned NumOptionInfos;
48
49    /// \brief The lazily constructed options table, indexed by option::ID - 1.
50    mutable Option **Options;
51
52    /// \brief Prebound input option instance.
53    const Option *TheInputOption;
54
55    /// \brief Prebound unknown option instance.
56    const Option *TheUnknownOption;
57
58    /// The index of the first option which can be parsed (i.e., is not a
59    /// special option like 'input' or 'unknown', and is not an option group).
60    unsigned FirstSearchableIndex;
61
62  private:
63    const Info &getInfo(OptSpecifier Opt) const {
64      unsigned id = Opt.getID();
65      assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID.");
66      return OptionInfos[id - 1];
67    }
68
69    Option *CreateOption(unsigned id) const;
70
71  protected:
72    OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos);
73  public:
74    ~OptTable();
75
76    /// \brief Return the total number of option classes.
77    unsigned getNumOptions() const { return NumOptionInfos; }
78
79    /// \brief Get the given Opt's Option instance, lazily creating it
80    /// if necessary.
81    ///
82    /// \return The option, or null for the INVALID option id.
83    const Option *getOption(OptSpecifier Opt) const {
84      unsigned id = Opt.getID();
85      if (id == 0)
86        return 0;
87
88      assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
89      Option *&Entry = Options[id - 1];
90      if (!Entry)
91        Entry = CreateOption(id);
92      return Entry;
93    }
94
95    /// \brief Lookup the name of the given option.
96    const char *getOptionName(OptSpecifier id) const {
97      return getInfo(id).Name;
98    }
99
100    /// \brief Get the kind of the given option.
101    unsigned getOptionKind(OptSpecifier id) const {
102      return getInfo(id).Kind;
103    }
104
105    /// \brief Get the group id for the given option.
106    unsigned getOptionGroupID(OptSpecifier id) const {
107      return getInfo(id).GroupID;
108    }
109
110    /// \brief Should the help for the given option be hidden by default.
111    bool isOptionHelpHidden(OptSpecifier id) const;
112
113    /// \brief Get the help text to use to describe this option.
114    const char *getOptionHelpText(OptSpecifier id) const {
115      return getInfo(id).HelpText;
116    }
117
118    /// \brief Get the meta-variable name to use when describing
119    /// this options values in the help text.
120    const char *getOptionMetaVar(OptSpecifier id) const {
121      return getInfo(id).MetaVar;
122    }
123
124    /// \brief Parse a single argument; returning the new argument and
125    /// updating Index.
126    ///
127    /// \param [in,out] Index - The current parsing position in the argument
128    /// string list; on return this will be the index of the next argument
129    /// string to parse.
130    ///
131    /// \return The parsed argument, or 0 if the argument is missing values
132    /// (in which case Index still points at the conceptual next argument string
133    /// to parse).
134    Arg *ParseOneArg(const ArgList &Args, unsigned &Index) const;
135
136    /// \brief Parse an list of arguments into an InputArgList.
137    ///
138    /// The resulting InputArgList will reference the strings in [\p ArgBegin,
139    /// \p ArgEnd), and their lifetime should extend past that of the returned
140    /// InputArgList.
141    ///
142    /// The only error that can occur in this routine is if an argument is
143    /// missing values; in this case \p MissingArgCount will be non-zero.
144    ///
145    /// \param ArgBegin - The beginning of the argument vector.
146    /// \param ArgEnd - The end of the argument vector.
147    /// \param MissingArgIndex - On error, the index of the option which could
148    /// not be parsed.
149    /// \param MissingArgCount - On error, the number of missing options.
150    /// \return An InputArgList; on error this will contain all the options
151    /// which could be parsed.
152    InputArgList *ParseArgs(const char* const *ArgBegin,
153                            const char* const *ArgEnd,
154                            unsigned &MissingArgIndex,
155                            unsigned &MissingArgCount) const;
156
157    /// \brief Render the help text for an option table.
158    ///
159    /// \param OS - The stream to write the help text to.
160    /// \param Name - The name to use in the usage line.
161    /// \param Title - The title to use in the usage line.
162    /// \param ShowHidden - Whether help-hidden arguments should be shown.
163    void PrintHelp(raw_ostream &OS, const char *Name,
164                   const char *Title, bool ShowHidden = false) const;
165  };
166}
167}
168
169#endif
170