2011-01-01 01:31:54 +08:00
|
|
|
//===--- Option.cpp - Abstract Driver Options -----------------------------===//
|
2009-03-03 13:55:11 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/Driver/Option.h"
|
2009-03-05 07:22:02 +08:00
|
|
|
|
|
|
|
#include "clang/Driver/Arg.h"
|
|
|
|
#include "clang/Driver/ArgList.h"
|
2009-03-04 16:33:23 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2011-09-23 13:57:42 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-03-03 13:55:11 +08:00
|
|
|
#include <cassert>
|
2009-03-05 07:22:02 +08:00
|
|
|
#include <algorithm>
|
2009-03-03 13:55:11 +08:00
|
|
|
using namespace clang::driver;
|
|
|
|
|
2012-10-04 03:58:10 +08:00
|
|
|
Option::Option(const OptTable::Info *info, const OptTable *owner)
|
|
|
|
: Info(info), Owner(owner) {
|
2009-03-03 13:55:11 +08:00
|
|
|
|
|
|
|
// Multi-level aliases are not supported, and alias options cannot
|
|
|
|
// have groups. This just simplifies option tracking, it is not an
|
|
|
|
// inherent limitation.
|
2012-10-19 06:42:31 +08:00
|
|
|
assert((!getAlias() || (!getAlias()->getAlias() && !getGroup())) &&
|
2009-09-09 23:08:12 +08:00
|
|
|
"Multi-level aliases and aliases with groups are unsupported.");
|
2009-03-03 13:55:11 +08:00
|
|
|
}
|
|
|
|
|
2009-03-04 16:33:23 +08:00
|
|
|
Option::~Option() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void Option::dump() const {
|
|
|
|
llvm::errs() << "<";
|
2012-08-22 02:51:17 +08:00
|
|
|
switch (getKind()) {
|
2009-03-04 16:33:23 +08:00
|
|
|
#define P(N) case N: llvm::errs() << #N; break
|
|
|
|
P(GroupClass);
|
|
|
|
P(InputClass);
|
|
|
|
P(UnknownClass);
|
|
|
|
P(FlagClass);
|
|
|
|
P(JoinedClass);
|
|
|
|
P(SeparateClass);
|
|
|
|
P(CommaJoinedClass);
|
|
|
|
P(MultiArgClass);
|
|
|
|
P(JoinedOrSeparateClass);
|
|
|
|
P(JoinedAndSeparateClass);
|
|
|
|
#undef P
|
|
|
|
}
|
|
|
|
|
2012-08-22 02:51:17 +08:00
|
|
|
llvm::errs() << " Name:\"" << getName() << '"';
|
2009-03-04 16:33:23 +08:00
|
|
|
|
2012-10-19 06:42:31 +08:00
|
|
|
const Option *Group = getGroup();
|
|
|
|
if (Group) {
|
2009-03-04 16:33:23 +08:00
|
|
|
llvm::errs() << " Group:";
|
2012-10-19 06:42:31 +08:00
|
|
|
Group->dump();
|
2009-03-04 16:33:23 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-10-19 06:42:31 +08:00
|
|
|
const Option *Alias = getAlias();
|
|
|
|
if (Alias) {
|
2009-03-04 16:33:23 +08:00
|
|
|
llvm::errs() << " Alias:";
|
2012-10-19 06:42:31 +08:00
|
|
|
Alias->dump();
|
2009-03-04 16:33:23 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-08-22 02:51:17 +08:00
|
|
|
if (getKind() == MultiArgClass)
|
|
|
|
llvm::errs() << " NumArgs:" << getNumArgs();
|
2009-03-04 16:33:23 +08:00
|
|
|
|
|
|
|
llvm::errs() << ">\n";
|
|
|
|
}
|
|
|
|
|
2009-11-19 12:14:53 +08:00
|
|
|
bool Option::matches(OptSpecifier Opt) const {
|
2009-11-19 11:26:50 +08:00
|
|
|
// Aliases are never considered in matching, look through them.
|
2012-10-19 06:42:31 +08:00
|
|
|
const Option *Alias = getAlias();
|
|
|
|
if (Alias)
|
|
|
|
return Alias->matches(Opt);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-19 12:14:53 +08:00
|
|
|
// Check exact match.
|
2012-09-26 07:12:48 +08:00
|
|
|
if (getID() == Opt.getID())
|
2009-03-03 13:55:11 +08:00
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-10-19 06:42:31 +08:00
|
|
|
const Option *Group = getGroup();
|
|
|
|
if (Group)
|
|
|
|
return Group->matches(Opt);
|
2009-03-03 13:55:11 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-21 05:41:17 +08:00
|
|
|
Arg *Option::accept(const ArgList &Args, unsigned &Index) const {
|
2012-08-22 02:51:17 +08:00
|
|
|
switch (getKind()) {
|
2012-08-21 05:41:17 +08:00
|
|
|
case FlagClass:
|
|
|
|
if (getName().size() != strlen(Args.getArgString(Index)))
|
|
|
|
return 0;
|
2009-03-04 16:33:23 +08:00
|
|
|
|
2012-08-21 05:41:17 +08:00
|
|
|
return new Arg(getUnaliasedOption(), Index++);
|
|
|
|
case JoinedClass: {
|
|
|
|
const char *Value = Args.getArgString(Index) + getName().size();
|
|
|
|
return new Arg(getUnaliasedOption(), Index++, Value);
|
|
|
|
}
|
|
|
|
case CommaJoinedClass: {
|
|
|
|
// Always matches.
|
|
|
|
const char *Str = Args.getArgString(Index) + getName().size();
|
|
|
|
Arg *A = new Arg(getUnaliasedOption(), Index++);
|
|
|
|
|
|
|
|
// Parse out the comma separated values.
|
|
|
|
const char *Prev = Str;
|
|
|
|
for (;; ++Str) {
|
|
|
|
char c = *Str;
|
|
|
|
|
|
|
|
if (!c || c == ',') {
|
|
|
|
if (Prev != Str) {
|
|
|
|
char *Value = new char[Str - Prev + 1];
|
|
|
|
memcpy(Value, Prev, Str - Prev);
|
|
|
|
Value[Str - Prev] = '\0';
|
|
|
|
A->getValues().push_back(Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!c)
|
|
|
|
break;
|
|
|
|
|
|
|
|
Prev = Str + 1;
|
2010-06-10 06:31:08 +08:00
|
|
|
}
|
|
|
|
}
|
2012-08-21 05:41:17 +08:00
|
|
|
A->setOwnsValues(true);
|
2009-03-04 16:33:23 +08:00
|
|
|
|
2012-08-21 05:41:17 +08:00
|
|
|
return A;
|
2010-06-10 06:31:00 +08:00
|
|
|
}
|
2012-08-21 05:41:17 +08:00
|
|
|
case SeparateClass:
|
2012-09-27 18:16:10 +08:00
|
|
|
// Matches iff this is an exact match.
|
2012-08-21 05:41:17 +08:00
|
|
|
// FIXME: Avoid strlen.
|
|
|
|
if (getName().size() != strlen(Args.getArgString(Index)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Index += 2;
|
|
|
|
if (Index > Args.getNumInputArgStrings())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return new Arg(getUnaliasedOption(),
|
|
|
|
Index - 2, Args.getArgString(Index - 1));
|
|
|
|
case MultiArgClass: {
|
2012-09-27 18:16:10 +08:00
|
|
|
// Matches iff this is an exact match.
|
2012-08-21 05:41:17 +08:00
|
|
|
// FIXME: Avoid strlen.
|
|
|
|
if (getName().size() != strlen(Args.getArgString(Index)))
|
|
|
|
return 0;
|
|
|
|
|
2012-08-22 02:51:17 +08:00
|
|
|
Index += 1 + getNumArgs();
|
2012-08-21 05:41:17 +08:00
|
|
|
if (Index > Args.getNumInputArgStrings())
|
|
|
|
return 0;
|
|
|
|
|
2012-08-22 02:51:17 +08:00
|
|
|
Arg *A = new Arg(getUnaliasedOption(), Index - 1 - getNumArgs(),
|
|
|
|
Args.getArgString(Index - getNumArgs()));
|
|
|
|
for (unsigned i = 1; i != getNumArgs(); ++i)
|
|
|
|
A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
|
2012-08-21 05:41:17 +08:00
|
|
|
return A;
|
|
|
|
}
|
|
|
|
case JoinedOrSeparateClass: {
|
|
|
|
// If this is not an exact match, it is a joined arg.
|
|
|
|
// FIXME: Avoid strlen.
|
|
|
|
if (getName().size() != strlen(Args.getArgString(Index))) {
|
|
|
|
const char *Value = Args.getArgString(Index) + getName().size();
|
2012-10-19 06:42:31 +08:00
|
|
|
return new Arg(this, Index++, Value);
|
2012-08-21 05:41:17 +08:00
|
|
|
}
|
2009-03-05 07:22:02 +08:00
|
|
|
|
2012-08-21 05:41:17 +08:00
|
|
|
// Otherwise it must be separate.
|
|
|
|
Index += 2;
|
|
|
|
if (Index > Args.getNumInputArgStrings())
|
|
|
|
return 0;
|
2009-03-23 07:26:43 +08:00
|
|
|
|
2012-08-21 05:41:17 +08:00
|
|
|
return new Arg(getUnaliasedOption(),
|
|
|
|
Index - 2, Args.getArgString(Index - 1));
|
|
|
|
}
|
|
|
|
case JoinedAndSeparateClass:
|
|
|
|
// Always matches.
|
|
|
|
Index += 2;
|
|
|
|
if (Index > Args.getNumInputArgStrings())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return new Arg(getUnaliasedOption(), Index - 2,
|
|
|
|
Args.getArgString(Index-2)+getName().size(),
|
|
|
|
Args.getArgString(Index-1));
|
2012-08-21 06:22:51 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("Invalid option kind!");
|
2012-08-21 05:41:17 +08:00
|
|
|
}
|
2009-03-04 16:33:23 +08:00
|
|
|
}
|