//
// 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 file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include <cstdlib>
#include <cerrno>
#include <cstring>
+#include <climits>
using namespace llvm;
using namespace cl;
// Template instantiations and anchors.
//
TEMPLATE_INSTANTIATION(class basic_parser<bool>);
+TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
TEMPLATE_INSTANTIATION(class basic_parser<int>);
TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
TEMPLATE_INSTANTIATION(class basic_parser<double>);
void Option::anchor() {}
void basic_parser_impl::anchor() {}
void parser<bool>::anchor() {}
+void parser<boolOrDefault>::anchor() {}
void parser<int>::anchor() {}
void parser<unsigned>::anchor() {}
void parser<double>::anchor() {}
MoreHelp->push_back(Help);
}
+static bool OptionListChanged = false;
+
+// MarkOptionsChanged - Internal helper function.
+void cl::MarkOptionsChanged() {
+ OptionListChanged = true;
+}
+
/// RegisteredOptionList - This is the list of the command line options that
/// have statically constructed themselves.
static Option *RegisteredOptionList = 0;
NextRegistered = RegisteredOptionList;
RegisteredOptionList = this;
+ MarkOptionsChanged();
}
+
//===----------------------------------------------------------------------===//
// Basic, shared command line option processing machinery.
//
/// GetOptionInfo - Scan the list of registered options, turning them into data
/// structures that are easier to handle.
static void GetOptionInfo(std::vector<Option*> &PositionalOpts,
+ std::vector<Option*> &SinkOpts,
std::map<std::string, Option*> &OptionsMap) {
std::vector<const char*> OptionNames;
+ Option *CAOpt = 0; // The ConsumeAfter option if it exists.
for (Option *O = RegisteredOptionList; O; O = O->getNextRegisteredOption()) {
// If this option wants to handle multiple option names, get the full set.
// This handles enum options like "-O1 -O2" etc.
// Remember information about positional options.
if (O->getFormattingFlag() == cl::Positional)
PositionalOpts.push_back(O);
+ else if (O->getMiscFlags() & cl::Sink) // Remember sink options
+ SinkOpts.push_back(O);
else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) {
- if (!PositionalOpts.empty() &&
- PositionalOpts.front()->getNumOccurrencesFlag() == cl::ConsumeAfter)
+ if (CAOpt)
O->error("Cannot specify more than one option with cl::ConsumeAfter!");
- PositionalOpts.insert(PositionalOpts.begin(), O);
+ CAOpt = O;
}
}
+
+ if (CAOpt)
+ PositionalOpts.push_back(CAOpt);
+
+ // Make sure that they are in order of registration not backwards.
+ std::reverse(PositionalOpts.begin(), PositionalOpts.end());
}
static void ParseCStringVector(std::vector<char *> &output,
const char *input) {
// Characters which will be treated as token separators:
- static const char *delims = " \v\f\t\r\n";
+ static const char *const delims = " \v\f\t\r\n";
std::string work (input);
// Skip past any delims at head of input string.
free (*i);
}
-void cl::ParseCommandLineOptions(int &argc, char **argv,
+void cl::ParseCommandLineOptions(int argc, char **argv,
const char *Overview) {
// Process all registered options.
std::vector<Option*> PositionalOpts;
+ std::vector<Option*> SinkOpts;
std::map<std::string, Option*> Opts;
- GetOptionInfo(PositionalOpts, Opts);
+ GetOptionInfo(PositionalOpts, SinkOpts, Opts);
assert((!Opts.empty() || !PositionalOpts.empty()) &&
"No options specified!");
const char *Value = 0;
const char *ArgName = "";
+ // If the option list changed, this means that some command line
+ // option has just been registered or deregistered. This can occur in
+ // response to things like -load, etc. If this happens, rescan the options.
+ if (OptionListChanged) {
+ PositionalOpts.clear();
+ SinkOpts.clear();
+ Opts.clear();
+ GetOptionInfo(PositionalOpts, SinkOpts, Opts);
+ OptionListChanged = false;
+ }
+
// Check to see if this is a positional argument. This argument is
// considered to be positional if it doesn't start with '-', if it is "-"
// itself, or if we have seen "--" already.
}
if (Handler == 0) {
- cerr << ProgramName << ": Unknown command line argument '"
- << argv[i] << "'. Try: '" << argv[0] << " --help'\n";
- ErrorParsing = true;
+ if (SinkOpts.empty()) {
+ cerr << ProgramName << ": Unknown command line argument '"
+ << argv[i] << "'. Try: '" << argv[0] << " --help'\n";
+ ErrorParsing = true;
+ } else {
+ for (std::vector<Option*>::iterator I = SinkOpts.begin(),
+ E = SinkOpts.end(); I != E ; ++I)
+ (*I)->addOccurrence(i, "", argv[i]);
+ }
continue;
}
return false;
}
+// parser<boolOrDefault> implementation
+//
+bool parser<boolOrDefault>::parse(Option &O, const char *ArgName,
+ const std::string &Arg, boolOrDefault &Value) {
+ if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
+ Arg == "1") {
+ Value = BOU_TRUE;
+ } else if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
+ Value = BOU_FALSE;
+ } else {
+ return O.error(": '" + Arg +
+ "' is invalid value for boolean argument! Try 0 or 1");
+ }
+ return false;
+}
+
// parser<int> implementation
//
bool parser<int>::parse(Option &O, const char *ArgName,
}
public:
- HelpPrinter(bool showHidden) : ShowHidden(showHidden) {
+ explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {
EmptyArg = 0;
}
// Get all the options.
std::vector<Option*> PositionalOpts;
+ std::vector<Option*> SinkOpts;
std::map<std::string, Option*> OptMap;
- GetOptionInfo(PositionalOpts, OptMap);
+ GetOptionInfo(PositionalOpts, SinkOpts, OptMap);
// Copy Options into a vector so we can sort them as we like...
std::vector<std::pair<std::string, Option*> > Opts;
}
if (ProgramOverview)
- cout << "OVERVIEW:" << ProgramOverview << "\n";
+ cout << "OVERVIEW: " << ProgramOverview << "\n";
cout << "USAGE: " << ProgramName << " [options]";