blob: 3308bc51a9015d3ca912a63fcfd77f65e0199e63 [file] [log] [blame]
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +00001//===--- 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
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +000012#include "clang/Driver/Arg.h"
13#include "clang/Driver/ArgList.h"
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000014#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[] = {
Daniel Dunbar30b055f2009-03-04 21:53:04 +000031 // The InputOption info
32 { Option::InputClass, "<input>", 0, 0, "", 0 },
33 // The UnknownOption info
34 { Option::UnknownClass, "<unknown>", 0, 0, "", 0 },
35
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000036#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 {
Daniel Dunbar30b055f2009-03-04 21:53:04 +000065 if (id == NotOption)
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000066 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) {
Daniel Dunbar30b055f2009-03-04 21:53:04 +000085 case Option::InputClass:
86 Opt = new InputOption(); break;
87 case Option::UnknownClass:
88 Opt = new UnknownOption(); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000089 case Option::GroupClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000090 Opt = new OptionGroup(id, info.Name, Group); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000091 case Option::FlagClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000092 Opt = new FlagOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000093 case Option::JoinedClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000094 Opt = new JoinedOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000095 case Option::SeparateClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000096 Opt = new SeparateOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000097 case Option::CommaJoinedClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000098 Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000099 case Option::MultiArgClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000100 Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000101 case Option::JoinedOrSeparateClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000102 Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000103 case Option::JoinedAndSeparateClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000104 Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000105 }
106
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000107 for (const char *s = info.Flags; *s; ++s) {
108 switch (*s) {
Daniel Dunbar0f9098e2009-03-04 21:05:23 +0000109 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;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000115 }
116 }
117
118 return Opt;
119}
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000120
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
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000129 for (unsigned j = UnknownOpt + 1; j < LastOption; ++j) {
Daniel Dunbar5cc8c632009-03-04 23:03:35 +0000130 const char *OptName = getOptionName((options::ID) j);
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000131
132 // Arguments are only accepted by options which prefix them.
133 if (memcmp(Str, OptName, strlen(OptName)) == 0)
Daniel Dunbar5cc8c632009-03-04 23:03:35 +0000134 if (Arg *A = getOption((options::ID) j)->accept(Args, Index))
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000135 return A;
136 }
137
138 return new PositionalArg(getOption(UnknownOpt), Index++);
139}
140