diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
commit | eb11fae6d08f479c0799db45860a98af528fa6e7 (patch) | |
tree | 44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Support/CommandLine.cpp | |
parent | b8a2042aa938069e862750553db0e4d82d25822c (diff) |
Notes
Diffstat (limited to 'lib/Support/CommandLine.cpp')
-rw-r--r-- | lib/Support/CommandLine.cpp | 96 |
1 files changed, 82 insertions, 14 deletions
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 4caf4a4fdce07..a1e659a01c8e5 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -25,6 +25,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" #include "llvm/Support/ConvertUTF.h" @@ -873,6 +874,45 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, NewArgv.push_back(nullptr); } +void cl::tokenizeConfigFile(StringRef Source, StringSaver &Saver, + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs) { + for (const char *Cur = Source.begin(); Cur != Source.end();) { + SmallString<128> Line; + // Check for comment line. + if (isWhitespace(*Cur)) { + while (Cur != Source.end() && isWhitespace(*Cur)) + ++Cur; + continue; + } + if (*Cur == '#') { + while (Cur != Source.end() && *Cur != '\n') + ++Cur; + continue; + } + // Find end of the current line. + const char *Start = Cur; + for (const char *End = Source.end(); Cur != End; ++Cur) { + if (*Cur == '\\') { + if (Cur + 1 != End) { + ++Cur; + if (*Cur == '\n' || + (*Cur == '\r' && (Cur + 1 != End) && Cur[1] == '\n')) { + Line.append(Start, Cur - 1); + if (*Cur == '\r') + ++Cur; + Start = Cur + 1; + } + } + } else if (*Cur == '\n') + break; + } + // Tokenize line. + Line.append(Start, Cur); + cl::TokenizeGNUCommandLine(Line, Saver, NewArgv, MarkEOLs); + } +} + // It is called byte order marker but the UTF-8 BOM is actually not affected // by the host system's endianness. static bool hasUTF8ByteOrderMark(ArrayRef<char> S) { @@ -934,7 +974,7 @@ static bool ExpandResponseFile(StringRef FName, StringSaver &Saver, return true; } -/// \brief Expand response files on a command line recursively using the given +/// Expand response files on a command line recursively using the given /// StringSaver and tokenization strategy. bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl<const char *> &Argv, @@ -977,6 +1017,15 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, return AllExpanded; } +bool cl::readConfigFile(StringRef CfgFile, StringSaver &Saver, + SmallVectorImpl<const char *> &Argv) { + if (!ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv, + /*MarkEOLs*/ false, /*RelativeNames*/ true)) + return false; + return ExpandResponseFiles(Saver, cl::tokenizeConfigFile, Argv, + /*MarkEOLs*/ false, /*RelativeNames*/ true); +} + /// ParseEnvironmentOptions - An alternative entry point to the /// CommandLine library, which allows you to read the program's name /// from the caller (as PROGNAME) and its command-line arguments from @@ -1032,7 +1081,10 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, SmallVector<const char *, 20> newArgv(argv, argv + argc); BumpPtrAllocator A; StringSaver Saver(A); - ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv); + ExpandResponseFiles(Saver, + Triple(sys::getProcessTriple()).isOSWindows() ? + cl::TokenizeWindowsCommandLine : cl::TokenizeGNUCommandLine, + newArgv); argv = &newArgv[0]; argc = static_cast<int>(newArgv.size()); @@ -1218,8 +1270,15 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, // If this is a named positional argument, just remember that it is the // active one... - if (Handler->getFormattingFlag() == cl::Positional) + if (Handler->getFormattingFlag() == cl::Positional) { + if ((Handler->getMiscFlags() & PositionalEatsArgs) && !Value.empty()) { + Handler->error("This argument does not take a value.\n" + "\tInstead, it consumes any positional arguments until " + "the next recognized option.", *Errs); + ErrorParsing = true; + } ActivePositionalArg = Handler; + } else ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i); } @@ -1323,9 +1382,9 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, // Now that we know if -debug is specified, we can use it. // Note that if ReadResponseFiles == true, this must be done before the // memory allocated for the expanded command line is free()d below. - DEBUG(dbgs() << "Args: "; - for (int i = 0; i < argc; ++i) dbgs() << argv[i] << ' '; - dbgs() << '\n';); + LLVM_DEBUG(dbgs() << "Args: "; + for (int i = 0; i < argc; ++i) dbgs() << argv[i] << ' '; + dbgs() << '\n';); // Free all of the memory allocated to the map. Command line options may only // be processed once! @@ -1344,15 +1403,15 @@ bool CommandLineParser::ParseCommandLineOptions(int argc, // Option Base class implementation // -bool Option::error(const Twine &Message, StringRef ArgName) { +bool Option::error(const Twine &Message, StringRef ArgName, raw_ostream &Errs) { if (!ArgName.data()) ArgName = ArgStr; if (ArgName.empty()) - errs() << HelpStr; // Be nice for positional arguments + Errs << HelpStr; // Be nice for positional arguments else - errs() << GlobalParser->ProgramName << ": for the -" << ArgName; + Errs << GlobalParser->ProgramName << ": for the -" << ArgName; - errs() << " option: " << Message << "\n"; + Errs << " option: " << Message << "\n"; return true; } @@ -1422,8 +1481,12 @@ void alias::printOptionInfo(size_t GlobalWidth) const { size_t basic_parser_impl::getOptionWidth(const Option &O) const { size_t Len = O.ArgStr.size(); auto ValName = getValueName(); - if (!ValName.empty()) - Len += getValueStr(O, ValName).size() + 3; + if (!ValName.empty()) { + size_t FormattingLen = 3; + if (O.getMiscFlags() & PositionalEatsArgs) + FormattingLen = 6; + Len += getValueStr(O, ValName).size() + FormattingLen; + } return Len + 6; } @@ -1436,8 +1499,13 @@ void basic_parser_impl::printOptionInfo(const Option &O, outs() << " -" << O.ArgStr; auto ValName = getValueName(); - if (!ValName.empty()) - outs() << "=<" << getValueStr(O, ValName) << '>'; + if (!ValName.empty()) { + if (O.getMiscFlags() & PositionalEatsArgs) { + outs() << " <" << getValueStr(O, ValName) << ">..."; + } else { + outs() << "=<" << getValueStr(O, ValName) << '>'; + } + } Option::printHelpStr(O.HelpStr, GlobalWidth, getOptionWidth(O)); } |