Newer
Older
//===-- CommandLine.cpp - Command line parser implementation --------------===//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===//
//
// This class implements a command line argument processor that is useful when
// creating a tool. It provides a simple, minimalistic interface that is easily
// extensible and supports nonlocal (library) command line options.
//
// Note that rather than trying to figure out what this code does, you could try
// reading the library documentation located in docs/CommandLine.html
//
//===----------------------------------------------------------------------===//
#include "llvm/Config/config.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/System/Path.h"
#include <functional>
#include <cstdlib>
#include <cerrno>
//===----------------------------------------------------------------------===//
// Template instantiations and anchors.
//
TEMPLATE_INSTANTIATION(class basic_parser<bool>);
TEMPLATE_INSTANTIATION(class basic_parser<int>);
TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
TEMPLATE_INSTANTIATION(class basic_parser<double>);
TEMPLATE_INSTANTIATION(class basic_parser<float>);
TEMPLATE_INSTANTIATION(class basic_parser<std::string>);
TEMPLATE_INSTANTIATION(class opt<unsigned>);
TEMPLATE_INSTANTIATION(class opt<int>);
TEMPLATE_INSTANTIATION(class opt<std::string>);
TEMPLATE_INSTANTIATION(class opt<bool>);
void Option::anchor() {}
void basic_parser_impl::anchor() {}
void parser<bool>::anchor() {}
void parser<int>::anchor() {}
void parser<unsigned>::anchor() {}
void parser<double>::anchor() {}
void parser<float>::anchor() {}
void parser<std::string>::anchor() {}
//===----------------------------------------------------------------------===//
// Globals for name and overview of program
static std::string ProgramName = "<premain>";
static const char *ProgramOverview = 0;
// This collects additional help to be printed.
static ManagedStatic<std::vector<const char*> > MoreHelp;
: morehelp(Help) {
}
//===----------------------------------------------------------------------===//
// Basic, shared command line option processing machinery.
static ManagedStatic<std::map<std::string, Option*> > Options;
static ManagedStatic<std::vector<Option*> > PositionalOptions;
Chris Lattner
committed
static Option *getOption(const std::string &Str) {
std::map<std::string,Option*>::iterator I = Options->find(Str);
return I != Options->end() ? I->second : 0;
Chris Lattner
committed
static void AddArgument(const char *ArgName, Option *Opt) {
if (getOption(ArgName)) {
std::cerr << ProgramName << ": CommandLine Error: Argument '"
<< ArgName << "' defined more than once!\n";
Chris Lattner
committed
// Add argument to the argument map!
Chris Lattner
committed
}
}
// RemoveArgument - It's possible that the argument is no longer in the map if
// options have already been processed and the map has been deleted!
Chris Lattner
committed
static void RemoveArgument(const char *ArgName, Option *Opt) {
Tanya Lattner
committed
#ifndef NDEBUG
// This disgusting HACK is brought to you courtesy of GCC 3.3.2, which ICE's
// If we pass ArgName directly into getOption here.
std::string Tmp = ArgName;
assert(getOption(Tmp) == Opt && "Arg not in map!");
#endif
static inline bool ProvideOption(Option *Handler, const char *ArgName,
const char *Value, int argc, char **argv,
int &i) {
// Enforce value requirements
switch (Handler->getValueExpectedFlag()) {
case ValueRequired:
if (Value == 0) { // No value specified?
if (i+1 < argc) { // Steal the next argument, like for '-o filename'
Value = argv[++i];
} else {
return Handler->error(" requires a value!");
}
}
break;
case ValueDisallowed:
if (Value)
return Handler->error(" does not allow a value! '" +
break;
break;
default:
std::cerr << ProgramName
<< ": Bad ValueMask flag! CommandLine usage error:"
<< Handler->getValueExpectedFlag() << "\n";
abort();
break;
}
// Run the handler now!
return Handler->addOccurrence(i, ArgName, Value ? Value : "");
}
static bool ProvidePositionalOption(Option *Handler, const std::string &Arg,
int i) {
int Dummy = i;
return ProvideOption(Handler, Handler->ArgStr, Arg.c_str(), 0, 0, Dummy);
}
// Option predicates...
static inline bool isGrouping(const Option *O) {
return O->getFormattingFlag() == cl::Grouping;
}
static inline bool isPrefixedOrGrouping(const Option *O) {
return isGrouping(O) || O->getFormattingFlag() == cl::Prefix;
}
// getOptionPred - Check to see if there are any options that satisfy the
// specified predicate with names that are the prefixes in Name. This is
// checked by progressively stripping characters off of the name, checking to
// see if there options that satisfy the predicate. If we find one, return it,
// otherwise return null.
Chris Lattner
committed
//
static Option *getOptionPred(std::string Name, unsigned &Length,
bool (*Pred)(const Option*)) {
Chris Lattner
committed
Option *Op = getOption(Name);
if (Op && Pred(Op)) {
Chris Lattner
committed
return Op;
Chris Lattner
committed
if (Name.size() == 1) return 0;
do {
Name.erase(Name.end()-1, Name.end()); // Chop off the last character...
Chris Lattner
committed
Op = getOption(Name);
// Loop while we haven't found an option and Name still has at least two
// characters in it (so that the next iteration will not be the empty
// string...
Chris Lattner
committed
} while ((Op == 0 || !Pred(Op)) && Name.size() > 1);
Chris Lattner
committed
if (Op && Pred(Op)) {
Chris Lattner
committed
return Op; // Found one!
Chris Lattner
committed
}
Chris Lattner
committed
return O->getNumOccurrencesFlag() == cl::Required ||
O->getNumOccurrencesFlag() == cl::OneOrMore;
}
static bool EatsUnboundedNumberOfValues(const Option *O) {
return O->getNumOccurrencesFlag() == cl::ZeroOrMore ||
O->getNumOccurrencesFlag() == cl::OneOrMore;
Chris Lattner
committed
}
/// ParseCStringVector - Break INPUT up wherever one or more
/// whitespace characters are found, and store the resulting tokens in
Loading
Loading full blame...