Add support for option aliases.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51749 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2008-05-30 06:22:52 +00:00
parent 2d0dc9ab44
commit 6be4ffc7c3
2 changed files with 70 additions and 18 deletions

View File

@ -30,6 +30,7 @@ def sink;
// Possible option types
def alias_option;
def switch_option;
def parameter_option;
def parameter_list_option;
@ -45,7 +46,7 @@ def unpack_values;
def help;
def required;
// Marker for an empty DAG.
// Empty DAG marker.
def empty;
// The 'case' construct.

View File

@ -93,7 +93,9 @@ bool isDagEmpty (const DagInit* d) {
// A command-line option can have one of the following types:
//
// Switch - a simple switch w/o arguments, e.g. -O2
// Alias - an alias for another option.
//
// Switch - a simple switch without arguments, e.g. -O2
//
// Parameter - an option that takes one(and only one) argument, e.g. -o file,
// --output=file
@ -105,10 +107,11 @@ bool isDagEmpty (const DagInit* d) {
// e.g. -Wa,-foo,-bar, -DNAME=VALUE
//
// PrefixList - same as Prefix, but more than one option occurence is
// allowed
// allowed.
namespace OptionType {
enum OptionType { Switch, Parameter, ParameterList, Prefix, PrefixList};
enum OptionType { Alias, Switch,
Parameter, ParameterList, Prefix, PrefixList};
}
bool IsListOptionType (OptionType::OptionType t) {
@ -133,6 +136,8 @@ struct OptionDescription {
const char* GenTypeDeclaration() const {
switch (Type) {
case OptionType::Alias:
return "cl::alias";
case OptionType::PrefixList:
case OptionType::ParameterList:
return "cl::list<std::string>";
@ -164,18 +169,20 @@ struct OptionDescription {
std::string GenVariableName() const {
const std::string& EscapedName = EscapeVariableName(Name);
switch (Type) {
case OptionType::Alias:
return "AutoGeneratedAlias" + EscapedName;
case OptionType::Switch:
return "AutoGeneratedSwitch" + EscapedName;
case OptionType::Prefix:
return "AutoGeneratedPrefix" + EscapedName;
case OptionType::PrefixList:
return "AutoGeneratedPrefixList" + EscapedName;
case OptionType::Parameter:
return "AutoGeneratedParameter" + EscapedName;
case OptionType::ParameterList:
default:
return "AutoGeneratedParameterList" + EscapedName;
}
return "AutoGeneratedSwitch" + EscapedName;
case OptionType::Prefix:
return "AutoGeneratedPrefix" + EscapedName;
case OptionType::PrefixList:
return "AutoGeneratedPrefixList" + EscapedName;
case OptionType::Parameter:
return "AutoGeneratedParameter" + EscapedName;
case OptionType::ParameterList:
default:
return "AutoGeneratedParameterList" + EscapedName;
}
}
};
@ -195,8 +202,9 @@ struct GlobalOptionDescription : public OptionDescription {
GlobalOptionDescription() : OptionDescription(), Flags(0)
{}
GlobalOptionDescription (OptionType::OptionType t, const std::string& n)
: OptionDescription(t, n), Help(DefaultHelpString), Flags(0)
GlobalOptionDescription (OptionType::OptionType t, const std::string& n,
const std::string& h = DefaultHelpString)
: OptionDescription(t, n), Help(h), Flags(0)
{}
bool isRequired() const {
@ -399,6 +407,7 @@ public:
&CollectProperties::onPrefixList;
propertyHandlers_["sink"] = &CollectProperties::onSink;
propertyHandlers_["switch_option"] = &CollectProperties::onSwitch;
propertyHandlers_["alias_option"] = &CollectProperties::onAlias;
// Init option property handlers
optionPropertyHandlers_["append_cmd"] = &CollectProperties::onAppendCmd;
@ -492,6 +501,15 @@ private:
toolProps_.setSink();
}
void onAlias (const DagInit* d) {
checkNumberOfArguments(d, 2);
// We just need a GlobalOptionDescription for the aliases.
insertDescription
(GlobalOptionDescription(OptionType::Alias,
InitPtrToString(d->getArg(0)),
InitPtrToString(d->getArg(1))));
}
void onSwitch (const DagInit* d) {
addOption(d, OptionType::Switch);
}
@ -842,6 +860,9 @@ void EmitForwardOptionPropertyHandlingCode (const ToolOptionDescription& D,
<< Indent4 << "vec.push_back(*B);\n"
<< Indent3 << "}\n";
break;
case OptionType::Alias:
default:
throw std::string("Aliases are not allowed in tool option descriptions!");
}
}
@ -1191,11 +1212,18 @@ void EmitToolClassDefinition (const ToolProperties& P,
void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
std::ostream& O)
{
std::vector<GlobalOptionDescription> Aliases;
// Emit static cl::Option variables
for (GlobalOptionDescriptions::const_iterator B = descs.begin(),
E = descs.end(); B!=E; ++B) {
const GlobalOptionDescription& val = B->second;
if (val.Type == OptionType::Alias) {
Aliases.push_back(val);
continue;
}
O << val.GenTypeDeclaration() << ' '
<< val.GenVariableName()
<< "(\"" << val.Name << '\"';
@ -1214,9 +1242,32 @@ void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
}
}
O << ", cl::desc(\"" << val.Help << "\"));\n";
if (!val.Help.empty())
O << ", cl::desc(\"" << val.Help << "\")";
O << ");\n";
}
// Emit the aliases (they should go after all the 'proper' options).
for (std::vector<GlobalOptionDescription>::const_iterator
B = Aliases.begin(), E = Aliases.end(); B != E; ++B) {
const GlobalOptionDescription& val = *B;
O << val.GenTypeDeclaration() << ' '
<< val.GenVariableName()
<< "(\"" << val.Name << '\"';
GlobalOptionDescriptions::container_type
::const_iterator F = descs.Descriptions.find(val.Help);
if (F != descs.Descriptions.end())
O << ", cl::aliasopt(" << F->second.GenVariableName() << ")";
else
throw val.Name + ": alias to an unknown option!";
O << ", cl::desc(\"" << "An alias for -" + val.Help << "\"));\n";
}
// Emit the sink option.
if (descs.HasSink)
O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";