blob: 00a949f086b26fe9f2241fb5a5fbd698e89cfe8d [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 {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000022 const char *Name;
Daniel Dunbare1495ec2009-03-12 01:46:53 +000023 const char *Flags;
24
25 Option::OptionClass Kind;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000026 unsigned GroupID;
27 unsigned AliasID;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000028 unsigned Param;
29};
30
31static Info OptionInfos[] = {
Daniel Dunbar30b055f2009-03-04 21:53:04 +000032 // The InputOption info
Daniel Dunbarb349fcc2009-03-12 03:42:54 +000033 { "<input>", "", Option::InputClass, OPT_INVALID, OPT_INVALID, 0 },
Daniel Dunbar30b055f2009-03-04 21:53:04 +000034 // The UnknownOption info
Daniel Dunbarb349fcc2009-03-12 03:42:54 +000035 { "<unknown>", "", Option::UnknownClass, OPT_INVALID, OPT_INVALID, 0 },
Daniel Dunbar30b055f2009-03-04 21:53:04 +000036
Daniel Dunbarb349fcc2009-03-12 03:42:54 +000037#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM) \
38 { NAME, FLAGS, Option::KIND##Class, OPT_##GROUP, OPT_##ALIAS, PARAM },
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000039#include "clang/Driver/Options.def"
40};
41static const unsigned numOptions = sizeof(OptionInfos) / sizeof(OptionInfos[0]);
42
43static Info &getInfo(unsigned id) {
44 assert(id > 0 && id - 1 < numOptions && "Invalid Option ID.");
45 return OptionInfos[id - 1];
46}
47
48OptTable::OptTable() : Options(new Option*[numOptions]) {
Daniel Dunbar644eade2009-03-12 05:46:32 +000049 memset(Options, 0, sizeof(*Options) * numOptions);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000050}
51
52OptTable::~OptTable() {
53 for (unsigned i=0; i<numOptions; ++i)
54 delete Options[i];
55 delete[] Options;
56}
57
58unsigned OptTable::getNumOptions() const {
59 return numOptions;
60}
61
62const char *OptTable::getOptionName(options::ID id) const {
63 return getInfo(id).Name;
64}
65
66const Option *OptTable::getOption(options::ID id) const {
Daniel Dunbarb349fcc2009-03-12 03:42:54 +000067 if (id == OPT_INVALID)
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000068 return 0;
69
70 assert((unsigned) (id - 1) < numOptions && "Invalid ID.");
71
72 Option *&Entry = Options[id - 1];
73 if (!Entry)
74 Entry = constructOption(id);
75
76 return Entry;
77}
78
79Option *OptTable::constructOption(options::ID id) const {
80 Info &info = getInfo(id);
81 const OptionGroup *Group =
82 cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID));
83 const Option *Alias = getOption((options::ID) info.AliasID);
84
85 Option *Opt = 0;
86 switch (info.Kind) {
Daniel Dunbar30b055f2009-03-04 21:53:04 +000087 case Option::InputClass:
88 Opt = new InputOption(); break;
89 case Option::UnknownClass:
90 Opt = new UnknownOption(); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000091 case Option::GroupClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000092 Opt = new OptionGroup(id, info.Name, Group); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000093 case Option::FlagClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000094 Opt = new FlagOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000095 case Option::JoinedClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000096 Opt = new JoinedOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000097 case Option::SeparateClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000098 Opt = new SeparateOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000099 case Option::CommaJoinedClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000100 Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000101 case Option::MultiArgClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000102 Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000103 case Option::JoinedOrSeparateClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000104 Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000105 case Option::JoinedAndSeparateClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000106 Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000107 }
108
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000109 for (const char *s = info.Flags; *s; ++s) {
110 switch (*s) {
Daniel Dunbar0f9098e2009-03-04 21:05:23 +0000111 default: assert(0 && "Invalid option flag.");
Daniel Dunbar0f9098e2009-03-04 21:05:23 +0000112 case 'J': Opt->setForceJoinedRender(true); break;
113 case 'S': Opt->setForceSeparateRender(true); break;
Daniel Dunbar644eade2009-03-12 05:46:32 +0000114 case 'i': Opt->setNoOptAsInput(true); break;
115 case 'l': Opt->setLinkerInput(true); break;
116 case 'u': Opt->setUnsupported(true); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000117 }
118 }
119
120 return Opt;
121}
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000122
123Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
124 unsigned IndexEnd) const {
125 const char *Str = Args.getArgString(Index);
126
127 // Anything that doesn't start with '-' is an input.
128 if (Str[0] != '-')
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000129 return new PositionalArg(getOption(OPT_INPUT), Index++);
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000130
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000131 for (unsigned j = OPT_UNKNOWN + 1; j < LastOption; ++j) {
Daniel Dunbar5cc8c632009-03-04 23:03:35 +0000132 const char *OptName = getOptionName((options::ID) j);
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000133
134 // Arguments are only accepted by options which prefix them.
135 if (memcmp(Str, OptName, strlen(OptName)) == 0)
Daniel Dunbar5cc8c632009-03-04 23:03:35 +0000136 if (Arg *A = getOption((options::ID) j)->accept(Args, Index))
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000137 return A;
138 }
139
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000140 return new PositionalArg(getOption(OPT_UNKNOWN), Index++);
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000141}
142