OptTable.cpp revision 70a0dbbfbd933c80722549fef2d56de85c32d752
1//===--- Options.cpp - Option info table --------------------------------*-===//
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#include "clang/Driver/Options.h"
11
12#include "clang/Driver/Arg.h"
13#include "clang/Driver/ArgList.h"
14#include "clang/Driver/Option.h"
15#include <cassert>
16
17using namespace clang;
18using namespace clang::driver;
19using namespace clang::driver::options;
20
21struct Info {
22  Option::OptionClass Kind;
23  const char *Name;
24  unsigned GroupID;
25  unsigned AliasID;
26  const char *Flags;
27  unsigned Param;
28};
29
30static Info OptionInfos[] = {
31  // The InputOption info
32  { Option::InputClass, "<input>", 0, 0, "", 0 },
33  // The UnknownOption info
34  { Option::UnknownClass, "<unknown>", 0, 0, "", 0 },
35
36#define OPTION(ID, KIND, NAME, GROUP, ALIAS, FLAGS, PARAM)      \
37  { Option::KIND##Class, NAME, GROUP, ALIAS, FLAGS, PARAM },
38#include "clang/Driver/Options.def"
39};
40static const unsigned numOptions = sizeof(OptionInfos) / sizeof(OptionInfos[0]);
41
42static Info &getInfo(unsigned id) {
43  assert(id > 0 && id - 1 < numOptions && "Invalid Option ID.");
44  return OptionInfos[id - 1];
45}
46
47OptTable::OptTable() : Options(new Option*[numOptions]) {
48}
49
50OptTable::~OptTable() {
51  for (unsigned i=0; i<numOptions; ++i)
52    delete Options[i];
53  delete[] Options;
54}
55
56unsigned OptTable::getNumOptions() const {
57  return numOptions;
58}
59
60const char *OptTable::getOptionName(options::ID id) const {
61  return getInfo(id).Name;
62}
63
64const Option *OptTable::getOption(options::ID id) const {
65  if (id == NotOption)
66    return 0;
67
68  assert((unsigned) (id - 1) < numOptions && "Invalid ID.");
69
70  Option *&Entry = Options[id - 1];
71  if (!Entry)
72    Entry = constructOption(id);
73
74  return Entry;
75}
76
77Option *OptTable::constructOption(options::ID id) const {
78  Info &info = getInfo(id);
79  const OptionGroup *Group =
80    cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID));
81  const Option *Alias = getOption((options::ID) info.AliasID);
82
83  Option *Opt = 0;
84  switch (info.Kind) {
85  case Option::InputClass:
86    Opt = new InputOption(); break;
87  case Option::UnknownClass:
88    Opt = new UnknownOption(); break;
89  case Option::GroupClass:
90    Opt = new OptionGroup(id, info.Name, Group); break;
91  case Option::FlagClass:
92    Opt = new FlagOption(id, info.Name, Group, Alias); break;
93  case Option::JoinedClass:
94    Opt = new JoinedOption(id, info.Name, Group, Alias); break;
95  case Option::SeparateClass:
96    Opt = new SeparateOption(id, info.Name, Group, Alias); break;
97  case Option::CommaJoinedClass:
98    Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break;
99  case Option::MultiArgClass:
100    Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break;
101  case Option::JoinedOrSeparateClass:
102    Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break;
103  case Option::JoinedAndSeparateClass:
104    Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
105  }
106
107  for (const char *s = info.Flags; *s; ++s) {
108    switch (*s) {
109    default: assert(0 && "Invalid option flag.");
110    case 'l': Opt->setLinkerInput(true); break;
111    case 'i': Opt->setNoOptAsInput(true); break;
112    case 'J': Opt->setForceJoinedRender(true); break;
113    case 'S': Opt->setForceSeparateRender(true); break;
114    case 'U': Opt->setUnsupported(true); break;
115    }
116  }
117
118  return Opt;
119}
120
121Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
122                           unsigned IndexEnd) const {
123  const char *Str = Args.getArgString(Index);
124
125  // Anything that doesn't start with '-' is an input.
126  if (Str[0] != '-')
127    return new PositionalArg(getOption(InputOpt), Index++);
128
129  for (unsigned j = UnknownOpt + 1; j < getNumOptions(); ++j) {
130    const char *OptName = getOptionName((options::ID) (j + 1));
131
132    // Arguments are only accepted by options which prefix them.
133    if (memcmp(Str, OptName, strlen(OptName)) == 0)
134      if (Arg *A = getOption((options::ID) (j + 1))->accept(Args, Index))
135        return A;
136  }
137
138  return new PositionalArg(getOption(UnknownOpt), Index++);
139}
140
141