diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Support/CommandLine.cpp | |
parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) |
Notes
Diffstat (limited to 'lib/Support/CommandLine.cpp')
-rw-r--r-- | lib/Support/CommandLine.cpp | 50 |
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); } |