+/// ParseCStringVector - Break INPUT up wherever one or more
+/// whitespace characters are found, and store the resulting tokens in
+/// OUTPUT. The tokens stored in OUTPUT are dynamically allocated
+/// using strdup (), so it is the caller's responsibility to free ()
+/// them later.
+///
+static void ParseCStringVector(std::vector<char *> &output,
+ const char *input) {
+ // Characters which will be treated as token separators:
+ static const char *const delims = " \v\f\t\r\n";
+
+ std::string work (input);
+ // Skip past any delims at head of input string.
+ size_t pos = work.find_first_not_of (delims);
+ // If the string consists entirely of delims, then exit early.
+ if (pos == std::string::npos) return;
+ // Otherwise, jump forward to beginning of first word.
+ work = work.substr (pos);
+ // Find position of first delimiter.
+ pos = work.find_first_of (delims);
+
+ while (!work.empty() && pos != std::string::npos) {
+ // Everything from 0 to POS is the next word to copy.
+ output.push_back (strdup (work.substr (0,pos).c_str ()));
+ // Is there another word in the string?
+ size_t nextpos = work.find_first_not_of (delims, pos + 1);
+ if (nextpos != std::string::npos) {
+ // Yes? Then remove delims from beginning ...
+ work = work.substr (work.find_first_not_of (delims, pos + 1));
+ // and find the end of the word.
+ pos = work.find_first_of (delims);
+ } else {
+ // No? (Remainder of string is delims.) End the loop.
+ work = "";
+ pos = std::string::npos;
+ }
+ }
+
+ // If `input' ended with non-delim char, then we'll get here with
+ // the last word of `input' in `work'; copy it now.
+ if (!work.empty ()) {
+ output.push_back (strdup (work.c_str ()));
+ }
+}
+
+/// 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
+/// an environment variable (whose name is given in ENVVAR).
+///
+void cl::ParseEnvironmentOptions(const char *progName, const char *envVar,
+ const char *Overview, bool ReadResponseFiles) {
+ // Check args.
+ assert(progName && "Program name not specified");
+ assert(envVar && "Environment variable name missing");
+
+ // Get the environment variable they want us to parse options out of.
+ const char *envValue = getenv(envVar);
+ if (!envValue)
+ return;
+
+ // Get program's "name", which we wouldn't know without the caller
+ // telling us.
+ std::vector<char*> newArgv;
+ newArgv.push_back(strdup(progName));
+
+ // Parse the value of the environment variable into a "command line"
+ // and hand it off to ParseCommandLineOptions().
+ ParseCStringVector(newArgv, envValue);
+ int newArgc = static_cast<int>(newArgv.size());
+ ParseCommandLineOptions(newArgc, &newArgv[0], Overview, ReadResponseFiles);
+
+ // Free all the strdup()ed strings.
+ for (std::vector<char*>::iterator i = newArgv.begin(), e = newArgv.end();
+ i != e; ++i)
+ free (*i);
+}
+
+
+/// ExpandResponseFiles - Copy the contents of argv into newArgv,
+/// substituting the contents of the response files for the arguments
+/// of type @file.
+static void ExpandResponseFiles(int argc, char** argv,
+ std::vector<char*>& newArgv) {
+ for (int i = 1; i != argc; ++i) {
+ char* arg = argv[i];
+
+ if (arg[0] == '@') {
+
+ sys::PathWithStatus respFile(++arg);
+
+ // Check that the response file is not empty (mmap'ing empty
+ // files can be problematic).
+ const sys::FileStatus *FileStat = respFile.getFileStatus();
+ if (FileStat && FileStat->getSize() != 0) {
+
+ // Mmap the response file into memory.
+ OwningPtr<MemoryBuffer>
+ respFilePtr(MemoryBuffer::getFile(respFile.c_str()));
+
+ // If we could open the file, parse its contents, otherwise
+ // pass the @file option verbatim.
+
+ // TODO: we should also support recursive loading of response files,
+ // since this is how gcc behaves. (From their man page: "The file may
+ // itself contain additional @file options; any such options will be
+ // processed recursively.")
+
+ if (respFilePtr != 0) {
+ ParseCStringVector(newArgv, respFilePtr->getBufferStart());
+ continue;
+ }
+ }
+ }
+ newArgv.push_back(strdup(arg));
+ }
+}
+
+void cl::ParseCommandLineOptions(int argc, char **argv,
+ const char *Overview, bool ReadResponseFiles) {
+ // Process all registered options.
+ std::vector<Option*> PositionalOpts;
+ std::vector<Option*> SinkOpts;
+ std::map<std::string, Option*> Opts;
+ GetOptionInfo(PositionalOpts, SinkOpts, Opts);
+
+ assert((!Opts.empty() || !PositionalOpts.empty()) &&
+ "No options specified!");
+
+ // Expand response files.
+ std::vector<char*> newArgv;
+ if (ReadResponseFiles) {
+ newArgv.push_back(strdup(argv[0]));
+ ExpandResponseFiles(argc, argv, newArgv);
+ argv = &newArgv[0];
+ argc = static_cast<int>(newArgv.size());
+ }
+
+ // Copy the program name into ProgName, making sure not to overflow it.
+ std::string ProgName = sys::Path(argv[0]).getLast();
+ if (ProgName.size() > 79) ProgName.resize(79);
+ strcpy(ProgramName, ProgName.c_str());
+