summaryrefslogtreecommitdiff
path: root/lib/Support/CommandLine.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Support/CommandLine.cpp
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
Notes
Diffstat (limited to 'lib/Support/CommandLine.cpp')
-rw-r--r--lib/Support/CommandLine.cpp50
1 files changed, 41 insertions, 9 deletions
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index a1e659a01c8e..f7290b54dcf3 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -426,12 +426,17 @@ Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,
return I != Sub.OptionsMap.end() ? I->second : nullptr;
}
- // If the argument before the = is a valid option name, we match. If not,
- // return Arg unmolested.
+ // If the argument before the = is a valid option name and the option allows
+ // non-prefix form (ie is not AlwaysPrefix), we match. If not, signal match
+ // failure by returning nullptr.
auto I = Sub.OptionsMap.find(Arg.substr(0, EqualPos));
if (I == Sub.OptionsMap.end())
return nullptr;
+ auto O = I->second;
+ if (O->getFormattingFlag() == cl::AlwaysPrefix)
+ return nullptr;
+
Value = Arg.substr(EqualPos + 1);
Arg = Arg.substr(0, EqualPos);
return I->second;
@@ -539,7 +544,9 @@ static inline bool ProvideOption(Option *Handler, StringRef ArgName,
switch (Handler->getValueExpectedFlag()) {
case ValueRequired:
if (!Value.data()) { // No value specified?
- if (i + 1 >= argc)
+ // If no other argument or the option only supports prefix form, we
+ // cannot look at the next argument.
+ if (i + 1 >= argc || Handler->getFormattingFlag() == cl::AlwaysPrefix)
return Handler->error("requires a value!");
// Steal the next argument, like for '-o filename'
assert(argv && "null check");
@@ -597,7 +604,8 @@ 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;
+ return isGrouping(O) || O->getFormattingFlag() == cl::Prefix ||
+ O->getFormattingFlag() == cl::AlwaysPrefix;
}
// getOptionPred - Check to see if there are any options that satisfy the
@@ -647,7 +655,8 @@ HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value,
// If the option is a prefixed option, then the value is simply the
// rest of the name... so fall through to later processing, by
// setting up the argument name flags and value fields.
- if (PGOpt->getFormattingFlag() == cl::Prefix) {
+ if (PGOpt->getFormattingFlag() == cl::Prefix ||
+ PGOpt->getFormattingFlag() == cl::AlwaysPrefix) {
Value = Arg.substr(Length);
Arg = Arg.substr(0, Length);
assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt);
@@ -693,6 +702,10 @@ static bool isWhitespace(char C) {
return C == ' ' || C == '\t' || C == '\r' || C == '\n';
}
+static bool isWhitespaceOrNull(char C) {
+ return isWhitespace(C) || C == '\0';
+}
+
static bool isQuote(char C) { return C == '\"' || C == '\''; }
void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver,
@@ -808,7 +821,7 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver,
// INIT state indicates that the current input index is at the start of
// the string or between tokens.
if (State == INIT) {
- if (isWhitespace(C)) {
+ if (isWhitespaceOrNull(C)) {
// Mark the end of lines in response files
if (MarkEOLs && C == '\n')
NewArgv.push_back(nullptr);
@@ -832,7 +845,7 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver,
// quotes.
if (State == UNQUOTED) {
// Whitespace means the end of the token.
- if (isWhitespace(C)) {
+ if (isWhitespaceOrNull(C)) {
NewArgv.push_back(Saver.save(StringRef(Token)).data());
Token.clear();
State = INIT;
@@ -1057,8 +1070,27 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar,
}
bool cl::ParseCommandLineOptions(int argc, const char *const *argv,
- StringRef Overview, raw_ostream *Errs) {
- return GlobalParser->ParseCommandLineOptions(argc, argv, Overview,
+ StringRef Overview, raw_ostream *Errs,
+ const char *EnvVar) {
+ SmallVector<const char *, 20> NewArgv;
+ BumpPtrAllocator A;
+ StringSaver Saver(A);
+ NewArgv.push_back(argv[0]);
+
+ // Parse options from environment variable.
+ if (EnvVar) {
+ if (llvm::Optional<std::string> EnvValue =
+ sys::Process::GetEnv(StringRef(EnvVar)))
+ TokenizeGNUCommandLine(*EnvValue, Saver, NewArgv);
+ }
+
+ // Append options from command line.
+ for (int I = 1; I < argc; ++I)
+ NewArgv.push_back(argv[I]);
+ int NewArgc = static_cast<int>(NewArgv.size());
+
+ // Parse all options.
+ return GlobalParser->ParseCommandLineOptions(NewArgc, &NewArgv[0], Overview,
Errs);
}