blob: 5caaace3ad02de895f6fa6ff9af5bd19e91ae649 [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]) {
49}
50
51OptTable::~OptTable() {
52 for (unsigned i=0; i<numOptions; ++i)
53 delete Options[i];
54 delete[] Options;
55}
56
57unsigned OptTable::getNumOptions() const {
58 return numOptions;
59}
60
61const char *OptTable::getOptionName(options::ID id) const {
62 return getInfo(id).Name;
63}
64
65const Option *OptTable::getOption(options::ID id) const {
Daniel Dunbarb349fcc2009-03-12 03:42:54 +000066 if (id == OPT_INVALID)
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000067 return 0;
68
69 assert((unsigned) (id - 1) < numOptions && "Invalid ID.");
70
71 Option *&Entry = Options[id - 1];
72 if (!Entry)
73 Entry = constructOption(id);
74
75 return Entry;
76}
77
78Option *OptTable::constructOption(options::ID id) const {
79 Info &info = getInfo(id);
80 const OptionGroup *Group =
81 cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID));
82 const Option *Alias = getOption((options::ID) info.AliasID);
83
84 Option *Opt = 0;
85 switch (info.Kind) {
Daniel Dunbar30b055f2009-03-04 21:53:04 +000086 case Option::InputClass:
87 Opt = new InputOption(); break;
88 case Option::UnknownClass:
89 Opt = new UnknownOption(); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000090 case Option::GroupClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000091 Opt = new OptionGroup(id, info.Name, Group); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000092 case Option::FlagClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000093 Opt = new FlagOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000094 case Option::JoinedClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000095 Opt = new JoinedOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000096 case Option::SeparateClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000097 Opt = new SeparateOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000098 case Option::CommaJoinedClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +000099 Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000100 case Option::MultiArgClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000101 Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000102 case Option::JoinedOrSeparateClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000103 Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000104 case Option::JoinedAndSeparateClass:
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000105 Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000106 }
107
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000108 for (const char *s = info.Flags; *s; ++s) {
109 switch (*s) {
Daniel Dunbar0f9098e2009-03-04 21:05:23 +0000110 default: assert(0 && "Invalid option flag.");
111 case 'l': Opt->setLinkerInput(true); break;
112 case 'i': Opt->setNoOptAsInput(true); break;
113 case 'J': Opt->setForceJoinedRender(true); break;
114 case 'S': Opt->setForceSeparateRender(true); break;
115 case 'U': Opt->setUnsupported(true); break;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000116 }
117 }
118
119 return Opt;
120}
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000121
122Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
123 unsigned IndexEnd) const {
124 const char *Str = Args.getArgString(Index);
125
126 // Anything that doesn't start with '-' is an input.
127 if (Str[0] != '-')
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000128 return new PositionalArg(getOption(OPT_INPUT), Index++);
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000129
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000130 for (unsigned j = OPT_UNKNOWN + 1; j < LastOption; ++j) {
Daniel Dunbar5cc8c632009-03-04 23:03:35 +0000131 const char *OptName = getOptionName((options::ID) j);
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000132
133 // Arguments are only accepted by options which prefix them.
134 if (memcmp(Str, OptName, strlen(OptName)) == 0)
Daniel Dunbar5cc8c632009-03-04 23:03:35 +0000135 if (Arg *A = getOption((options::ID) j)->accept(Args, Index))
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000136 return A;
137 }
138
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000139 return new PositionalArg(getOption(OPT_UNKNOWN), Index++);
Daniel Dunbar70a0dbb2009-03-04 22:41:37 +0000140}
141