summaryrefslogtreecommitdiffstats
path: root/lib/Driver/OptTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/OptTable.cpp')
-rw-r--r--lib/Driver/OptTable.cpp220
1 files changed, 104 insertions, 116 deletions
diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp
index affd1c5..f68a1d8 100644
--- a/lib/Driver/OptTable.cpp
+++ b/lib/Driver/OptTable.cpp
@@ -1,4 +1,4 @@
-//===--- Options.cpp - Option info table --------------------------------*-===//
+//===--- OptTable.cpp - Option Table Implementation ---------------------*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,8 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Driver/Options.h"
-
+#include "clang/Driver/OptTable.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Option.h"
@@ -18,18 +17,6 @@
using namespace clang::driver;
using namespace clang::driver::options;
-struct Info {
- const char *Name;
- const char *Flags;
- const char *HelpText;
- const char *MetaVar;
-
- Option::OptionClass Kind;
- unsigned GroupID;
- unsigned AliasID;
- unsigned Param;
-};
-
// Ordering on Info. The ordering is *almost* lexicographic, with two
// exceptions. First, '\0' comes at the end of the alphabet instead of
// the beginning (thus options preceed any other options which prefix
@@ -56,7 +43,9 @@ static int StrCmpOptionName(const char *A, const char *B) {
return (a < b) ? -1 : 1;
}
-static inline bool operator<(const Info &A, const Info &B) {
+namespace clang {
+namespace driver {
+static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
if (&A == &B)
return false;
@@ -70,57 +59,62 @@ static inline bool operator<(const Info &A, const Info &B) {
return B.Kind == Option::JoinedClass;
}
+// Support lower_bound between info and an option name.
+static inline bool operator<(const OptTable::Info &I, const char *Name) {
+ return StrCmpOptionName(I.Name, Name) == -1;
+}
+static inline bool operator<(const char *Name, const OptTable::Info &I) {
+ return StrCmpOptionName(Name, I.Name) == -1;
+}
+}
+}
+
//
-static Info OptionInfos[] = {
- // The InputOption info
- { "<input>", "d", 0, 0, Option::InputClass, OPT_INVALID, OPT_INVALID, 0 },
- // The UnknownOption info
- { "<unknown>", "", 0, 0, Option::UnknownClass, OPT_INVALID, OPT_INVALID, 0 },
-
-#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) \
- { NAME, FLAGS, HELPTEXT, METAVAR, \
- Option::KIND##Class, OPT_##GROUP, OPT_##ALIAS, PARAM },
-#include "clang/Driver/Options.def"
-};
-static const unsigned numOptions = sizeof(OptionInfos) / sizeof(OptionInfos[0]);
-
-static Info &getInfo(unsigned id) {
- assert(id > 0 && id - 1 < numOptions && "Invalid Option ID.");
- return OptionInfos[id - 1];
-}
+OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
-OptTable::OptTable() : Options(new Option*[numOptions]) {
+//
+
+OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
+ : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos),
+ Options(new Option*[NumOptionInfos]),
+ TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0)
+{
// Explicitly zero initialize the error to work around a bug in array
// value-initialization on MinGW with gcc 4.3.5.
- memset(Options, 0, sizeof(*Options) * numOptions);
+ memset(Options, 0, sizeof(*Options) * NumOptionInfos);
// Find start of normal options.
- FirstSearchableOption = 0;
- for (unsigned i = OPT_UNKNOWN + 1; i < LastOption; ++i) {
- if (getInfo(i).Kind != Option::GroupClass) {
- FirstSearchableOption = i;
+ for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+ unsigned Kind = getInfo(i + 1).Kind;
+ if (Kind == Option::InputClass) {
+ assert(!TheInputOption && "Cannot have multiple input options!");
+ TheInputOption = getOption(i + 1);
+ } else if (Kind == Option::UnknownClass) {
+ assert(!TheUnknownOption && "Cannot have multiple input options!");
+ TheUnknownOption = getOption(i + 1);
+ } else if (Kind != Option::GroupClass) {
+ FirstSearchableIndex = i;
break;
}
}
- assert(FirstSearchableOption != 0 && "No searchable options?");
+ assert(FirstSearchableIndex != 0 && "No searchable options?");
#ifndef NDEBUG
// Check that everything after the first searchable option is a
// regular option class.
- for (unsigned i = FirstSearchableOption; i < LastOption; ++i) {
- Option::OptionClass Kind = getInfo(i).Kind;
+ for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
+ Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
Kind != Option::GroupClass) &&
"Special options should be defined first!");
}
// Check that options are in order.
- for (unsigned i = FirstSearchableOption + 1; i < LastOption; ++i) {
- if (!(getInfo(i - 1) < getInfo(i))) {
- getOption((options::ID) (i - 1))->dump();
- getOption((options::ID) i)->dump();
+ for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
+ if (!(getInfo(i) < getInfo(i + 1))) {
+ getOption(i)->dump();
+ getOption(i + 1)->dump();
assert(0 && "Options are not in order!");
}
}
@@ -128,56 +122,23 @@ OptTable::OptTable() : Options(new Option*[numOptions]) {
}
OptTable::~OptTable() {
- for (unsigned i = 0; i < numOptions; ++i)
+ for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
delete Options[i];
delete[] Options;
}
-unsigned OptTable::getNumOptions() const {
- return numOptions;
-}
-
-const char *OptTable::getOptionName(options::ID id) const {
- return getInfo(id).Name;
-}
-
-unsigned OptTable::getOptionKind(options::ID id) const {
- return getInfo(id).Kind;
-}
-
-const char *OptTable::getOptionHelpText(options::ID id) const {
- return getInfo(id).HelpText;
-}
-
-const char *OptTable::getOptionMetaVar(options::ID id) const {
- return getInfo(id).MetaVar;
-}
-
-const Option *OptTable::getOption(options::ID id) const {
- if (id == OPT_INVALID)
- return 0;
-
- assert((unsigned) (id - 1) < numOptions && "Invalid ID.");
-
- Option *&Entry = Options[id - 1];
- if (!Entry)
- Entry = constructOption(id);
-
- return Entry;
-}
-
-Option *OptTable::constructOption(options::ID id) const {
- Info &info = getInfo(id);
+Option *OptTable::CreateOption(unsigned id) const {
+ const Info &info = getInfo(id);
const OptionGroup *Group =
- cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID));
- const Option *Alias = getOption((options::ID) info.AliasID);
+ cast_or_null<OptionGroup>(getOption(info.GroupID));
+ const Option *Alias = getOption(info.AliasID);
Option *Opt = 0;
switch (info.Kind) {
case Option::InputClass:
- Opt = new InputOption(); break;
+ Opt = new InputOption(id); break;
case Option::UnknownClass:
- Opt = new UnknownOption(); break;
+ Opt = new UnknownOption(id); break;
case Option::GroupClass:
Opt = new OptionGroup(id, info.Name, Group); break;
case Option::FlagClass:
@@ -196,44 +157,38 @@ Option *OptTable::constructOption(options::ID id) const {
Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
}
- for (const char *s = info.Flags; *s; ++s) {
- switch (*s) {
- default: assert(0 && "Invalid option flag.");
- case 'J':
- assert(info.Kind == Option::SeparateClass && "Invalid option.");
- Opt->setForceJoinedRender(true); break;
- case 'S':
- assert(info.Kind == Option::JoinedClass && "Invalid option.");
- Opt->setForceSeparateRender(true); break;
- case 'd': Opt->setDriverOption(true); break;
- case 'i': Opt->setNoOptAsInput(true); break;
- case 'l': Opt->setLinkerInput(true); break;
- case 'q': Opt->setNoArgumentUnused(true); break;
- case 'u': Opt->setUnsupported(true); break;
- }
+ if (info.Flags & DriverOption)
+ Opt->setDriverOption(true);
+ if (info.Flags & LinkerInput)
+ Opt->setLinkerInput(true);
+ if (info.Flags & NoArgumentUnused)
+ Opt->setNoArgumentUnused(true);
+ if (info.Flags & RenderAsInput)
+ Opt->setNoOptAsInput(true);
+ if (info.Flags & RenderJoined) {
+ assert(info.Kind == Option::SeparateClass && "Invalid option.");
+ Opt->setForceJoinedRender(true);
}
+ if (info.Flags & RenderSeparate) {
+ assert(info.Kind == Option::JoinedClass && "Invalid option.");
+ Opt->setForceSeparateRender(true);
+ }
+ if (info.Flags & Unsupported)
+ Opt->setUnsupported(true);
return Opt;
}
-// Support lower_bound between info and an option name.
-static inline bool operator<(struct Info &I, const char *Name) {
- return StrCmpOptionName(I.Name, Name) == -1;
-}
-static inline bool operator<(const char *Name, struct Info &I) {
- return StrCmpOptionName(Name, I.Name) == -1;
-}
-
Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const {
unsigned Prev = Index;
const char *Str = Args.getArgString(Index);
// Anything that doesn't start with '-' is an input, as is '-' itself.
if (Str[0] != '-' || Str[1] == '\0')
- return new PositionalArg(getOption(OPT_INPUT), Index++);
+ return new PositionalArg(TheInputOption, Index++);
- struct Info *Start = OptionInfos + FirstSearchableOption - 1;
- struct Info *End = OptionInfos + LastOption - 1;
+ const Info *Start = OptionInfos + FirstSearchableIndex;
+ const Info *End = OptionInfos + getNumOptions();
// Search for the first next option which could be a prefix.
Start = std::lower_bound(Start, End, Str);
@@ -255,8 +210,7 @@ Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const {
break;
// See if this option matches.
- options::ID id = (options::ID) (Start - OptionInfos + 1);
- if (Arg *A = getOption(id)->accept(Args, Index))
+ if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index))
return A;
// Otherwise, see if this argument was missing values.
@@ -264,6 +218,40 @@ Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const {
return 0;
}
- return new PositionalArg(getOption(OPT_UNKNOWN), Index++);
+ return new PositionalArg(TheUnknownOption, Index++);
}
+InputArgList *OptTable::ParseArgs(const char **ArgBegin, const char **ArgEnd,
+ unsigned &MissingArgIndex,
+ unsigned &MissingArgCount) const {
+ InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
+
+ // FIXME: Handle '@' args (or at least error on them).
+
+ MissingArgIndex = MissingArgCount = 0;
+ unsigned Index = 0, End = ArgEnd - ArgBegin;
+ while (Index < End) {
+ // Ignore empty arguments (other things may still take them as arguments).
+ if (Args->getArgString(Index)[0] == '\0') {
+ ++Index;
+ continue;
+ }
+
+ unsigned Prev = Index;
+ Arg *A = ParseOneArg(*Args, Index);
+ assert(Index > Prev && "Parser failed to consume argument.");
+
+ // Check for missing argument error.
+ if (!A) {
+ assert(Index >= End && "Unexpected parser error.");
+ assert(Index - Prev - 1 && "No missing arguments!");
+ MissingArgIndex = Prev;
+ MissingArgCount = Index - Prev - 1;
+ break;
+ }
+
+ Args->append(A);
+ }
+
+ return Args;
+}
OpenPOWER on IntegriCloud