summaryrefslogtreecommitdiff
path: root/lib/Support/CommandLine.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
commiteb11fae6d08f479c0799db45860a98af528fa6e7 (patch)
tree44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Support/CommandLine.cpp
parentb8a2042aa938069e862750553db0e4d82d25822c (diff)
Notes
Diffstat (limited to 'lib/Support/CommandLine.cpp')
-rw-r--r--lib/Support/CommandLine.cpp96
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));
}